Files
pdfcraft/vendor/hayro
b36bdaeac6 M2: a shrunk image on a turned or mirrored page snaps to whole pixels (#5530) (#5640)
* 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>
2026-11-01 15:07:29 -05:00
..
2026-09-30 11:00:02 -04:00
2026-09-30 11:00:02 -04:00
2026-09-30 11:00:02 -04:00
2026-09-30 11:00:02 -04:00
2026-09-30 11:00:02 -04:00
2026-09-30 11:00:02 -04:00

hayro

Crates.io Documentation

A crate for rendering PDF files.

This crate allows you to render pages of a PDF file into bitmaps. It is supposed to be relatively lightweight, since we do not have any dependencies on the GPU. All the rendering happens on the CPU.

The ultimate goal of this crate is to be a feature-complete and performant PDF rasterizer. With that said, we are currently still very far away from reaching that goal: So far, no effort has been put into performance optimizations, as we are still working on implementing missing features. However, this crate is currently the most comprehensive and feature-complete implementation of a PDF rasterizer in pure Rust. This claim is supported by the fact that we currently include over 1000 PDF files in our regression test suite. The majority of those have been scraped from the pdf.js and PDFBOX test suites and therefore represent a very large and diverse sample of PDF files.

As mentioned, there are still some serious limitations, including lack of support for encrypted/password-protected PDF files, blending and isolation, knockout groups as well as a range of smaller features such as color key masking. But you should be able to render the vast majority of PDF files without too many issues.

Safety

This crate forbids unsafe code via a crate-level attribute.

Examples

For usage examples, see the example in the GitHub repository.

Cargo features

This crate has one optional feature:

  • embed-fonts: See the description of hayro-interpret for more information.

License

Licensed under either of

at your option.