From 0617b4e0f54018fbb0ad786ac3c0d0bd6a8ee9c3 Mon Sep 17 00:00:00 2001 From: Arnaud Botella Date: Wed, 21 Oct 2026 09:09:49 +0200 Subject: [PATCH] feat(RasterImage): contiguous access to all the colors colors() and modifiable_colors() expose the color storage as spans so readers and writers can process whole images without a function call per cell. Co-Authored-By: Claude Opus 5.5 --- include/geode/image/core/raster_image.hpp | 13 ++++++++++ src/geode/image/core/raster_image.cpp | 22 ++++++++++++++++ tests/image/test-raster-image.cpp | 31 +++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/include/geode/image/core/raster_image.hpp b/include/geode/image/core/raster_image.hpp index 844d78251..9d91f8139 100644 --- a/include/geode/image/core/raster_image.hpp +++ b/include/geode/image/core/raster_image.hpp @@ -23,6 +23,8 @@ #pragma once +#include + #include #include #include @@ -72,6 +74,17 @@ namespace geode void set_color( index_t index, RGBColor color ); + /*! + * All the cell colors, stored contiguously in cell index order + */ + [[nodiscard]] absl::Span< const RGBColor > colors() const; + + /*! + * All the cell colors, stored contiguously in cell index order, for + * bulk modifications + */ + [[nodiscard]] absl::Span< RGBColor > modifiable_colors(); + [[nodiscard]] RasterImage clone() const; private: diff --git a/src/geode/image/core/raster_image.cpp b/src/geode/image/core/raster_image.cpp index 117de7734..f9b6f7770 100644 --- a/src/geode/image/core/raster_image.cpp +++ b/src/geode/image/core/raster_image.cpp @@ -55,6 +55,16 @@ namespace geode colors_[index] = std::move( color ); } + [[nodiscard]] absl::Span< const RGBColor > colors() const + { + return colors_; + } + + [[nodiscard]] absl::Span< RGBColor > modifiable_colors() + { + return absl::MakeSpan( colors_ ); + } + [[nodiscard]] index_t nb_colors() const { return static_cast< index_t >( colors_.size() ); @@ -150,6 +160,18 @@ namespace geode impl_->set_color( index, std::move( color ) ); } + template < index_t dimension > + absl::Span< const RGBColor > RasterImage< dimension >::colors() const + { + return impl_->colors(); + } + + template < index_t dimension > + absl::Span< RGBColor > RasterImage< dimension >::modifiable_colors() + { + return impl_->modifiable_colors(); + } + template < index_t dimension > RasterImage< dimension > RasterImage< dimension >::clone() const { diff --git a/tests/image/test-raster-image.cpp b/tests/image/test-raster-image.cpp index a5b3e1bf0..fa2d2ffab 100644 --- a/tests/image/test-raster-image.cpp +++ b/tests/image/test-raster-image.cpp @@ -135,6 +135,36 @@ void test_extra_colors() "[TEST] Loading more colors than cells should throw" ); } +void test_colors_access() +{ + geode::RasterImage2D raster{ { 4, 3 } }; + auto colors = raster.modifiable_colors(); + geode::OpenGeodeImageException::test( colors.size() == raster.nb_cells(), + "[TEST] Wrong number of modifiable colors" ); + for( const auto i : geode::Indices{ colors } ) + { + const auto value = static_cast< geode::local_index_t >( 10 * i ); + colors[i] = { value, static_cast< geode::local_index_t >( value + 1 ), + static_cast< geode::local_index_t >( value + 2 ) }; + } + const auto& const_raster = raster; + const auto stored_colors = const_raster.colors(); + geode::OpenGeodeImageException::test( + stored_colors.size() == raster.nb_cells(), + "[TEST] Wrong number of colors" ); + for( const auto i : geode::Range{ raster.nb_cells() } ) + { + const auto value = static_cast< geode::local_index_t >( 10 * i ); + const geode::RGBColor expected{ value, + static_cast< geode::local_index_t >( value + 1 ), + static_cast< geode::local_index_t >( value + 2 ) }; + geode::OpenGeodeImageException::test( raster.color( i ) == expected, + "[TEST] Wrong color set through modifiable colors for ", i ); + geode::OpenGeodeImageException::test( + stored_colors[i] == expected, "[TEST] Wrong stored color for ", i ); + } +} + template < geode::index_t dimension > void test_io( std::array< geode::index_t, dimension > cells_number ) { @@ -190,6 +220,7 @@ void test() test_missing_colors(); test_too_many_cells(); test_extra_colors(); + test_colors_access(); auto raster2 = std::move( raster ); geode::OpenGeodeImageException::test( raster2.nb_cells() == 100, "Wrong number of cells after move" );