Commit 0a470d2daf8ec8a1ba0abfea053af4b4d0955ff6

Authored by Jay Berkenbilt
1 parent eb49e07c

Don't optimize non-8-bit images

Also add test cases for additional coverage on image optimization.
ChangeLog
1 1 2019-01-31 Jay Berkenbilt <ejb@ql.org>
2 2  
  3 + * Bug fix: do better pre-checks on images before optimizing;
  4 + refuse to optimize images that can't be converted to JPEG because
  5 + of colorspace or depth.
  6 +
3 7 * Add new options --externalize-inline-images, which converts
4 8 inline images larger than a specified size to regular images, and
5 9 --ii-min-bytes, which tweaks that size.
... ...
1   -Now
2   -===
3   -
4   -* Deal with compiler warnings
5   -
6 1 Soon
7 2 ====
8 3  
... ...
manual/qpdf-manual.xml
... ... @@ -4456,6 +4456,13 @@ print &quot;\n&quot;;
4456 4456 </listitem>
4457 4457 <listitem>
4458 4458 <para>
  4459 + When optimizing images, detect and refuse to optimize
  4460 + images that can't be converted to JPEG because of bit depth
  4461 + or color space.
  4462 + </para>
  4463 + </listitem>
  4464 + <listitem>
  4465 + <para>
4459 4466 Linearization and page manipulation APIs now detect and
4460 4467 recover from files that have duplicate Page objects in the
4461 4468 pages tree.
... ...
qpdf/qpdf.cc
... ... @@ -3816,6 +3816,18 @@ ImageOptimizer::makePipeline(std::string const&amp; description, Pipeline* next)
3816 3816 }
3817 3817 return result;
3818 3818 }
  3819 + QPDFObjectHandle components_obj = dict.getKey("/BitsPerComponent");
  3820 + if (! (components_obj.isInteger() && (components_obj.getIntValue() == 8)))
  3821 + {
  3822 + QTC::TC("qpdf", "qpdf image optimize bits per component");
  3823 + if (o.verbose && (! description.empty()))
  3824 + {
  3825 + std::cout << whoami << ": " << description
  3826 + << ": not optimizing because image has other than"
  3827 + << " 8 bits per component" << std::endl;
  3828 + }
  3829 + return result;
  3830 + }
3819 3831 // Files have been seen in the wild whose width and height are
3820 3832 // floating point, which is goofy, but we can deal with it.
3821 3833 JDIMENSION w = static_cast<JDIMENSION>(
... ... @@ -3844,6 +3856,7 @@ ImageOptimizer::makePipeline(std::string const&amp; description, Pipeline* next)
3844 3856 }
3845 3857 else
3846 3858 {
  3859 + QTC::TC("qpdf", "qpdf image optimize colorspace");
3847 3860 if (o.verbose && (! description.empty()))
3848 3861 {
3849 3862 std::cout << whoami << ": " << description
... ...
qpdf/qpdf.testcov
... ... @@ -437,3 +437,5 @@ QPDFTokenizer inline image at EOF the old way 0
437 437 QPDFTokenizer found EI after more than one try 0
438 438 QPDFPageObjectHelper externalize inline image 0
439 439 QPDFPageObjectHelper keep inline image 0
  440 +qpdf image optimize colorspace 0
  441 +qpdf image optimize bits per component 0
... ...
qpdf/qtest/qpdf.test
... ... @@ -2088,6 +2088,8 @@ my @image_opt = (
2088 2088 '--oi-min-width=0 --oi-min-height=0 --oi-min-area=0 --ii-min-bytes=0'],
2089 2089 ['large-inline-image', 'inline-images-keep-some', ''],
2090 2090 ['large-inline-image', 'inline-images-keep-all', '--keep-inline-images'],
  2091 + ['unsupported-optimization', 'unsupported',
  2092 + '--oi-min-width=0 --oi-min-height=0 --oi-min-area=0'],
2091 2093 );
2092 2094  
2093 2095 $n_tests += 2 * scalar(@image_opt);
... ...
qpdf/qtest/qpdf/optimize-images-unsupported-json.out 0 โ†’ 100644
  1 +{
  2 + "pages": [
  3 + {
  4 + "contents": [
  5 + "4 0 R"
  6 + ],
  7 + "images": [
  8 + {
  9 + "bitspercomponent": 1,
  10 + "colorspace": "/DeviceGray",
  11 + "decodeparms": [
  12 + null
  13 + ],
  14 + "filter": [
  15 + "/FlateDecode"
  16 + ],
  17 + "filterable": true,
  18 + "height": 200,
  19 + "name": "/Im1",
  20 + "object": "6 0 R",
  21 + "width": 100
  22 + },
  23 + {
  24 + "bitspercomponent": 8,
  25 + "colorspace": "/XeviceGray",
  26 + "decodeparms": [
  27 + null
  28 + ],
  29 + "filter": [
  30 + "/FlateDecode"
  31 + ],
  32 + "filterable": true,
  33 + "height": 200,
  34 + "name": "/Im2",
  35 + "object": "7 0 R",
  36 + "width": 200
  37 + }
  38 + ],
  39 + "label": null,
  40 + "object": "3 0 R",
  41 + "outlines": [],
  42 + "pageposfrom1": 1
  43 + }
  44 + ],
  45 + "parameters": {
  46 + "decodelevel": "generalized"
  47 + },
  48 + "version": 1
  49 +}
... ...
qpdf/qtest/qpdf/optimize-images-unsupported.out 0 โ†’ 100644
  1 +qpdf: image /Im1 on page 1: not optimizing because image has other than 8 bits per component
  2 +qpdf: image /Im2 on page 1: not optimizing because qpdf can't optimize images with this colorspace
  3 +qpdf: wrote file a.pdf
... ...
qpdf/qtest/qpdf/unsupported-optimization.pdf 0 โ†’ 100644
No preview for this file type