Complete OCR question image persistence - #94
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 555af3dece
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| metadata, questions, images_to_upload, unmapped, warnings = self.postprocessor.process( | ||
| text_blocks, | ||
| page_count=1, | ||
| page_dimensions={page_index: (int(image.shape[1]), int(image.shape[0]))}, |
There was a problem hiding this comment.
Transform crop coordinates back through deskewing
When default deskewing rotates a page, OCR bounding boxes are measured on processed_image, whose dimensions and origin can differ from the original raster, but this contract labels those coordinates with the original image dimensions. The backend only applies independent X/Y scaling, so it cannot undo the rotation and translation; persisted crops from skewed scans will consequently capture the wrong page region. Either map the boxes through the inverse preprocessing transform or derive regions in the original coordinate space.
Useful? React with 👍 / 👎.
| bbox = region_bbox( | ||
| question.page_index, | ||
| question.start_y, | ||
| max(question.end_y, question.start_y + 1), | ||
| ) |
There was a problem hiding this comment.
Extend question crops to include unrecognized figures
For a question whose prompt references a figure followed by an image containing no OCR text, end_y remains the bottom of the last recognized question block. Passing that value here means the generated box ends only 24 pixels below the prompt, so a typical figure placed beneath the prompt—and especially one followed immediately by the next question—is excluded from the persisted image. The region should extend to the next question boundary or otherwise include the non-text visual area.
Useful? React with 👍 / 👎.
| private boolean isRaster(OcrUploadedFile file) { | ||
| try { | ||
| return ImageIO.read(new ByteArrayInputStream(file.content())) != null; | ||
| } catch (IOException | RuntimeException error) { |
There was a problem hiding this comment.
Add WebP decoding before filtering OCR image sources
When /extract-and-persist receives an allowed WebP source, standard JDK ImageIO has no WebP reader and the backend declares no ImageIO WebP provider, so this check returns false and silently drops every OCR image candidate. This makes the new persistence behavior fail specifically for a format advertised by OcrController; decode WebP with a supported library or remove it from the persistence endpoint's accepted formats.
Useful? React with 👍 / 👎.
Summary
Completes the OCR image persistence vertical slice on top of the storage foundation from the closed PR #93.
ImageStorageport and local/S3-compatible adapters.contractVersion: 1), boundedbbox, source dimensions, page index, and source-file index.questao_Nregions from validated raster sources, stores normalized PNG objects, and associates them with the persistedQuestionImagerow.cabecalho/rodapemetadata-only until a statement-asset/PDF rendering contract exists.Explicit boundary
This PR makes automatic question-image persistence safe for raster uploads. It does not claim that PDF-rendered pages can be reconstructed by the backend, nor does it add a new statement-assets table for headers and footers. Issue #69 remains open for those follow-up cases.
Validation
./mvnw -B test: 35 tests passed.--runslow.python3 -m py_compilefor modified OCR modules: passed.git diff --check: passed.Security and operations
Replaces the closed PR #93 after the branch was renamed from the historical
agent/*name toocr-image-storage.