mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-06 18:52:36 +00:00
* M11: JBIG2 encodes only what its decoder takes: Optimize no longer loses large images encode_jbig2 took rows of up to 2^20 samples and any number of them, while hayro-jbig2, which draws and reads these streams, takes 65,535 on a side and 2^28 samples. The optimizer doesn't read back what it stores, so with Monochrome Images on JBIG2, any 1-bit image with a side of 65,536 or more was replaced by a stream that draws nothing: 65,536 × 16 went from 37,875 dark pixels to none, and was reported as recompressed. The encoder now refuses what the decoder can't read, so such an image stays as it is. Symbol coding's limit of 2^24 rows can't be reached any more, so it goes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmsdeUCdTaD72jkDw2pJKY * M11: the JBIG2 boundary test checks a pixel It counted rows, which a page decoded blank would pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmsdeUCdTaD72jkDw2pJKY * M11: the encoder's bound on samples is MAX_JBIG2_PIXELS, the decoder's main brought decode_jbig2 and its public MAX_JBIG2_PIXELS into this crate, 2^28 like this branch's private MAX_JBIG2_SAMPLES and for the same reason. One constant now bounds both, so the encoder can't drift past what the decoder reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmsdeUCdTaD72jkDw2pJKY * M11: an image too large for JBIG2 isn't stored as JBIG2, as the notes say The parity note said such an image stays as it is. A 1-bit one does unless it is averaged, but one packed from more bits may become 1-bit Flate. The note now says it isn't stored as JBIG2 and cites an_image_too_large_for_the_jbig2_decoder_stays_as_it_is, and the optimizer README lists the bound under Not yet. MAX_JBIG2_PIXELS is the most the decoder takes, not about that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmsdeUCdTaD72jkDw2pJKY * M11: the optimizer's own size limit, and tests for what JBIG2 can't take The optimizer leaves images over 80 million pixels alone whatever the settings, and nothing said so; the README and parity note say it now, and that JBIG2's 2^28 in all is past it, so from Optimize the side bound is the one that applies. The note says what the image step does: it leaves a 1-bit image past the bound as it is unless it is averaged, and may store one packed from more bits as 1-bit Flate. what_is_too_large_for_jbig2_is_stored_another_way tests those two cases: eight-bit grey of black and white at 65,536 wide becomes 1-bit Flate, and a 1-bit image at 600 ppi averaged to 70,000 wide does too. At 65,535 and 35,000 both become JBIG2. The symbol cap's comment says why hayro-jbig2 refuses 32,768 symbols: it caps new and exported symbols together at 65,535, and a plan exports every symbol it codes. Measured: 32,767 decode, 32,768, 40,000 and 65,535 are refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmsdeUCdTaD72jkDw2pJKY * M11: the 80-million-pixel limit is the image steps', tested on both sides The README and parity note said images over 80 million pixels are left alone whatever the settings, but Clean Up still Flates an unfiltered or LZW one. They now say the image steps leave them alone, and the note cites group_4_takes_images_of_one_bit_a_pixel_up_to_the_pixel_limit for it. (The last commit said the note also gives 2^28 as past that limit; only the README does.) what_is_too_large_for_jbig2_is_stored_another_way covered the width bound only: it now runs tall images too, packed and averaged, and checks the averaged ones are one bit and half the size both ways. The older test uses the same bars() fixture, and its comment says such a stream drew nothing in PdfCraft, not that the picture was lost: Poppler and Ghostscript draw it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmsdeUCdTaD72jkDw2pJKY * M11: the JBIG2 stored at the decoder's bound reads back, and grey keeps the pixel limit - The optimize test at 65,535 on a side decoded nothing it stored: it checked the filter only, and the coding stored there is symbols, not the generic coding the filters test reads back. It now decodes the stored stream and compares it with the bars. - The README's 80-million-pixel sentence covers the colour and grey steps too, and only the 1-bit step had a test. A grey image of 10,000 × 8,000 at 600 ppi is resampled; a row more stays as it is. - The filters README names decode_jbig2_within, with its work, as main renamed decode_jbig2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmsdeUCdTaD72jkDw2pJKY * M11: the filters README names #5569's other renames too The README named decode_jbig2_within but still decode_ccitt, which #5569 made private behind decode_ccitt_within, and gave Document::decoded_image as both decoders' caller, which is test-only now: ImageBudget::decode calls them, as lib.rs's doc says. The ccitt.rs test line keeps decode_ccitt, which those tests call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmsdeUCdTaD72jkDw2pJKY --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>