Repository navigation
Conversation
The output file was truncated as soon as the writer was created, so any failure (exception, full disk) left an empty or partial file and lost the previous one. The file is now written in a temporary file which replaces the output only once complete. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Colors were copied pixel by pixel through RasterImage::color() into a temporary buffer. The VTK writer can now reference external data, so the contiguous color storage is written as is, without any copy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GDAL returns the top row first for every format, but unlike the PNG, JPG and TIFF inputs the BMP input did not reverse the rows: BMP images were loaded upside down. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each band was read in its own buffer, then every pixel was copied with one RasterImage::set_color call. GDAL now writes the pixels interleaved straight into the color storage, rows reversed through a negative line spacing. Loading a 64 Mpx image goes from 1.0s to 0.47s (PNG) and from 0.70s to 0.26s (TIFF), at half the peak memory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Images with 3 or 4 bands without red/green/blue color interpretation (e.g. TIFF with MINISBLACK photometric) used band 0, which does not exist: the load crashed. The first three bands are now used, with a warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Images with 5 bands or more (e.g. multispectral TIFF) were silently loaded all black. Their red, green and blue bands, or their first three bands, are now used. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Palette images (8-bit PNG, BMP, TIFF) were loaded as grey levels of their palette indices. The RGB or grey palette colors are now used. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pixels were converted to 8-bit by GDAL with clamping: 16-bit images were loaded all white and floating point images all black. Values are now linearly rescaled from the range of the image values, nodata and NaN pixels being black. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The main file was returned as an additional file and every file was flagged as missing, although GDAL only lists existing files: any image was reported with missing additional files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Image files were opened by any GDAL driver: a VRT file named .png was loaded and could make GDAL read any other local file or URL. Image inputs now only accept the PNG, JPEG, BMP and GTiff drivers, so a misnamed image of these formats still loads. GDALFile accepts a list of allowed drivers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
is_loadable() threw on files GDAL cannot open instead of returning 0. GDAL errors were printed on stderr and missing from the exceptions, which only said the file failed to open. GDAL warnings are now logged and GDAL error messages are part of the exceptions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cpp-Linter Report
|
The image test uses the VTK writer header, which needs pugixml. When the tests are configured on their own against an installed OpenGeode-IO, the pugixml target was not defined. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
Review of the image library, focused on robustness and performance. One commit per fix, each one with a test that fails before it.
Depends on
RasterImage::colors()/modifiable_colors()fix/vtk-output-robustness, which already rewrites the VTK writer. Retarget tonextonce fix(VTKOutput): precision, overflow and I/O error handling in writers #219 is merged.Robustness
fix(VTKOutput): write to a temporary file, then rename/dev/fullare still written directly.fix(BMPInput): same row order as the other formatsfix(ImageInput): bands not tagged as RGBfix(ImageInput): more than four bandsfix(ImageInput): palette imagesfix(ImageInput): 16-bit and floating point imagesfix(GDALFile): additional filesfix(ImageInput): image drivers only.pngwas followed to arbitrary files or URLs. Now only PNG, JPEG, BMP and GTiff are accepted, so misnamed images still load.fix(ImageInput): GDAL errorsis_loadable()threw on unreadable files. GDAL errors went to stderr and were missing from the exceptions.Performance (64 Mpx RGB image, compared with
next)perf(ImageInput): GDAL decodes straight into the raster color storage, rows reversed through a negative line spacing. Previously there was one buffer per band plus oneset_colorcall per pixel. Peak memory is halved.perf(VTIRasterImageOutput): the color storage is written as is, with no copy.Tests
New 4×3 test images in
tests/data/image_*, checked pixel by pixel intest-raster-image. All OpenGeode-IO tests pass locally.🤖 Generated with Claude Code