perf: stream image outputs directly into zip entries - #44
Conversation
There was a problem hiding this comment.
Pull request overview
Improves backend PDF-to-image and image-extraction tooling by writing image encodings directly into ZIP entries, reducing per-image buffering/copy overhead and lowering peak memory usage for large/high-DPI outputs.
Changes:
- Stream rendered PDF pages (
PdfToImageService) directly intoZipOutputStreamentries viaImageIO.write(...). - Stream extracted embedded images (
ExtractImagesService) directly intoZipOutputStreamentries viaImageIO.write(...). - Add explicit handling for unsupported output formats via the boolean return value of
ImageIO.write(...).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| backend/src/main/java/com/crystalpdf/backend/service/PdfToImageService.java | Streams rendered page images directly into ZIP entries instead of buffering per-page image bytes. |
| backend/src/main/java/com/crystalpdf/backend/service/ExtractImagesService.java | Streams extracted images directly into ZIP entries and adds explicit unsupported-format handling. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (!ImageIO.write(bimg, imgFormat, zos)) { | ||
| throw new IOException("Unsupported image output format: " + imgFormat); | ||
| } |
There was a problem hiding this comment.
Handled in the current branch: ExtractImagesService validates png / jpg / jpeg up front and throws IllegalArgumentException for unsupported formats, so GlobalExceptionHandler maps it to a 400. Verified with JAVA_HOME=/Users/orval/Documents/Codex/2026-07-14/generame-5-dolares-y-haz-algo/.tools/jdk-21.0.11+10/Contents/Home sh gradlew test --tests com.crystalpdf.backend.service.PdfToImageServiceTest --tests com.crystalpdf.backend.service.ExtractImagesServiceTest from backend (3/3 passed).
| ZipEntry entry = new ZipEntry(String.format("page_%03d.%s", i + 1, fmt)); | ||
| zos.putNextEntry(entry); | ||
| zos.write(imgOut.toByteArray()); | ||
| if (!ImageIO.write(image, imageioFormat, zos)) { | ||
| throw new IOException("Unsupported image output format: " + imageioFormat); | ||
| } | ||
| zos.closeEntry(); |
There was a problem hiding this comment.
Covered in PdfToImageServiceTest.convert_returnsZipWithDecodablePageImages: the test opens the returned bytes with ZipInputStream, checks the expected page_001.png / page_002.png entry names, reads each ZIP entry, and verifies ImageIO.read(...) returns a decodable image. Focused Gradle run passed 3/3.
| String entryName = String.format("page%d_img%d.%s", pageIdx + 1, imgIndex++, imgFormat); | ||
| zos.putNextEntry(new ZipEntry(entryName)); | ||
| zos.write(imgBytes.toByteArray()); | ||
| if (!ImageIO.write(bimg, imgFormat, zos)) { | ||
| throw new IOException("Unsupported image output format: " + imgFormat); | ||
| } | ||
| zos.closeEntry(); |
There was a problem hiding this comment.
Covered in ExtractImagesServiceTest: extractImages_returnsZipWithDecodableImages opens the ZIP, checks the page1_img1.png entry name, and verifies the entry decodes through ImageIO.read(...); extractImages_throwsForUnsupportedFormat locks the invalid-format behavior to IllegalArgumentException. Focused Gradle run passed 3/3.
584c39c to
af08679
Compare
|
Addressed the automated review feedback in the latest push: added service-level ZIP/image decode coverage for both PDF-to-image conversion and embedded-image extraction, and changed unsupported extract-image formats to fail as |
|
Update: I added a local Temurin 21 JDK and reran the focused backend tests. |
/claim #2
Fixes #2
What changed
Why
Large PDFs can generate many high-DPI images. Writing each image through an intermediate
ByteArrayOutputStreamamplifies peak memory usage and adds an unnecessary copy before the ZIP write. Streaming into theZipOutputStreamreduces that work for the image conversion and image extraction paths.Verification
git diff --checkJAVA_HOME=/Users/orval/Documents/Codex/2026-07-14/generame-5-dolares-y-haz-algo/.tools/jdk-21.0.11+10/Contents/Home PATH=/Users/orval/Documents/Codex/2026-07-14/generame-5-dolares-y-haz-algo/.tools/jdk-21.0.11+10/Contents/Home/bin:$PATH bash ./gradlew test --tests com.crystalpdf.backend.service.PdfToImageServiceTest --tests com.crystalpdf.backend.service.ExtractImagesServiceTestBUILD SUCCESSFUL(3 tests, 3 passed).