tiff io: avoid over-allocation + add more tests
This commit is contained in:
parent
dc1ed0ae29
commit
fcf71c36d9
2 changed files with 60 additions and 4 deletions
|
@ -136,6 +136,8 @@ private:
|
|||
unsigned photometric_;
|
||||
unsigned bands_;
|
||||
bool is_tiled_;
|
||||
unsigned planar_config_;
|
||||
unsigned compression_;
|
||||
|
||||
public:
|
||||
enum TiffType {
|
||||
|
@ -158,6 +160,9 @@ public:
|
|||
bool is_tiled() const { return is_tiled_; }
|
||||
unsigned tile_width() const { return tile_width_; }
|
||||
unsigned tile_height() const { return tile_height_; }
|
||||
unsigned rows_per_strip() const { return rows_per_strip_; }
|
||||
unsigned planar_config() const { return planar_config_; }
|
||||
unsigned compression() const { return compression_; }
|
||||
private:
|
||||
tiff_reader(const tiff_reader&);
|
||||
tiff_reader& operator=(const tiff_reader&);
|
||||
|
@ -207,7 +212,9 @@ tiff_reader<T>::tiff_reader(std::string const& file_name)
|
|||
bps_(0),
|
||||
photometric_(0),
|
||||
bands_(1),
|
||||
is_tiled_(false)
|
||||
is_tiled_(false),
|
||||
planar_config_(PLANARCONFIG_CONTIG),
|
||||
compression_(COMPRESSION_NONE)
|
||||
{
|
||||
if (!stream_) throw image_reader_exception("TIFF reader: cannot open file "+ file_name);
|
||||
init();
|
||||
|
@ -228,7 +235,9 @@ tiff_reader<T>::tiff_reader(char const* data, std::size_t size)
|
|||
bps_(0),
|
||||
photometric_(0),
|
||||
bands_(1),
|
||||
is_tiled_(false)
|
||||
is_tiled_(false),
|
||||
planar_config_(PLANARCONFIG_CONTIG),
|
||||
compression_(COMPRESSION_NONE)
|
||||
{
|
||||
if (!stream_) throw image_reader_exception("TIFF reader: cannot open image stream ");
|
||||
stream_.seekg(0, std::ios::beg);
|
||||
|
@ -257,6 +266,15 @@ void tiff_reader<T>::init()
|
|||
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width_);
|
||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height_);
|
||||
|
||||
if (width_ > 10000 || height_ > 10000)
|
||||
{
|
||||
throw image_reader_exception("Can't allocate tiff > 10000x10000");
|
||||
}
|
||||
|
||||
TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar_config_);
|
||||
TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression_ );
|
||||
TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rows_per_strip_);
|
||||
|
||||
std::uint16_t orientation;
|
||||
if (TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation) == 0)
|
||||
{
|
||||
|
@ -273,7 +291,7 @@ void tiff_reader<T>::init()
|
|||
MAPNIK_LOG_DEBUG(tiff_reader) << "reading tiled tiff";
|
||||
read_method_ = tiled;
|
||||
}
|
||||
else if (TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rows_per_strip_)!=0)
|
||||
else if (rows_per_strip_ > 0)
|
||||
{
|
||||
MAPNIK_LOG_DEBUG(tiff_reader) << "reading striped tiff";
|
||||
read_method_ = stripped;
|
||||
|
@ -291,6 +309,23 @@ void tiff_reader<T>::init()
|
|||
premultiplied_alpha_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_tiled_ &&
|
||||
compression_ == COMPRESSION_NONE &&
|
||||
planar_config_ == PLANARCONFIG_CONTIG)
|
||||
{
|
||||
if (height_ > 128 * 1024 * 1024)
|
||||
{
|
||||
std::size_t line_size = (bands_ * width_ * bps_ + 7) / 8;
|
||||
std::size_t default_strip_height = 8192 / line_size;
|
||||
if (default_strip_height == 0) default_strip_height = 1;
|
||||
std::size_t num_strips = height_ / default_strip_height;
|
||||
if (num_strips > 128 * 1024 * 1024)
|
||||
{
|
||||
throw image_reader_exception("Can't allocate tiff");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -606,7 +641,7 @@ void tiff_reader<T>::read_stripped(unsigned x0,unsigned y0,image_data_rgba8& ima
|
|||
|
||||
if (!TIFFReadRGBAStrip(tif,y,buf.get()))
|
||||
{
|
||||
std::clog << "TIFFReadRGBAStrip failed";
|
||||
std::clog << "TIFFReadRGBAStrip failed at " << y << " for " << width_ << "/" << height_ << "\n";
|
||||
break;
|
||||
}
|
||||
row=y+ty0-y0;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
mapnik::tiff_reader<boost::iostreams::file_source> tiff_reader(filename); \
|
||||
REQUIRE( tiff_reader.width() == 256 ); \
|
||||
REQUIRE( tiff_reader.height() == 256 ); \
|
||||
REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); \
|
||||
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff")); \
|
||||
REQUIRE( reader->width() == 256 ); \
|
||||
REQUIRE( reader->height() == 256 ); \
|
||||
|
@ -54,11 +55,13 @@ TEST_CASE("tiff io") {
|
|||
|
||||
SECTION("rgba8 striped") {
|
||||
TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_rgba8_striped.tif")
|
||||
REQUIRE( tiff_reader.rows_per_strip() == 1 );
|
||||
REQUIRE( tiff_reader.bits_per_sample() == 8 );
|
||||
REQUIRE( tiff_reader.is_tiled() == false );
|
||||
REQUIRE( tiff_reader.tile_width() == 0 );
|
||||
REQUIRE( tiff_reader.tile_height() == 0 );
|
||||
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
|
||||
REQUIRE( tiff_reader.compression() == COMPRESSION_ADOBE_DEFLATE );
|
||||
mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height());
|
||||
REQUIRE( data.is<mapnik::image_data_rgba8>() == true );
|
||||
TIFF_ASSERT_SIZE( data,reader );
|
||||
|
@ -68,11 +71,13 @@ SECTION("rgba8 striped") {
|
|||
|
||||
SECTION("rgba8 tiled") {
|
||||
TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_rgba8_tiled.tif")
|
||||
REQUIRE( tiff_reader.rows_per_strip() == 0 );
|
||||
REQUIRE( tiff_reader.bits_per_sample() == 8 );
|
||||
REQUIRE( tiff_reader.is_tiled() == true );
|
||||
REQUIRE( tiff_reader.tile_width() == 256 );
|
||||
REQUIRE( tiff_reader.tile_height() == 256 );
|
||||
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
|
||||
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
|
||||
mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height());
|
||||
REQUIRE( data.is<mapnik::image_data_rgba8>() == true );
|
||||
TIFF_ASSERT_SIZE( data,reader );
|
||||
|
@ -82,11 +87,13 @@ SECTION("rgba8 tiled") {
|
|||
|
||||
SECTION("rgb8 striped") {
|
||||
TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_rgb8_striped.tif")
|
||||
REQUIRE( tiff_reader.rows_per_strip() == 10 );
|
||||
REQUIRE( tiff_reader.bits_per_sample() == 8 );
|
||||
REQUIRE( tiff_reader.is_tiled() == false );
|
||||
REQUIRE( tiff_reader.tile_width() == 0 );
|
||||
REQUIRE( tiff_reader.tile_height() == 0 );
|
||||
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
|
||||
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
|
||||
mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height());
|
||||
REQUIRE( data.is<mapnik::image_data_rgba8>() == true );
|
||||
TIFF_ASSERT_SIZE( data,reader );
|
||||
|
@ -96,11 +103,13 @@ SECTION("rgb8 striped") {
|
|||
|
||||
SECTION("rgb8 tiled") {
|
||||
TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_rgb8_tiled.tif")
|
||||
REQUIRE( tiff_reader.rows_per_strip() == 0 );
|
||||
REQUIRE( tiff_reader.bits_per_sample() == 8 );
|
||||
REQUIRE( tiff_reader.is_tiled() == true );
|
||||
REQUIRE( tiff_reader.tile_width() == 256 );
|
||||
REQUIRE( tiff_reader.tile_height() == 256 );
|
||||
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
|
||||
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
|
||||
mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height());
|
||||
REQUIRE( data.is<mapnik::image_data_rgba8>() == true );
|
||||
TIFF_ASSERT_SIZE( data,reader );
|
||||
|
@ -110,11 +119,13 @@ SECTION("rgb8 tiled") {
|
|||
|
||||
SECTION("gray8 striped") {
|
||||
TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_gray8_striped.tif")
|
||||
REQUIRE( tiff_reader.rows_per_strip() == 32 );
|
||||
REQUIRE( tiff_reader.bits_per_sample() == 8 );
|
||||
REQUIRE( tiff_reader.is_tiled() == false );
|
||||
REQUIRE( tiff_reader.tile_width() == 0 );
|
||||
REQUIRE( tiff_reader.tile_height() == 0 );
|
||||
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
|
||||
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
|
||||
mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height());
|
||||
REQUIRE( data.is<mapnik::image_data_gray8>() == true );
|
||||
TIFF_ASSERT_SIZE( data,reader );
|
||||
|
@ -124,11 +135,13 @@ SECTION("gray8 striped") {
|
|||
|
||||
SECTION("gray8 tiled") {
|
||||
TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_gray8_tiled.tif")
|
||||
REQUIRE( tiff_reader.rows_per_strip() == 0 );
|
||||
REQUIRE( tiff_reader.bits_per_sample() == 8 );
|
||||
REQUIRE( tiff_reader.is_tiled() == true );
|
||||
REQUIRE( tiff_reader.tile_width() == 256 );
|
||||
REQUIRE( tiff_reader.tile_height() == 256 );
|
||||
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
|
||||
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
|
||||
mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height());
|
||||
REQUIRE( data.is<mapnik::image_data_gray8>() == true );
|
||||
TIFF_ASSERT_SIZE( data,reader );
|
||||
|
@ -138,11 +151,13 @@ SECTION("gray8 tiled") {
|
|||
|
||||
SECTION("gray16 striped") {
|
||||
TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_gray16_striped.tif")
|
||||
REQUIRE( tiff_reader.rows_per_strip() == 16 );
|
||||
REQUIRE( tiff_reader.bits_per_sample() == 16 );
|
||||
REQUIRE( tiff_reader.is_tiled() == false );
|
||||
REQUIRE( tiff_reader.tile_width() == 0 );
|
||||
REQUIRE( tiff_reader.tile_height() == 0 );
|
||||
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
|
||||
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
|
||||
mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height());
|
||||
REQUIRE( data.is<mapnik::image_data_gray16>() == true );
|
||||
TIFF_ASSERT_SIZE( data,reader );
|
||||
|
@ -152,11 +167,13 @@ SECTION("gray16 striped") {
|
|||
|
||||
SECTION("gray16 tiled") {
|
||||
TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_gray16_tiled.tif")
|
||||
REQUIRE( tiff_reader.rows_per_strip() == 0 );
|
||||
REQUIRE( tiff_reader.bits_per_sample() == 16 );
|
||||
REQUIRE( tiff_reader.is_tiled() == true );
|
||||
REQUIRE( tiff_reader.tile_width() == 256 );
|
||||
REQUIRE( tiff_reader.tile_height() == 256 );
|
||||
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
|
||||
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
|
||||
mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height());
|
||||
REQUIRE( data.is<mapnik::image_data_gray16>() == true );
|
||||
TIFF_ASSERT_SIZE( data,reader );
|
||||
|
@ -166,11 +183,13 @@ SECTION("gray16 tiled") {
|
|||
|
||||
SECTION("gray32f striped") {
|
||||
TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_gray32f_striped.tif")
|
||||
REQUIRE( tiff_reader.rows_per_strip() == 8 );
|
||||
REQUIRE( tiff_reader.bits_per_sample() == 32 );
|
||||
REQUIRE( tiff_reader.is_tiled() == false );
|
||||
REQUIRE( tiff_reader.tile_width() == 0 );
|
||||
REQUIRE( tiff_reader.tile_height() == 0 );
|
||||
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
|
||||
REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
|
||||
mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height());
|
||||
REQUIRE( data.is<mapnik::image_data_gray32f>() == true );
|
||||
TIFF_ASSERT_SIZE( data,reader );
|
||||
|
@ -180,11 +199,13 @@ SECTION("gray32f striped") {
|
|||
|
||||
SECTION("gray32f tiled") {
|
||||
TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_gray32f_tiled.tif")
|
||||
REQUIRE( tiff_reader.rows_per_strip() == 0 );
|
||||
REQUIRE( tiff_reader.bits_per_sample() == 32 );
|
||||
REQUIRE( tiff_reader.is_tiled() == true );
|
||||
REQUIRE( tiff_reader.tile_width() == 256 );
|
||||
REQUIRE( tiff_reader.tile_height() == 256 );
|
||||
REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
|
||||
REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
|
||||
mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height());
|
||||
REQUIRE( data.is<mapnik::image_data_gray32f>() == true );
|
||||
TIFF_ASSERT_SIZE( data,reader );
|
||||
|
|
Loading…
Reference in a new issue