From efcb667f039dd88a5126c3c5563e71985f89ee43 Mon Sep 17 00:00:00 2001 From: Blake Thompson Date: Wed, 17 May 2017 17:06:40 -0500 Subject: [PATCH] The last stripe of a tiff could be read incorrectly due to a swap --- src/tiff_reader.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/src/tiff_reader.cpp b/src/tiff_reader.cpp index 0740d31b6..c28eb5953 100644 --- a/src/tiff_reader.cpp +++ b/src/tiff_reader.cpp @@ -169,6 +169,8 @@ private: template void read_stripped(std::size_t x,std::size_t y, ImageData & image); + void read_stripped(std::size_t x,std::size_t y, image_rgba8 & image); + template void read_tiled(std::size_t x,std::size_t y, ImageData & image); @@ -530,10 +532,11 @@ struct tiff_reader_traits { if (TIFFReadRGBAStrip(tif, y, buf) != -1) { + /* for (std::size_t y = 0; y < rows_per_strip/2; ++y) { std::swap_ranges(buf + y * strip_width, buf + (y + 1) * strip_width, buf + (rows_per_strip - y - 1) * strip_width); - } + }*/ return true; } return false; @@ -719,6 +722,54 @@ void tiff_reader::read_tiled(std::size_t x0,std::size_t y0, ImageData & image } } +template +void tiff_reader::read_stripped(std::size_t x0, std::size_t y0, image_rgba8 & image) +{ + using pixel_type = typename detail::tiff_reader_traits::pixel_type; + TIFF* tif = open(stream_); + if (tif) + { + std::uint32_t strip_size = TIFFStripSize(tif); + std::unique_ptr strip(new pixel_type[strip_size]); + std::size_t width = image.width(); + std::size_t height = image.height(); + + std::size_t start_y = (y0 / rows_per_strip_) * rows_per_strip_; + std::size_t end_y = std::min(y0 + height, height_); + std::size_t tx0, tx1, ty0, ty1, rows_on_strip; + + tx0 = x0; + tx1 = std::min(width + x0, width_); + rows_on_strip = rows_per_strip_; + std::size_t row = 0; + bool pick_first_band = (bands_ > 1) && (strip_size / (width_ * rows_per_strip_ * sizeof(pixel_type)) == bands_); + for (std::size_t y = start_y; y < end_y; y += rows_per_strip_) + { + ty0 = std::max(y0, y) - y; + ty1 = std::min(end_y, y + rows_per_strip_) - y; + rows_on_strip = std::min(end_y - y, static_cast(rows_per_strip_)); + + if (!detail::tiff_reader_traits::read_strip(tif, y, rows_per_strip_, width_, strip.get())) + { + MAPNIK_LOG_DEBUG(tiff_reader) << "TIFFRead(Encoded|RGBA)Strip failed at " << y << " for " << width_ << "/" << height_ << "\n"; + break; + } + if (pick_first_band) + { + std::uint32_t size = width_ * rows_per_strip_ * sizeof(pixel_type); + for (std::uint32_t n = 0; n < size; ++n) + { + strip[n] = strip[bands_ * n]; + } + } + for (std::size_t ty = ty0; ty < ty1; ++ty) + { + image.set_row(row++, tx0 - x0, tx1 - x0, &strip[(rows_on_strip - ty - 1) * width_ + tx0]); + } + } + } +} + template template void tiff_reader::read_stripped(std::size_t x0, std::size_t y0, ImageData & image)