99#include < LLUtils/Exception.h>
1010#include < IImagePlugin.h>
1111
12+ #include < utility>
13+
1214namespace IMCodec
1315{
1416 class CodecTiff : public IImagePlugin
@@ -66,20 +68,15 @@ namespace IMCodec
6668 case SAMPLEFORMAT_UINT :
6769 switch (samplesPerPixel)
6870 {
69- case 1 :
70- switch (bitsPerSample)
71- {
72- case 8 :
73- texelFormat = TexelFormat::I_A8 ;
74- break ;
75- }
76- break ;
7771 case 3 :
7872 switch (bitsPerSample)
7973 {
8074 case 8 :
8175 texelFormat = TexelFormat::I_R8_G8_B8 ;
8276 break ;
77+ case 16 :
78+ texelFormat = TexelFormat::I_R16_G16_B16 ;
79+ break ;
8380 }
8481 break ;
8582 case 4 :
@@ -88,6 +85,9 @@ namespace IMCodec
8885 case 8 :
8986 texelFormat = TexelFormat::I_R8_G8_B8_A8 ;
9087 break ;
88+ case 16 :
89+ texelFormat = TexelFormat::I_R16_G16_B16_A16 ;
90+ break ;
9191 }
9292 break ;
9393 }
@@ -112,6 +112,9 @@ namespace IMCodec
112112 case 32 :
113113 texelFormat = TexelFormat::F_X32 ;
114114 break ;
115+ case 64 :
116+ texelFormat = TexelFormat::F_X64 ;
117+ break ;
115118 default :
116119 break ;
117120 }
@@ -127,37 +130,42 @@ namespace IMCodec
127130 case 1 :
128131 texelFormat = TexelFormat::I_X1 ;
129132 break ;
133+ case 4 :
134+ texelFormat = TexelFormat::I_X4 ;
135+ break ;
130136 case 8 :
131137 texelFormat = TexelFormat::I_X8 ;
132138 break ;
133139 case 16 :
134140 texelFormat = TexelFormat::I_X16 ;
135141 break ;
136- case SAMPLEFORMAT_INT :
137- switch (bitsPerSample)
138- {
139- case 8 :
140- texelFormat = TexelFormat::S_X8 ;
141- break ;
142- case 16 :
143- texelFormat = TexelFormat::S_X16 ;
144- break ;
145- default :
146- break ;
147- }
142+ }
143+ break ;
144+ }
145+ break ;
146+ case SAMPLEFORMAT_INT :
147+ switch (samplesPerPixel)
148+ {
149+ case 1 :
150+ switch (bitsPerSample)
151+ {
152+ case 8 :
153+ texelFormat = TexelFormat::S_X8 ;
154+ break ;
155+ case 16 :
156+ texelFormat = TexelFormat::S_X16 ;
157+ break ;
158+ default :
148159 break ;
149160 }
150161 break ;
151162 }
163+ break ;
152164 }
153165 }
154166
155-
156- if (texelFormat == TexelFormat::UNKNOWN )
157- LL_ERROR (LLUtils::Exception::ErrorCode::NotImplemented, " CodecTiff: unsupported floating point format." );
158-
159- return texelFormat;
160- }
167+ return texelFormat;
168+ }
161169
162170 std::vector<ImageItemSharedPtr> GetImage (TIFF * tiff)
163171 {
@@ -201,6 +209,9 @@ namespace IMCodec
201209 TIFFGetField(tiff, TIFFTAG_MAXSAMPLEVALUE, &maxSampleValue);*/
202210 TIFFGetField (tiff, TIFFTAG_EXTRASAMPLES , &extraSamples, &sampleTypes);
203211
212+ if (samplesPerPixel <= extraSamples)
213+ return {};
214+
204215 const uint32_t bytesPerSample = bitsPerSample / CHAR_BIT ;
205216
206217 uint32_t numberOfStripts = TIFFNumberOfStrips (tiff);
@@ -229,17 +240,38 @@ namespace IMCodec
229240 // If there's an alpha channel and it's interleaved in the image data, return as single image with alpha channel
230241 imageItem->descriptor .texelFormatDecompressed = imageItem->descriptor .texelFormatStorage = mainChannelTexelFormat;
231242
232- if (planarConfig == PLANARCONFIG_CONTIG && extraSamples == 1 && sampleTypes[ 0 ] > 0 )
243+ auto extractExtraSampleImages = [&]( )
233244 {
234- imageItem->descriptor .texelFormatStorage = imageItem->descriptor .texelFormatDecompressed = GetTexelFormat (sampleFormat, bitsPerSample, samplesPerPixel, photoMetric);
245+ return ExtactExtraSamples (width, height, rowPitch, samplesPerPixel, extraSamples, planarConfig
246+ , bytesPerSample, imageItem->data , photoMetric, bitsPerSample, sampleFormat);
247+ };
248+
249+ if (planarConfig == PLANARCONFIG_CONTIG && extraSamples > 0 )
250+ {
251+ const auto interleavedTexelFormat = GetTexelFormat (sampleFormat, bitsPerSample, samplesPerPixel, photoMetric);
252+
253+ if (interleavedTexelFormat != TexelFormat::UNKNOWN )
254+ {
255+ imageItem->descriptor .texelFormatStorage = imageItem->descriptor .texelFormatDecompressed = interleavedTexelFormat;
256+ }
257+ else
258+ {
259+ auto extraChannelImages = extractExtraSampleImages ();
260+
261+ if (extraChannelImages.empty () == false )
262+ imageItems = extraChannelImages;
263+ else
264+ return {};
265+ }
235266 }
236- else
267+ else if (extraSamples > 0 )
237268 {
238- auto extraChannelImages = ExtactExtraSamples (width, height, rowPitch, samplesPerPixel, extraSamples, planarConfig
239- , bytesPerSample, imageItem->data , photoMetric, bitsPerSample, sampleFormat);
269+ auto extraChannelImages = extractExtraSampleImages ();
240270
241271 if (extraChannelImages.empty () == false )
242272 imageItems = extraChannelImages;
273+ else
274+ return {};
243275 }
244276 }
245277 else
@@ -274,9 +306,13 @@ namespace IMCodec
274306 {
275307
276308 const auto sampleSize = sampleCount * bytesPerSample;
309+ const auto samplePhotometric = sampleOffset == 0 ? photometric : PHOTOMETRIC_MINISBLACK ;
277310
278311 auto imageItem = std::make_shared<ImageItem>();
279- imageItem->descriptor .texelFormatStorage = GetTexelFormat (sampleFormat, bitsPerSample , sampleCount, photometric);
312+ imageItem->descriptor .texelFormatStorage = GetTexelFormat (sampleFormat, bitsPerSample , sampleCount, samplePhotometric);
313+ if (imageItem->descriptor .texelFormatStorage == TexelFormat::UNKNOWN )
314+ return {};
315+
280316 imageItem->descriptor .texelFormatDecompressed = imageItem->descriptor .texelFormatStorage ;
281317 imageItem->descriptor .height = height;
282318 imageItem->descriptor .width = width;
@@ -293,7 +329,7 @@ namespace IMCodec
293329 {
294330 for (size_t x = 0 ; x < width; x++)
295331 {
296- const size_t sourceRowIndex = sampleOffset * sampleSize + x * samplesPerPixel * bytesPerSample;
332+ const size_t sourceRowIndex = sampleOffset * bytesPerSample + x * samplesPerPixel * bytesPerSample;
297333 const size_t destRowIndex = x * sampleSize;
298334 memcpy (image.data () + destOffset + destRowIndex, sourceBuffer.data () + sourceOffset + sourceRowIndex, sampleSize);
299335 }
@@ -318,12 +354,25 @@ namespace IMCodec
318354
319355 if (extraSmaples > 0 )
320356 {
357+ if (bytesPerSample == 0 || bitsPerSample % CHAR_BIT != 0 || samplesPerPixel <= extraSmaples)
358+ return {};
359+
321360 const auto mainImageSampleCount = samplesPerPixel - extraSmaples;
322361
323- subChannels.push_back (extractSamples (0 , mainImageSampleCount));
362+ auto mainImage = extractSamples (0 , mainImageSampleCount);
363+ if (mainImage == nullptr )
364+ return {};
365+
366+ subChannels.push_back (std::move (mainImage));
324367
325368 for (int i = 0 ; i < extraSmaples; i++)
326- subChannels.push_back (extractSamples (mainImageSampleCount + i, 1 ));
369+ {
370+ auto extraImage = extractSamples (mainImageSampleCount + i, 1 );
371+ if (extraImage == nullptr )
372+ return {};
373+
374+ subChannels.push_back (std::move (extraImage));
375+ }
327376 }
328377
329378
@@ -344,6 +393,9 @@ namespace IMCodec
344393 int currentSubImage = 0 ;
345394
346395 auto firstImageItemChannles = GetImage (tiff);
396+ if (firstImageItemChannles.empty ())
397+ return ImageResult::FormatNotSupported;
398+
347399 firstImageItem = firstImageItemChannles.at (0 );
348400
349401 if (firstImageItemChannles.size () > 1 )
@@ -365,6 +417,9 @@ namespace IMCodec
365417 }
366418
367419 auto nextImages = GetImage (tiff);
420+ if (nextImages.empty ())
421+ return ImageResult::FormatNotSupported;
422+
368423 for (size_t i = 0 ; i < nextImages.size (); i++)
369424 {
370425 subImages.push_back (std::make_shared<Image>(nextImages.at (i), ImageItemType::Pages));
0 commit comments