mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-03 06:51:50 -06:00
* M2: a shrunk image on a turned or mirrored page snaps to whole pixels (#5530) hayro patch 14 (`snap_minified_image`) shrinks an interpolated image once to its whole-pixel device rectangle and draws that 1:1, instead of shrinking to a rounded-up size and resampling again at a fractional scale and offset. It only accepted an upright transform (a > 0, d > 0, b = c = 0), so every image on a page under /Rotate 90, 180 or 270 -- and any image placed turned or mirrored by its own matrix -- still took the double resample. That is #5530: a scanned page that matches PDFium upright drifts and softens when the same page is rotated. The snap now accepts every transform whose axes lie along the device's (the eight quarter-turns and mirrors) and returns the 1:1 transform that draws the shrunk raster from the snapped corner, one source-axis step a whole device pixel, in whichever direction that axis runs. Skewed and freely rotated images keep the old path. On a synthetic page (crop box and scale on whole pixels, image at fractional coordinates), /Rotate 90, 180 and 270 renders turned back differed from the upright render in 72% of pixels, by up to 200 grey levels; now they are identical. Non-interpolated images were already identical and stay so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * M2: snap only when the dropped skew is invisible, and only a resize that succeeded Review of #5640: - The snap judged an image axis-aligned by a tolerance on its coefficients (1e-4 of the scale). For a very wide image a skew that small still moves the far edge by more than a pixel (40 000 samples at 4e-5: 1.6 px), and the snap flattened it. It now measures what it drops: how far each off-axis term moves the far edges, at most a hundredth of a device pixel (SNAP_SKEW). Upright and turned alike. - A resize that fails hands back the source raster at source size; the 1:1 snapped transform then drew it at that size. The snapped transform is now used only when the shrink produced the snapped size; otherwise the full transform, as before. - The mirrored case of the edge test drew a uniform image, which looks the same mirrored; it now also mirrors a half-black image and checks which side the black lands on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * M2: the turned-page test draws every kind of image the snap reaches The /Rotate oracle test drew one 8-bit grey image. Stencil masks (CCITT scans often are one), 1-bit images and images with a soft mask reach the snap through other paths, so it now draws all five: 8-bit and 1-bit grey, a stencil mask, a soft mask of the image's size and one of another size. On main, every interpolated kind is off by 113-217 levels over 63-73% of the image when turned, and so is a non-interpolated image with a smaller soft mask (110 levels, 16%): hayro patch 15 filters such a mask whatever /Interpolate says, so it is snapped upright and was not when turned. All are identical with the fix; the other non-interpolated kinds were already identical and stay as guards. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>