mirror of
https://pdfium.googlesource.com/pdfium
synced 2026-08-02 05:04:39 +08:00
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5cebac774c |
Reland "Decode JPEGs at reduced size via libjpeg scale_denom"
This is a reland of commit 009b91d9d95d998fa7e8e09c55f716cb42d99546 Original change's description: > Decode JPEGs at reduced size via libjpeg scale_denom > > JPEGs store image data in 8x8 DCT tiles in the frequency domain. To > restore an 8x8 tile in the image domain, an IDCT is computed, using up > to 64 coefficients. > > If a JPEG with large dimensions is drawn at small scale on screen, > pdfium used to completely decompress the JPEG to large size, doing a > full IDCT for each tile, and then scale it down at decode time. > > Using scale_denom, pdfium can instead decode the image at 1/8th (or > 1/4th, 1/2th) its size (in each dimension) by not doing the full IDCT, > but instead only taking the one DC term (for 1/8th), or 2x2 or 4x4 > coefficents (for 1/4th, 1/2th). > > This not just saves work decoding the image, it also outputs a smaller > image that is faster to downsample when painting it. For most images, > this shouldn't look perceptively different than downsampling from the > large bitmap. > > This kind of matches what Blink does when decoding JPEGs [1], and > morally matches what pdfium already does for JPEG2000s after > https://pdfium-review.googlesource.com/c/pdfium/+/99970. > > (Note that CPDF_ImageRenderer::StartLoadDIBBase() in > cpdf_imagerenderer.cpp passes in the page size as max_size_required, > which cpdf_dib.cpp uses to compute resolution_levels_to_skip. So image > decoding currently isn't limited to the size the image is drawn at, but > by the size of the bitmap the whole page is drawn at. This can be be > improved later.) > > Depending on what data the encoder writes in padding rows / columns for > images that aren't a multiple of the MCU size, the code might produce > artifacts in the last row or column. So only do this for images with > sizes a multiple of the MCU for now, see also https://crbug.com/890745 > and the discussion on > https://github.com/libjpeg-turbo/libjpeg-turbo/issues/297. This is > unfortunate, but currently there's no way to do better without hacks. > (This also matches what Blink does.) > > Timing (hyperfine, --render-repeats): a 3072x2304 4:4:4 image drawn onto > a 64pt page decodes in 40ms at scale_denom 8 vs 84ms at full resolution. > > 1: > https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc;l=430 > ...but evidently this is much harder to hit now then when that code was > initially added, probably because JPEGs in Chrome now go down the > DecodeYUV path, which doesn't set scale_denom (yet?). > > Depends on new baseline in > https://pdfium-review.googlesource.com/c/pdfium_tests/+/151570 > and updates DEPS to pick it up. > > Plumb the existing resolution_levels_to_skip (computed in > CPDF_DIB::StartLoadDIBBase from the render device size) into the DCT > path. CreateDCTDecoder maps it to a libjpeg scale_denom of 1/2/4/8 > (capped at 8, the largest power-of-two DCT scaling libjpeg supports) and > passes it to JpegModule::CreateDecoder. JpegDecoder sets > cinfo.scale_denom before jpeg_start_decompress and reports the > scaled-down output dimensions (ceil(dim/scale_denom), matching > jpeg_core_output_dimensions). The DIB then adopts the decoder's reduced > dimensions, mirroring the JPX path. libjpeg performs the reduction > cheaply inside the IDCT (e.g. 1/8 uses a 1x1 IDCT), so far fewer pixels > are produced for images shown much smaller than native. > > The calls to SetWidth()/SetHeight() are a slight behavior change for all > JPEG data for invalid files: Previously, the code used width/height from > the PDF dict, now it gets the size from the decoder. These sizes are > supposed to match, but if they aren't, pdfium now uses the other one. > This is arguably better, as that size dictates how much data is actually > present. > > Bug: 531782505 > Change-Id: I66409898d028685813b274e063aedf52200be0dd > Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/151550 > Commit-Queue: Nico Weber <thakis@chromium.org> > Reviewed-by: Lei Zhang <thestig@chromium.org> > Reviewed-by: Nico Weber <thakis@google.com> Bug: 531782505 Change-Id: I42c141839a21c77855b06caded3c79db2e53ed50 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/151930 Commit-Queue: Nico Weber <thakis@chromium.org> Reviewed-by: Nico Weber <thakis@google.com> Reviewed-by: Lei Zhang <thestig@chromium.org> |
||
|
|
fb09d84c50 |
Revert "Decode JPEGs at reduced size via libjpeg scale_denom"
This reverts commit 009b91d9d95d998fa7e8e09c55f716cb42d99546. Reason for revert: Signifincantly slows down rendering in some cases. Failure Link: https://ci.chromium.org/ui/p/chromium/builders/ci/win11-arm64-dbg-tests/12279/overview Original change's description: > Decode JPEGs at reduced size via libjpeg scale_denom > > JPEGs store image data in 8x8 DCT tiles in the frequency domain. To > restore an 8x8 tile in the image domain, an IDCT is computed, using up > to 64 coefficients. > > If a JPEG with large dimensions is drawn at small scale on screen, > pdfium used to completely decompress the JPEG to large size, doing a > full IDCT for each tile, and then scale it down at decode time. > > Using scale_denom, pdfium can instead decode the image at 1/8th (or > 1/4th, 1/2th) its size (in each dimension) by not doing the full IDCT, > but instead only taking the one DC term (for 1/8th), or 2x2 or 4x4 > coefficents (for 1/4th, 1/2th). > > This not just saves work decoding the image, it also outputs a smaller > image that is faster to downsample when painting it. For most images, > this shouldn't look perceptively different than downsampling from the > large bitmap. > > This kind of matches what Blink does when decoding JPEGs [1], and > morally matches what pdfium already does for JPEG2000s after > https://pdfium-review.googlesource.com/c/pdfium/+/99970. > > (Note that CPDF_ImageRenderer::StartLoadDIBBase() in > cpdf_imagerenderer.cpp passes in the page size as max_size_required, > which cpdf_dib.cpp uses to compute resolution_levels_to_skip. So image > decoding currently isn't limited to the size the image is drawn at, but > by the size of the bitmap the whole page is drawn at. This can be be > improved later.) > > Depending on what data the encoder writes in padding rows / columns for > images that aren't a multiple of the MCU size, the code might produce > artifacts in the last row or column. So only do this for images with > sizes a multiple of the MCU for now, see also https://crbug.com/890745 > and the discussion on > https://github.com/libjpeg-turbo/libjpeg-turbo/issues/297. This is > unfortunate, but currently there's no way to do better without hacks. > (This also matches what Blink does.) > > Timing (hyperfine, --render-repeats): a 3072x2304 4:4:4 image drawn onto > a 64pt page decodes in 40ms at scale_denom 8 vs 84ms at full resolution. > > 1: > https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc;l=430 > ...but evidently this is much harder to hit now then when that code was > initially added, probably because JPEGs in Chrome now go down the > DecodeYUV path, which doesn't set scale_denom (yet?). > > Depends on new baseline in > https://pdfium-review.googlesource.com/c/pdfium_tests/+/151570 > and updates DEPS to pick it up. > > Plumb the existing resolution_levels_to_skip (computed in > CPDF_DIB::StartLoadDIBBase from the render device size) into the DCT > path. CreateDCTDecoder maps it to a libjpeg scale_denom of 1/2/4/8 > (capped at 8, the largest power-of-two DCT scaling libjpeg supports) and > passes it to JpegModule::CreateDecoder. JpegDecoder sets > cinfo.scale_denom before jpeg_start_decompress and reports the > scaled-down output dimensions (ceil(dim/scale_denom), matching > jpeg_core_output_dimensions). The DIB then adopts the decoder's reduced > dimensions, mirroring the JPX path. libjpeg performs the reduction > cheaply inside the IDCT (e.g. 1/8 uses a 1x1 IDCT), so far fewer pixels > are produced for images shown much smaller than native. > > The calls to SetWidth()/SetHeight() are a slight behavior change for all > JPEG data for invalid files: Previously, the code used width/height from > the PDF dict, now it gets the size from the decoder. These sizes are > supposed to match, but if they aren't, pdfium now uses the other one. > This is arguably better, as that size dictates how much data is actually > present. > > Bug: 531782505 > Change-Id: I66409898d028685813b274e063aedf52200be0dd > Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/151550 > Commit-Queue: Nico Weber <thakis@chromium.org> > Reviewed-by: Lei Zhang <thestig@chromium.org> > Reviewed-by: Nico Weber <thakis@google.com> # Not skipping CQ checks because original CL landed > 1 day ago. Bug: 531782505 Change-Id: If8fa628779381543e6243b75b0b07e26ae87ac12 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/151870 Reviewed-by: Lei Zhang <thestig@chromium.org> Commit-Queue: Lei Zhang <thestig@chromium.org> Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com> |
||
|
|
009b91d9d9 |
Decode JPEGs at reduced size via libjpeg scale_denom
JPEGs store image data in 8x8 DCT tiles in the frequency domain. To restore an 8x8 tile in the image domain, an IDCT is computed, using up to 64 coefficients. If a JPEG with large dimensions is drawn at small scale on screen, pdfium used to completely decompress the JPEG to large size, doing a full IDCT for each tile, and then scale it down at decode time. Using scale_denom, pdfium can instead decode the image at 1/8th (or 1/4th, 1/2th) its size (in each dimension) by not doing the full IDCT, but instead only taking the one DC term (for 1/8th), or 2x2 or 4x4 coefficents (for 1/4th, 1/2th). This not just saves work decoding the image, it also outputs a smaller image that is faster to downsample when painting it. For most images, this shouldn't look perceptively different than downsampling from the large bitmap. This kind of matches what Blink does when decoding JPEGs [1], and morally matches what pdfium already does for JPEG2000s after https://pdfium-review.googlesource.com/c/pdfium/+/99970. (Note that CPDF_ImageRenderer::StartLoadDIBBase() in cpdf_imagerenderer.cpp passes in the page size as max_size_required, which cpdf_dib.cpp uses to compute resolution_levels_to_skip. So image decoding currently isn't limited to the size the image is drawn at, but by the size of the bitmap the whole page is drawn at. This can be be improved later.) Depending on what data the encoder writes in padding rows / columns for images that aren't a multiple of the MCU size, the code might produce artifacts in the last row or column. So only do this for images with sizes a multiple of the MCU for now, see also https://crbug.com/890745 and the discussion on https://github.com/libjpeg-turbo/libjpeg-turbo/issues/297. This is unfortunate, but currently there's no way to do better without hacks. (This also matches what Blink does.) Timing (hyperfine, --render-repeats): a 3072x2304 4:4:4 image drawn onto a 64pt page decodes in 40ms at scale_denom 8 vs 84ms at full resolution. 1: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc;l=430 ...but evidently this is much harder to hit now then when that code was initially added, probably because JPEGs in Chrome now go down the DecodeYUV path, which doesn't set scale_denom (yet?). Depends on new baseline in https://pdfium-review.googlesource.com/c/pdfium_tests/+/151570 and updates DEPS to pick it up. Plumb the existing resolution_levels_to_skip (computed in CPDF_DIB::StartLoadDIBBase from the render device size) into the DCT path. CreateDCTDecoder maps it to a libjpeg scale_denom of 1/2/4/8 (capped at 8, the largest power-of-two DCT scaling libjpeg supports) and passes it to JpegModule::CreateDecoder. JpegDecoder sets cinfo.scale_denom before jpeg_start_decompress and reports the scaled-down output dimensions (ceil(dim/scale_denom), matching jpeg_core_output_dimensions). The DIB then adopts the decoder's reduced dimensions, mirroring the JPX path. libjpeg performs the reduction cheaply inside the IDCT (e.g. 1/8 uses a 1x1 IDCT), so far fewer pixels are produced for images shown much smaller than native. The calls to SetWidth()/SetHeight() are a slight behavior change for all JPEG data for invalid files: Previously, the code used width/height from the PDF dict, now it gets the size from the decoder. These sizes are supposed to match, but if they aren't, pdfium now uses the other one. This is arguably better, as that size dictates how much data is actually present. Bug: 531782505 Change-Id: I66409898d028685813b274e063aedf52200be0dd Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/151550 Commit-Queue: Nico Weber <thakis@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org> Reviewed-by: Nico Weber <thakis@google.com> |