@@ -1586,12 +1586,12 @@ Task<ImageData> decodeJpeg(
15861586
15871587 const auto numJpegSamples = numJpegPixels * numComponents;
15881588 const auto numTileSamples = numTilePixels * tileNumComponents;
1589+ const auto numSamples = std::max (numJpegSamples, numTileSamples);
15891590
1590- if (numJpegSamples < numTileSamples) {
1591- throw ImageLoadError{fmt::format (
1592- " Decompressed JPEG has fewer samples ({}) than expected from the tile size and samples per pixel ({})." , numJpegSamples, numTileSamples
1593- )};
1594- }
1591+ // There are situations in which either the jpeg is smaller than the tile size (e.g. last strip of an image, where the strip height does
1592+ // not evenly divide the image height) or the jpeg is larger than the tile size (some DNG; we ignore the extra data). Hence make our
1593+ // buffer large enough for either case.
1594+ auto buf = PixelBuffer::alloc (numSamples, pixelFormat);
15951595
15961596 const float scale = 1 .0f / (float )((1ull << precision) - 1 );
15971597
@@ -1611,8 +1611,6 @@ Task<ImageData> decodeJpeg(
16111611 // (int)cinfo.jpeg_color_space
16121612 // );
16131613
1614- auto buf = PixelBuffer::alloc (width * height * numComponents, pixelFormat);
1615-
16161614 if (cinfo.data_precision <= 8 ) {
16171615 HeapArray<JSAMPROW > rowPointers (height);
16181616 for (size_t y = 0 ; y < height; ++y) {
@@ -2193,18 +2191,6 @@ Task<ImageData> readTiffImage(
21932191 };
21942192 }
21952193
2196- const auto tileSize = Vector2i{(int )tile.width , (int )tile.height };
2197- for (auto & channel : tmpImage.channels ) {
2198- if (channel.size () != tileSize) {
2199- throw ImageLoadError{fmt::format (
2200- " Tile channel '{}' has unexpected dimensions: expected {}, got {}" ,
2201- channel.name (),
2202- tileSize,
2203- tmpImage.channels .front ().size ()
2204- )};
2205- }
2206- }
2207-
22082194 // Rescale embedded image data according to its true bits per sample. E.g. when a 10 bit TIFF encodes data with only
22092195 // 16 bits of JXL precision, as can happen when JXL codestreams are embedded in TIFF files. Curiously, when the
22102196 // situation is reversed (e.g. 16 bit TIFF with 14 bit JXL data), the data shouldn't get rescaled. Hence the clamp.
@@ -2224,6 +2210,18 @@ Task<ImageData> readTiffImage(
22242210 const int yStart = (int )tileY * tile.height ;
22252211 const int yEnd = std::min ((int )((tileY + 1 ) * tile.height ), size.y ());
22262212
2213+ const auto tileSize = Vector2i{xEnd - xStart, yEnd - yStart};
2214+ for (auto & channel : tmpImage.channels ) {
2215+ if (channel.size ().x () < tileSize.x () || channel.size ().y () < tileSize.y ()) {
2216+ throw ImageLoadError{fmt::format (
2217+ " Tile channel '{}' has unexpected dimensions: expected {}, got {}" ,
2218+ channel.name (),
2219+ tileSize,
2220+ tmpImage.channels .front ().size ()
2221+ )};
2222+ }
2223+ }
2224+
22272225 const size_t numPixels = (size_t )(xEnd - xStart) * (yEnd - yStart);
22282226
22292227 auto * const data = buf.data <float >();
0 commit comments