pdfium/testing/resources/jpeg_reduced_size_with_smask.pdf
Nico Weber 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>
2026-07-13 14:54:20 -07:00

39 KiB