Skip to content

Commit

Permalink
Merge pull request #155 from Geode-solutions/feat/import_tiff
Browse files Browse the repository at this point in the history
Feat/import tiff
  • Loading branch information
MelchiorSchuh authored Feb 7, 2025
2 parents a997abe + b5facc1 commit a5a6372
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 4 deletions.
56 changes: 56 additions & 0 deletions include/geode/io/image/internal/tiff_input.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2019 - 2025 Geode-solutions
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/

#pragma once

#include <geode/image/io/raster_image_input.hpp>

namespace geode
{
FORWARD_DECLARATION_DIMENSION_CLASS( RasterImage );
ALIAS_2D( RasterImage );
} // namespace geode

namespace geode
{
namespace internal
{
class TIFFInput final : public RasterImageInput< 2 >
{
public:
explicit TIFFInput( std::string_view filename )
: RasterImageInput< 2 >( filename )
{
}

static std::vector< std::string > extensions()
{
static const std::vector< std::string > extensions{ "tiff",
"tif" };
return extensions;
}

RasterImage2D read() final;
};
} // namespace internal
} // namespace geode
2 changes: 2 additions & 0 deletions src/geode/io/image/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ add_geode_library(
"jpg_input.cpp"
"png_input.cpp"
"raster_image_input.cpp"
"tiff_input.cpp"
"vti_raster_image_output.cpp"
PUBLIC_HEADERS
"common.hpp"
Expand All @@ -39,6 +40,7 @@ add_geode_library(
"internal/jpg_input.hpp"
"internal/png_input.hpp"
"internal/raster_image_input.hpp"
"internal/tiff_input.hpp"
PUBLIC_DEPENDENCIES
OpenGeode::image
PRIVATE_DEPENDENCIES
Expand Down
7 changes: 7 additions & 0 deletions src/geode/io/image/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <geode/io/image/internal/bmp_input.hpp>
#include <geode/io/image/internal/jpg_input.hpp>
#include <geode/io/image/internal/png_input.hpp>
#include <geode/io/image/internal/tiff_input.hpp>

namespace
{
Expand All @@ -48,6 +49,12 @@ namespace
geode::RasterImageInputFactory2D::register_creator<
geode::internal::BMPInput >(
geode::internal::BMPInput::extension().data() );

for( const auto& tif_ext : geode::internal::TIFFInput::extensions() )
{
geode::RasterImageInputFactory2D::register_creator<
geode::internal::TIFFInput >( tif_ext );
}
}

void register_raster_output()
Expand Down
36 changes: 33 additions & 3 deletions src/geode/io/image/raster_image_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,32 @@ namespace
"[ImageInputImpl] Failed to read color component" );
return values;
}
std::array< geode::index_t, 3 > get_rgb_indices(
GDALDatasetUniquePtr& gdal_data )
{
std::array< geode::index_t, 3 > rgb_indices{ 0, 0, 0 };
const auto nb_color_components =
static_cast< geode::index_t >( gdal_data->GetRasterCount() );
for( const auto id : geode::Range( nb_color_components ) )
{
const auto band_id = id + 1;
GDALColorInterp colorInterp =
gdal_data->GetRasterBand( band_id )->GetColorInterpretation();
if( colorInterp == GCI_RedBand )
{
rgb_indices[0] = band_id;
}
else if( colorInterp == GCI_GreenBand )
{
rgb_indices[1] = band_id;
}
else if( colorInterp == GCI_BlueBand )
{
rgb_indices[2] = band_id;
}
}
return rgb_indices;
}

template < typename SpecificRange >
geode::RasterImage2D read_file( std::string_view filename )
Expand Down Expand Up @@ -83,9 +109,13 @@ namespace
}
else if( nb_color_components <= 4 )
{
const auto red = read_color_component( raster, gdal_data, 1 );
const auto green = read_color_component( raster, gdal_data, 2 );
const auto blue = read_color_component( raster, gdal_data, 3 );
const auto rgb_indices = get_rgb_indices( gdal_data );
const auto red =
read_color_component( raster, gdal_data, rgb_indices[0] );
const auto green =
read_color_component( raster, gdal_data, rgb_indices[1] );
const auto blue =
read_color_component( raster, gdal_data, rgb_indices[2] );
geode::index_t cell{ 0 };
for( const auto image_j :
SpecificRange{ raster.nb_cells_in_direction( 1 ) } )
Expand Down
40 changes: 40 additions & 0 deletions src/geode/io/image/tiff_input.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2019 - 2025 Geode-solutions
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/

#include <geode/io/image/internal/tiff_input.hpp>

#include <geode/image/core/raster_image.hpp>

#include <geode/io/image/internal/raster_image_input.hpp>

namespace geode
{
namespace internal
{
RasterImage2D TIFFInput::read()
{
ImageInputImpl reader{ filename() };
return reader.read_reversed_y_axis_file();
}
} // namespace internal
} // namespace geode
Binary file added tests/data/cea.og_img2d
Binary file not shown.
Binary file added tests/data/cea.tiff
Binary file not shown.
21 changes: 20 additions & 1 deletion tests/image/test-raster-image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,25 @@ void test_png_input()
geode::save_raster_image( raster, "test_grid_output_from_png.vti" );
}

void test_tiff_input()
{
auto raster = geode::load_raster_image< 2 >(
absl::StrCat( geode::DATA_PATH, "cea.tiff" ) );
auto ref_raster = geode::load_raster_image< 2 >(
absl::StrCat( geode::DATA_PATH, "cea.og_img2d" ) );
OPENGEODE_EXCEPTION( raster.nb_cells() == ref_raster.nb_cells(),
"[TEST] Wrong number of cells." );
for( const auto cell_id : geode::Range{ ref_raster.nb_cells() } )
{
OPENGEODE_EXCEPTION(
raster.color( cell_id ) == ref_raster.color( cell_id ),
"[TEST] Wrong color value for pixel ", cell_id,
" on image loaded from reference pixel." );
}

geode::save_raster_image( raster, "cea.vti" );
}

int main()
{
try
Expand All @@ -116,7 +135,7 @@ int main()
test_jpg_from_gimp_input();
test_jpg_from_paraview_input();
test_png_input();

test_tiff_input();
geode::Logger::info( "TEST SUCCESS" );
return 0;
}
Expand Down

0 comments on commit a5a6372

Please # to comment.