xref: /core/vcl/source/filter/itiff/itiff.cxx (revision 891ff133)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 #include <sal/log.hxx>
22 
23 #include <unotools/configmgr.hxx>
24 #include <vcl/FilterConfigItem.hxx>
25 #include <vcl/graph.hxx>
26 #include <vcl/BitmapTools.hxx>
27 #include <vcl/animate/Animation.hxx>
28 #include <tools/fract.hxx>
29 #include <tools/stream.hxx>
30 #include "lzwdecom.hxx"
31 #include "ccidecom.hxx"
32 
33 #include <filter/TiffReader.hxx>
34 
35 namespace {
36 
37 template< typename T > T BYTESWAP(T nByte) {
38     return ( nByte << 7 ) | ( ( nByte & 2 ) << 5 ) | ( ( nByte & 4 ) << 3 ) |
39         ( ( nByte & 8 ) << 1 ) | ( ( nByte & 16 ) >> 1 ) |
40         ( ( nByte & 32 ) >> 3 ) | ( ( nByte & 64 ) >> 5 ) |
41         ( ( nByte & 128 ) >> 7 );
42 }
43 
44 //============================ TIFFReader ==================================
45 
46 class TIFFReader
47 {
48 
49 private:
50 
51     bool                bStatus;                    // Whether until now no error occurred
52     Animation               aAnimation;
53 
54     SvStream*               pTIFF;                      // the TIFF file that should be read
55     std::vector<sal_uInt8>  maBitmap;
56     Size                    maBitmapPixelSize;
57     std::vector<Color>      mvPalette;
58     MapMode                 maBitmapPrefMapMode;
59     Size                    maBitmapPrefSize;
60     sal_uInt16              nDstBitsPerPixel;
61     int                     nLargestPixelIndex;
62 
63     sal_uInt64              nOrigPos;                   // start position in pTIFF
64     sal_uInt64              nEndOfFile;                 // end of file position in pTIFF
65 
66 
67     sal_uInt16              nDataType;
68     // Data taken from the TIFF tags:
69     bool                    bByteSwap;                  // sal_True if bits 0..7 -> 7..0 should get converted ( FILLORDER = 2 );
70 
71     sal_uInt32              nNewSubFile;
72     sal_uInt32              nSubFile;
73     sal_Int32               nImageWidth;                // picture width in pixels
74     sal_Int32               nImageLength;               // picture height in pixels
75     sal_uInt32              nBitsPerSample;             // bits per pixel per layer
76     sal_uInt32              nCompression;               // kind of compression
77     sal_uInt32              nPhotometricInterpretation;
78     sal_uInt32              nThresholding;
79     sal_uInt32              nCellWidth;
80     sal_uInt32              nCellLength;
81     sal_uInt32              nFillOrder;
82     std::vector<sal_uInt64> aStripOffsets;              // field of offsets to the Bitmap-Data-"Strips"
83     sal_uInt32              nOrientation;
84     sal_uInt32              nSamplesPerPixel;           // number of layers
85     sal_uInt32              nRowsPerStrip;              // if it's not compressed: number of rows per Strip
86     std::vector<sal_uInt32> aStripByteCounts;           // if compressed (in a certain way): size of the strips
87     sal_uInt32              nMinSampleValue;
88     sal_uInt32              nMaxSampleValue;
89     double                  fXResolution;               // X-resolution or 0.0
90     double                  fYResolution;               // Y-resolution or 0.0
91     sal_uInt32              nPlanarConfiguration;
92     sal_uInt32              nGroup3Options;
93     sal_uInt32              nGroup4Options;
94     sal_uInt32              nResolutionUnit;            // unit of fX/YResolution: 1=unknown, 2(default)=inch, 3=cm
95     sal_uInt32              nPredictor;
96     std::vector<sal_uInt32> aColorMap;                  // color palette
97     sal_uInt32              nNumColors;                 // number of colors within the color palette
98 
99     sal_uInt32              nPlanes;                    // number of layers within the Tiff file
100     sal_uInt32              nStripsPerPlane;            // number of Strips per layer
101     sal_uInt32              nBytesPerRow;               // Bytes per line per Layer in the Tiff file ( uncompressed )
102     std::vector<sal_uInt8>  aMap[4];                    // temporary Scanline
103 
104 
105     sal_uInt32 DataTypeSize();
106     sal_uInt32 ReadIntData();
107     double  ReadDoubleData();
108 
109     void    ReadHeader();
110     void    ReadTagData( sal_uInt16 nTagType, sal_uInt32 nDataLen );
111 
112     sal_uInt8* getMapData(sal_uInt32 np);
113 
114     bool    ReadMap();
115         // reads/decompress the bitmap data and fills aMap
116 
117     sal_uInt32 GetBits(const sal_uInt8 * pSrc, sal_uInt32 nBitsPos, sal_uInt32 nBitsCount) const;
118         // fetches BitsCount bits from pSrc[..] at the position nBitsPos
119 
120     void    MakePalCol();
121         // Create the bitmap from the temporary bitmap aMap
122         // and partly deletes aMap while doing this.
123 
124     bool    ConvertScanline(sal_Int32 nY);
125         // converts a Scanline to the Windows-BMP format
126 
127     bool HasAlphaChannel() const;
128 
129     void SetPixel(tools::Long nY, tools::Long nX, sal_uInt8 cIndex);
130     void SetPixel(tools::Long nY, tools::Long nX, Color c);
131     void SetPixelAlpha(tools::Long nY, tools::Long nX, sal_uInt8 nAlpha);
132 
133 public:
134 
135     TIFFReader()
136         : bStatus(false)
137         , pTIFF(nullptr)
138         , nDstBitsPerPixel(0)
139         , nLargestPixelIndex(-1)
140         , nOrigPos(0)
141         , nEndOfFile(0)
142         , nDataType(0)
143         , bByteSwap(false)
144         , nNewSubFile(0)
145         , nSubFile(0)
146         , nImageWidth(0)
147         , nImageLength(0)
148         , nBitsPerSample(1)
149         , nCompression(1)
150         , nPhotometricInterpretation(0)
151         , nThresholding(1)
152         , nCellWidth(1)
153         , nCellLength(1)
154         , nFillOrder(1)
155         , nOrientation(1)
156         , nSamplesPerPixel(1)
157         , nRowsPerStrip(0xffffffff)
158         , nMinSampleValue(0)
159         , nMaxSampleValue(0)
160         , fXResolution(0.0)
161         , fYResolution(0.0)
162         , nPlanarConfiguration(1)
163         , nGroup3Options(0)
164         , nGroup4Options(0)
165         , nResolutionUnit(2)
166         , nPredictor(0)
167         , nNumColors(0)
168         , nPlanes(0)
169         , nStripsPerPlane(0)
170         , nBytesPerRow(0)
171     {
172     }
173 
174     sal_uInt32 GetRowsPerStrip() const
175     {
176         //Rows Per Strip:
177         //
178         //(TIFF format only) The number of rows of pixels per strip to use for
179         //encoding the TIFF image. A value greater than zero specifies the
180         //number of rows per strip. A value of 0 sets the rows per strip equal
181         //to the image length, resulting in a single strip. A value of -1 (the
182         //default) sets the rows per strip equal to infinity, resulting in a
183         //single strip.
184         return nRowsPerStrip == 0 ? nImageLength : nRowsPerStrip;
185     }
186 
187     bool ReadTIFF( SvStream & rTIFF, Graphic & rGraphic );
188 };
189 
190 }
191 
192 //=================== Methods of TIFFReader ==============================
193 
194 sal_uInt32 TIFFReader::DataTypeSize()
195 {
196     sal_uInt32 nSize;
197     switch ( nDataType )
198     {
199         case 1 :            // BYTE
200         case 2 :            // ASCII
201         case 6 :            // SIGNED Byte
202         case 7 :            // UNDEFINED
203             nSize = 1;
204             break;
205         case 3 :            // UINT16
206         case 8 :            // INT16
207             nSize = 2;
208             break;
209         case 4 :            // UINT32
210         case 9 :            // INT32
211         case 11 :           // FLOAT
212             nSize = 4;
213             break;
214         case 5 :            // RATIONAL
215         case 10 :           // SIGNED RATIONAL
216         case 12 :           // DOUBLE
217             nSize = 8;
218             break;
219         default:
220             pTIFF->SetError(SVSTREAM_FILEFORMAT_ERROR);
221             nSize=1;
222     }
223     return nSize;
224 }
225 
226 sal_uInt32 TIFFReader::ReadIntData()
227 {
228     double  nDOUBLE(0.0);
229     float   nFLOAT(0);
230     sal_uInt32  nUINT32a(0), nUINT32b(0);
231     sal_Int32   nINT32(0);
232     sal_uInt16  nUINT16(0);
233     sal_Int16   nINT16(0);
234     sal_uInt8   nBYTE(0);
235     char    nCHAR(0);
236 
237     switch( nDataType )
238     {
239         case 0 :    //??
240         case 1 :
241         case 2 :
242         case 7 :
243             pTIFF->ReadUChar( nBYTE );
244             nUINT32a = nBYTE;
245         break;
246         case 3 :
247              pTIFF->ReadUInt16( nUINT16 );
248              nUINT32a = nUINT16;
249         break;
250         case 9 :
251         case 4 :
252             pTIFF->ReadUInt32( nUINT32a );
253         break;
254         case  5 :
255             pTIFF->ReadUInt32( nUINT32a ).ReadUInt32( nUINT32b );
256             if ( nUINT32b != 0 )
257                 nUINT32a /= nUINT32b;
258         break;
259         case 6 :
260             pTIFF->ReadChar( nCHAR );
261             nUINT32a = static_cast<sal_Int32>(nCHAR);
262         break;
263         case 8 :
264             pTIFF->ReadInt16( nINT16 );
265             nUINT32a = static_cast<sal_Int32>(nINT16);
266         break;
267         case 10 :
268             pTIFF->ReadUInt32( nUINT32a ).ReadInt32( nINT32 );
269             if ( nINT32 != 0 )
270                 nUINT32a /= nINT32;
271         break;
272         case 11 :
273             pTIFF->ReadFloat( nFLOAT );
274             if (!std::isnan(nFLOAT) && nFLOAT > SAL_MIN_INT32 - 1.0
275                 && nFLOAT < SAL_MAX_INT32 + 1.0)
276             {
277                 nUINT32a = static_cast<sal_Int32>(nFLOAT);
278             }
279             else
280             {
281                 SAL_INFO("filter.tiff", "float " << nFLOAT << " outsider of sal_Int32 range");
282             }
283         break;
284         case 12 :
285             pTIFF->ReadDouble( nDOUBLE );
286             if (!std::isnan(nDOUBLE) && nDOUBLE > SAL_MIN_INT32 - 1.0
287                 && nDOUBLE < SAL_MAX_INT32 + 1.0)
288             {
289                 nUINT32a = static_cast<sal_Int32>(nDOUBLE);
290             }
291             else
292             {
293                 SAL_INFO("filter.tiff", "double " << nDOUBLE << " outsider of sal_Int32 range");
294             }
295         break;
296         default:
297             pTIFF->ReadUInt32( nUINT32a );
298         break;
299     }
300     return nUINT32a;
301 }
302 
303 double TIFFReader::ReadDoubleData()
304 {
305     switch (nDataType) {
306     case 5:
307         {
308             sal_uInt32 nulong(0);
309             pTIFF->ReadUInt32( nulong );
310             double nd = static_cast<double>(nulong);
311             nulong = 0;
312             pTIFF->ReadUInt32( nulong );
313             if ( nulong != 0 )
314                 nd /= static_cast<double>(nulong);
315             return nd;
316         }
317 
318     case 11:
319         {
320             float x = 0;
321             pTIFF->ReadFloat(x);
322             return x;
323         }
324 
325     case 12:
326         {
327             double x = 0;
328             pTIFF->ReadDouble(x);
329             return x;
330         }
331 
332     default:
333         return static_cast<double>(ReadIntData());
334     }
335 }
336 
337 void TIFFReader::ReadTagData( sal_uInt16 nTagType, sal_uInt32 nDataLen)
338 {
339     if ( !bStatus )
340         return;
341 
342     switch ( nTagType )
343     {
344         case 0x00fe:   // New Sub File
345             nNewSubFile = ReadIntData();
346             SAL_INFO("filter.tiff","NewSubFile: " << nNewSubFile);
347             break;
348 
349         case 0x00ff:   // Sub File
350             nSubFile = ReadIntData();
351             SAL_INFO("filter.tiff","SubFile: " << nSubFile);
352             break;
353 
354         case 0x0100:   // Image Width
355             nImageWidth = ReadIntData();
356             SAL_INFO("filter.tiff","ImageWidth: " << nImageWidth);
357             break;
358 
359         case 0x0101:   // Image Length
360             nImageLength = ReadIntData();
361             SAL_INFO("filter.tiff","ImageLength: " << nImageLength);
362             break;
363 
364         case 0x0102:   // Bits Per Sample
365             nBitsPerSample = ReadIntData();
366             SAL_INFO("filter.tiff","BitsPerSample: " << nBitsPerSample);
367             if ( nBitsPerSample >= 32 ) // 32 bit and larger samples are not supported
368                 bStatus = false;
369             break;
370 
371         case 0x0103:   // Compression
372             nCompression = ReadIntData();
373             SAL_INFO("filter.tiff","Compression: " << nCompression);
374             break;
375 
376         case 0x0106:   // Photometric Interpretation
377             nPhotometricInterpretation = ReadIntData();
378             SAL_INFO("filter.tiff","PhotometricInterpretation: " << nPhotometricInterpretation);
379             break;
380 
381         case 0x0107:   // Thresholding
382             nThresholding = ReadIntData();
383             SAL_INFO("filter.tiff","Thresholding: " << nThresholding);
384             break;
385 
386         case 0x0108:   // Cell Width
387             nCellWidth = ReadIntData();
388             break;
389 
390         case 0x0109:   // Cell Length
391             nCellLength = ReadIntData();
392             break;
393 
394         case 0x010a:   // Fill Order
395             nFillOrder = ReadIntData();
396             SAL_INFO("filter.tiff","FillOrder: " << nFillOrder);
397             break;
398 
399         case 0x0111: { // Strip Offset(s)
400             size_t nOldNumSO = aStripOffsets.size();
401             nDataLen += nOldNumSO;
402             size_t const nMaxAllocAllowed = SAL_MAX_INT32 / sizeof(sal_uInt32);
403             size_t nMaxRecordsAvailable = pTIFF->remainingSize() / DataTypeSize();
404             if (nDataLen > nOldNumSO && nDataLen < nMaxAllocAllowed &&
405                 (nDataLen - nOldNumSO) <= nMaxRecordsAvailable)
406             {
407                 try
408                 {
409                     aStripOffsets.resize(nDataLen);
410                     if (nOrigPos)
411                     {
412                         for (size_t i = 0; i < nOldNumSO; ++i)
413                             aStripOffsets[i] += nOrigPos;
414                     }
415                     for (size_t i = nOldNumSO; i < aStripOffsets.size(); ++i)
416                         aStripOffsets[i] = ReadIntData() + nOrigPos;
417                 }
418                 catch (const std::bad_alloc &)
419                 {
420                     aStripOffsets.clear();
421                 }
422             }
423             SAL_INFO("filter.tiff","StripOffsets (Number:) " << nDataLen);
424             break;
425         }
426         case 0x0112:   // Orientation
427             nOrientation = ReadIntData();
428             SAL_INFO("filter.tiff","Orientation: " << nOrientation);
429             break;
430 
431         case 0x0115:   // Samples Per Pixel
432             nSamplesPerPixel = ReadIntData();
433             SAL_INFO("filter.tiff","SamplesPerPixel: " << nSamplesPerPixel);
434 
435             if (nSamplesPerPixel > USHRT_MAX) // ofz#15993 the expected type is SHORT
436                 bStatus = false;
437 
438             break;
439 
440         case 0x0116:   // Rows Per Strip
441             nRowsPerStrip = ReadIntData();
442             SAL_INFO("filter.tiff","RowsPerStrip: " << nRowsPerStrip);
443             break;
444 
445         case 0x0117: { // Strip Byte Counts
446             size_t nOldNumSBC = aStripByteCounts.size();
447             nDataLen += nOldNumSBC;
448             size_t const nMaxAllocAllowed = SAL_MAX_INT32 / sizeof(sal_uInt32);
449             size_t nMaxRecordsAvailable = pTIFF->remainingSize() / DataTypeSize();
450             if (nDataLen > nOldNumSBC && nDataLen < nMaxAllocAllowed &&
451                 (nDataLen - nOldNumSBC) <= nMaxRecordsAvailable)
452             {
453                 try
454                 {
455                     aStripByteCounts.resize(nDataLen);
456                     for (size_t i = nOldNumSBC; i < aStripByteCounts.size(); ++i)
457                         aStripByteCounts[i] = ReadIntData();
458                 }
459                 catch (const std::bad_alloc &)
460                 {
461                     aStripByteCounts.clear();
462                 }
463             }
464             SAL_INFO("filter.tiff","StripByteCounts (Number:) " << nDataLen);
465             break;
466         }
467         case 0x0118:   // Min Sample Value
468             nMinSampleValue = ReadIntData();
469             SAL_INFO("filter.tiff","MinSampleValue: " << nMinSampleValue);
470             break;
471 
472         case 0x0119:   // Max Sample Value
473             nMaxSampleValue = ReadIntData();
474             SAL_INFO("filter.tiff","MaxSampleValue: " << nMaxSampleValue);
475             break;
476 
477         case 0x011a:   // X Resolution
478             fXResolution = ReadDoubleData();
479             break;
480 
481         case 0x011b:   // Y Resolution
482             fYResolution = ReadDoubleData();
483             break;
484 
485         case 0x011c:   // Planar Configuration
486             nPlanarConfiguration = ReadIntData();
487             SAL_INFO("filter.tiff","PlanarConfiguration: " << nPlanarConfiguration);
488             break;
489 
490         case 0x0124:   // Group 3 Options
491             nGroup3Options = ReadIntData();
492             SAL_INFO("filter.tiff","Group3Options: " << nGroup3Options);
493             break;
494 
495         case 0x0125:   // Group 4 Options
496             nGroup4Options = ReadIntData();
497             SAL_INFO("filter.tiff","Group4Options: " << nGroup4Options);
498             break;
499 
500         case 0x0128:   // Resolution Unit
501             nResolutionUnit = ReadIntData();
502             break;
503 
504         case 0x013d:   // Predictor
505             nPredictor = ReadIntData();
506             SAL_INFO("filter.tiff","Predictor: " << nPredictor);
507             break;
508 
509         case 0x0140: { // Color Map
510             sal_uInt16 nVal;
511             nNumColors = (sal_uInt32(1) << nBitsPerSample);
512             if ( nDataType == 3 && nNumColors <= 256)
513             {
514                 aColorMap.resize(256);
515                 for (sal_uInt32 i = 0; i < nNumColors; ++i)
516                     aColorMap[i] = 0;
517                 for (sal_uInt32 i = 0; i < nNumColors; ++i)
518                 {
519                     pTIFF->ReadUInt16( nVal );
520                     aColorMap[i] |= ( static_cast<sal_uInt32>(nVal) << 8 ) & 0x00ff0000;
521                 }
522                 for (sal_uInt32 i = 0; i < nNumColors; ++i)
523                 {
524                     pTIFF->ReadUInt16( nVal );
525                     aColorMap[i] |= static_cast<sal_uInt32>(nVal) & 0x0000ff00;
526                 }
527                 for (sal_uInt32 i = 0; i < nNumColors; ++i)
528                 {
529                     pTIFF->ReadUInt16( nVal );
530                     aColorMap[i] |= ( static_cast<sal_uInt32>(nVal) >> 8 ) & 0x000000ff;
531                 }
532             }
533             else
534                 bStatus = false;
535             SAL_INFO("filter.tiff","ColorMap (number of colors): " << nNumColors);
536             break;
537         }
538 
539         case 0x0153: { // SampleFormat
540             sal_uInt32 nSampleFormat = ReadIntData();
541             if ( nSampleFormat == 3 ) // IEEE floating point samples are not supported yet
542                 bStatus = false;
543             break;
544         }
545     }
546 
547     if ( pTIFF->GetError() )
548         bStatus = false;
549 }
550 
551 sal_uInt8* TIFFReader::getMapData(sal_uInt32 np)
552 {
553     aMap[np].resize(nBytesPerRow);
554     return aMap[np].data();
555 }
556 
557 bool TIFFReader::ReadMap()
558 {
559     //when fuzzing with a max len set, max decompress to 250 times that limit
560     static size_t nMaxAllowedDecompression = [](const char* pEnv) { size_t nRet = pEnv ? std::atoi(pEnv) : 0; return nRet * 250; }(std::getenv("FUZZ_MAX_INPUT_LEN"));
561     size_t nTotalDataRead = 0;
562 
563     if ( nCompression == 1 || nCompression == 32771 )
564     {
565         sal_uInt32 nStripBytesPerRow;
566 
567         if ( nCompression == 1 )
568             nStripBytesPerRow = nBytesPerRow;
569         else
570             nStripBytesPerRow = ( nBytesPerRow + 1 ) & 0xfffffffe;
571         for (sal_Int32 ny = 0; ny < nImageLength; ++ny)
572         {
573             for (sal_uInt32 np = 0; np < nPlanes; ++np)
574             {
575                 if (np >= SAL_N_ELEMENTS(aMap))
576                     return false;
577                 sal_uInt32 nStrip = ny / GetRowsPerStrip() + np * nStripsPerPlane;
578                 if ( nStrip >= aStripOffsets.size())
579                     return false;
580                 pTIFF->Seek( aStripOffsets[ nStrip ] + ( ny % GetRowsPerStrip() ) * nStripBytesPerRow );
581                 // tdf#126147 allow a short incomplete read
582                 auto pDest = getMapData(np);
583                 auto nRead = pTIFF->ReadBytes(pDest, nBytesPerRow);
584                 if (nRead != nBytesPerRow)
585                     memset(pDest + nRead, 0, nBytesPerRow - nRead);
586             }
587             if ( !ConvertScanline( ny ) )
588                 return false;
589         }
590     }
591     else if ( nCompression == 2 || nCompression == 3 || nCompression == 4 )
592     {
593         sal_uInt32 nOptions;
594         if ( nCompression == 2 )
595         {
596             nOptions = CCI_OPTION_BYTEALIGNROW;
597         }
598         else if ( nCompression == 3 )
599         {
600             nOptions = CCI_OPTION_EOL;
601             if ( nGroup3Options & 0x00000001 )
602                 nOptions |= CCI_OPTION_2D;
603             if ( nGroup3Options & 0x00000004 )
604                 nOptions |= CCI_OPTION_BYTEALIGNEOL;
605             if ( nGroup3Options & 0xfffffffa )
606                 return false;
607         }
608         else
609         {   // nCompression==4
610             nOptions = CCI_OPTION_2D;
611             if ( nGroup4Options & 0xffffffff )
612                 return false;
613         }
614         if ( nFillOrder == 2 )
615         {
616             nOptions |= CCI_OPTION_INVERSEBITORDER;
617             bByteSwap = false;
618         }
619         sal_uInt32 nStrip = 0;
620         if (nStrip >= aStripOffsets.size())
621             return false;
622         sal_uInt64 nOffset = aStripOffsets[nStrip];
623         if (nOffset > nEndOfFile)
624             return false;
625         pTIFF->Seek(aStripOffsets[nStrip]);
626 
627         CCIDecompressor aCCIDecom( nOptions, nImageWidth );
628 
629         aCCIDecom.StartDecompression( *pTIFF );
630 
631         const bool bHasAlphaChannel = HasAlphaChannel();
632         for (sal_Int32 ny = 0; ny < nImageLength; ++ny)
633         {
634             bool bDifferentToPrev = ny == 0;
635             for (sal_uInt32 np = 0; np < nPlanes; ++np)
636             {
637                 if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip )
638                 {
639                     nStrip=ny/GetRowsPerStrip()+np*nStripsPerPlane;
640                     if (nStrip >= aStripOffsets.size())
641                         return false;
642                     nOffset = aStripOffsets[nStrip];
643                     if (nOffset > nEndOfFile)
644                         return false;
645                     pTIFF->Seek(nOffset);
646                     aCCIDecom.StartDecompression( *pTIFF );
647                 }
648                 if (np >= SAL_N_ELEMENTS(aMap))
649                     return false;
650                 DecompressStatus aResult = aCCIDecom.DecompressScanline(getMapData(np), nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes, np + 1 == nPlanes);
651                 if (!aResult.m_bSuccess)
652                     return false;
653                 bDifferentToPrev |= !aResult.m_bBufferUnchanged;
654                 if ( pTIFF->GetError() )
655                     return false;
656                 nTotalDataRead += nBytesPerRow;
657                 if (nMaxAllowedDecompression && nTotalDataRead > nMaxAllowedDecompression)
658                     return false;
659             }
660             if (!bDifferentToPrev)
661             {
662                 //if the buffer for this line didn't change, then just copy the
663                 //previous scanline instead of painfully decoding and setting
664                 //each pixel one by one again
665                 const int nColorSize = bHasAlphaChannel ? 4 : 3;
666                 memcpy( maBitmap.data() + (ny * maBitmapPixelSize.Width()) * nColorSize,
667                         maBitmap.data() + ((ny-1) * maBitmapPixelSize.Width()) * nColorSize,
668                         maBitmapPixelSize.Width() * nColorSize);
669             }
670             else
671             {
672                 if (!ConvertScanline(ny))
673                     return false;
674             }
675         }
676     }
677     else if ( nCompression == 5 )
678     {
679         LZWDecompressor aLZWDecom;
680         sal_uInt32 nStrip(0);
681         if (nStrip >= aStripOffsets.size())
682             return false;
683         pTIFF->Seek(aStripOffsets[nStrip]);
684         aLZWDecom.StartDecompression(*pTIFF);
685         for (sal_Int32 ny = 0; ny < nImageLength; ++ny)
686         {
687             for (sal_uInt32 np = 0; np < nPlanes; ++np)
688             {
689                 if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip )
690                 {
691                     nStrip = ny / GetRowsPerStrip() + np * nStripsPerPlane;
692                     if (nStrip >= aStripOffsets.size())
693                         return false;
694                     pTIFF->Seek(aStripOffsets[nStrip]);
695                     aLZWDecom.StartDecompression(*pTIFF);
696                 }
697                 if (np >= SAL_N_ELEMENTS(aMap))
698                     return false;
699                 if ( ( aLZWDecom.Decompress(getMapData(np), nBytesPerRow) != nBytesPerRow ) || pTIFF->GetError() )
700                     return false;
701             }
702 
703             nTotalDataRead += nBytesPerRow;
704             if (nMaxAllowedDecompression && nTotalDataRead > nMaxAllowedDecompression)
705                 return false;
706 
707             if ( !ConvertScanline( ny ) )
708                 return false;
709         }
710     }
711     else if ( nCompression == 32773 )
712     {
713         sal_uInt32 nStrip(0);
714         if (nStrip >= aStripOffsets.size())
715             return false;
716         pTIFF->Seek(aStripOffsets[nStrip]);
717         for (sal_Int32 ny = 0; ny < nImageLength; ++ny)
718         {
719             for (sal_uInt32 np = 0; np < nPlanes; ++np)
720             {
721                 if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip )
722                 {
723                     nStrip=ny/GetRowsPerStrip()+np*nStripsPerPlane;
724                     if (nStrip >= aStripOffsets.size())
725                         return false;
726                     pTIFF->Seek(aStripOffsets[nStrip]);
727                 }
728                 sal_uInt32 nRowBytesLeft = nBytesPerRow;
729                 if (np >= SAL_N_ELEMENTS(aMap))
730                     return false;
731                 sal_uInt8* pdst = getMapData(np);
732                 do
733                 {
734                     sal_uInt8 nRecHeader(0);
735                     pTIFF->ReadUChar(nRecHeader);
736                     sal_uInt32 nRecCount;
737                     if ((nRecHeader&0x80)==0)
738                     {
739                         nRecCount=0x00000001 + static_cast<sal_uInt32>(nRecHeader);
740                         if ( nRecCount > nRowBytesLeft )
741                             return false;
742                         pTIFF->ReadBytes(pdst, nRecCount);
743                         if (!pTIFF->good())
744                             return false;
745                         pdst+=nRecCount;
746                         nRowBytesLeft-=nRecCount;
747                     }
748                     else if ( nRecHeader != 0x80 )
749                     {
750                         nRecCount = 0x000000101 - static_cast<sal_uInt32>(nRecHeader);
751                         if ( nRecCount > nRowBytesLeft )
752                         {
753                             nRecCount = nRowBytesLeft;
754                         }
755                         sal_uInt8 nRecData(0);
756                         pTIFF->ReadUChar( nRecData );
757                         for (sal_uInt32 i = 0; i < nRecCount; ++i)
758                             *(pdst++) = nRecData;
759                         nRowBytesLeft -= nRecCount;
760                     }
761                 } while ( nRowBytesLeft != 0 );
762                 if ( pTIFF->GetError() )
763                     return false;
764             }
765             if ( !ConvertScanline( ny ) )
766                 return false;
767         }
768     }
769     else
770         return false;
771     return true;
772 }
773 
774 sal_uInt32 TIFFReader::GetBits( const sal_uInt8 * pSrc, sal_uInt32 nBitsPos, sal_uInt32 nBitsCount) const
775 {
776     sal_uInt32 nRes;
777     if ( bByteSwap )
778     {
779         pSrc += ( nBitsPos >> 3 );
780         nBitsPos &= 7;
781         sal_uInt8 nDat = *pSrc;
782         nRes = static_cast<sal_uInt32>( BYTESWAP( nDat ) & ( 0xff >> nBitsPos ) );
783 
784         if ( nBitsCount <= 8 - nBitsPos )
785         {
786             nRes >>= ( 8 - nBitsPos - nBitsCount );
787         }
788         else
789         {
790             pSrc++;
791             nBitsCount -= 8 - nBitsPos;
792             while ( nBitsCount >= 8 )
793             {
794                 nDat = *(pSrc++);
795                 nRes = ( nRes << 8 ) | static_cast<sal_uInt32>(BYTESWAP( nDat ));
796                 nBitsCount -= 8;
797             }
798             if ( nBitsCount > 0 )
799             {
800                 nDat = *pSrc;
801                 nRes = ( nRes << nBitsCount ) | (static_cast<sal_uInt32>(BYTESWAP(nDat))>>(8-nBitsCount));
802             }
803         }
804     }
805     else
806     {
807         pSrc += ( nBitsPos >> 3 );
808         nBitsPos &= 7;
809         nRes = static_cast<sal_uInt32>((*pSrc)&(0xff>>nBitsPos));
810         if ( nBitsCount <= 8 - nBitsPos )
811         {
812             nRes >>= ( 8 - nBitsPos - nBitsCount );
813         }
814         else
815         {
816             pSrc++;
817             nBitsCount -= 8 - nBitsPos;
818             while ( nBitsCount >= 8 )
819             {
820                 nRes = ( nRes << 8 ) | static_cast<sal_uInt32>(*(pSrc++));
821                 nBitsCount -= 8;
822             }
823             if ( nBitsCount > 0 )
824                 nRes = ( nRes << nBitsCount ) | (static_cast<sal_uInt32>(*pSrc)>>(8-nBitsCount));
825         }
826     }
827     return nRes;
828 }
829 
830 void TIFFReader::SetPixel(tools::Long nY, tools::Long nX, sal_uInt8 cIndex)
831 {
832     maBitmap[(maBitmapPixelSize.Width() * nY + nX) * (HasAlphaChannel() ? 4 : 3)] = cIndex;
833     nLargestPixelIndex = std::max<int>(nLargestPixelIndex, cIndex);
834 }
835 
836 void TIFFReader::SetPixel(tools::Long nY, tools::Long nX, Color c)
837 {
838     auto p = maBitmap.data() + ((maBitmapPixelSize.Width() * nY + nX) * (HasAlphaChannel() ? 4 : 3));
839     *p = c.GetRed();
840     p++;
841     *p = c.GetGreen();
842     p++;
843     *p = c.GetBlue();
844     if (HasAlphaChannel())
845     {
846         p++;
847         *p = 0xff; // alpha
848     }
849 }
850 
851 void TIFFReader::SetPixelAlpha(tools::Long nY, tools::Long nX, sal_uInt8 nAlpha)
852 {
853     assert(HasAlphaChannel());
854     maBitmap[((maBitmapPixelSize.Width() * nY + nX) * 4) + 3] = nAlpha;
855 }
856 
857 bool TIFFReader::ConvertScanline(sal_Int32 nY)
858 {
859     sal_uInt32  nRed, nGreen, nBlue, ns, nVal;
860     sal_uInt8   nByteVal;
861 
862     if ( nDstBitsPerPixel == 24 )
863     {
864         if ( nBitsPerSample == 8 && nSamplesPerPixel >= 3 &&
865              nPlanes == 1 && nPhotometricInterpretation == 2 )
866         {
867             sal_uInt8* pt = getMapData(0);
868 
869             // are the values being saved as difference?
870             if ( 2 == nPredictor )
871             {
872                 sal_uInt8  nLRed = 0;
873                 sal_uInt8  nLGreen = 0;
874                 sal_uInt8  nLBlue = 0;
875                 sal_uInt8  nLAlpha = 0;
876                 for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel)
877                 {
878                     // The following computations rely on sal_uInt8 wrap-around when adding the
879                     // (unsigned) pt deltas; the "& 0xFF" is only conceptual, but helps prevent
880                     // sanitizer warnings:
881                     nLRed = (nLRed + pt[ 0 ]) & 0xFF;
882                     nLGreen = (nLGreen + pt[ 1 ]) & 0xFF;
883                     nLBlue = (nLBlue + pt[ 2 ]) & 0xFF;
884                     SetPixel(nY, nx, Color(nLRed, nLGreen, nLBlue));
885                     if (HasAlphaChannel())
886                     {
887                         nLAlpha = (nLAlpha + pt[ 3 ]) & 0xFF;
888                         SetPixelAlpha(nY, nx, ~nLAlpha);
889                     }
890                 }
891             }
892             else
893             {
894                 for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel)
895                 {
896                     SetPixel(nY, nx, Color(pt[0], pt[1], pt[2]));
897                     if (HasAlphaChannel())
898                     {
899                         sal_uInt8 nAlpha = pt[3];
900                         SetPixelAlpha(nY, nx, ~nAlpha);
901                     }
902                 }
903             }
904         }
905         else if (
906                ( nPhotometricInterpretation == 2 && nSamplesPerPixel >= 3 ) ||
907                ( nPhotometricInterpretation == 5 && nSamplesPerPixel == 3 )
908         )
909         {
910             if ( nMaxSampleValue > nMinSampleValue )
911             {
912                 sal_uInt32 nMinMax = nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue );
913                 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
914                 {
915                     if ( nPlanes < 3 )
916                     {
917                         nRed = GetBits( getMapData(0), ( nx * nSamplesPerPixel + 0 ) * nBitsPerSample, nBitsPerSample );
918                         nGreen = GetBits( getMapData(0), ( nx * nSamplesPerPixel + 1 ) * nBitsPerSample, nBitsPerSample );
919                         nBlue = GetBits( getMapData(0), ( nx * nSamplesPerPixel + 2 ) * nBitsPerSample, nBitsPerSample );
920                     }
921                     else
922                     {
923                         nRed = GetBits( getMapData(0), nx * nBitsPerSample, nBitsPerSample );
924                         nGreen = GetBits( getMapData(1), nx * nBitsPerSample, nBitsPerSample );
925                         nBlue = GetBits( getMapData(2), nx * nBitsPerSample, nBitsPerSample );
926                     }
927                     if (nPhotometricInterpretation == 2)
928                         SetPixel(nY, nx, Color(static_cast<sal_uInt8>(nRed - nMinMax), static_cast<sal_uInt8>(nGreen - nMinMax), static_cast<sal_uInt8>(nBlue - nMinMax)));
929                     else
930                         SetPixel(nY, nx, Color(255 - static_cast<sal_uInt8>(nRed - nMinMax), 255 - static_cast<sal_uInt8>(nGreen - nMinMax), 255 - static_cast<sal_uInt8>(nBlue - nMinMax)));
931                 }
932             }
933         }
934         else if( nPhotometricInterpretation == 5 && nSamplesPerPixel == 4 )
935         {
936             if ( nMaxSampleValue > nMinSampleValue )
937             {
938                 sal_uInt8   nSamp[ 4 ];
939                 sal_uInt8   nSampLast[ 4 ] = { 0, 0, 0, 0 };
940 
941                 for(sal_Int32 nx = 0; nx < nImageWidth; ++nx)
942                 {
943                     // are the values being saved as difference?
944                     if( 2 == nPredictor )
945                     {
946                         for( ns = 0; ns < 4; ns++ )
947                         {
948                             if( nPlanes < 3 )
949                                 nSampLast[ ns ] = nSampLast[ ns ] + static_cast<sal_uInt8>(GetBits( getMapData(0), ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample ));
950                             else
951                                 nSampLast[ ns ] = nSampLast[ ns ] + static_cast<sal_uInt8>(GetBits( getMapData(ns), nx * nBitsPerSample, nBitsPerSample ));
952                             nSamp[ ns ] = nSampLast[ ns ];
953                         }
954                     }
955                     else
956                     {
957                         for( ns = 0; ns < 4; ns++ )
958                         {
959                             if( nPlanes < 3 )
960                                 nSamp[ ns ] = static_cast<sal_uInt8>(GetBits( getMapData(0), ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample ));
961                             else
962                                 nSamp[ ns ]= static_cast<sal_uInt8>(GetBits( getMapData(ns), nx * nBitsPerSample, nBitsPerSample ));
963                         }
964                     }
965                     const tools::Long nBlack = nSamp[ 3 ];
966                     nRed = static_cast<sal_uInt8>(std::max<sal_Int32>( 0, 255 - ( ( static_cast<sal_Int32>(nSamp[ 0 ]) + nBlack - static_cast<sal_Int32>(nMinSampleValue << 1U ) ) *
967                                 255L/static_cast<sal_Int32>(nMaxSampleValue-nMinSampleValue) ) ));
968                     nGreen = static_cast<sal_uInt8>(std::max<sal_Int32>( 0, 255 - ( ( static_cast<sal_Int32>(nSamp[ 1 ]) + nBlack - static_cast<sal_Int32>(nMinSampleValue << 1U ) ) *
969                                 255L/static_cast<sal_Int32>(nMaxSampleValue-nMinSampleValue) ) ));
970                     nBlue = static_cast<sal_uInt8>(std::max<sal_Int32>( 0, 255 - ( ( static_cast<sal_Int32>(nSamp[ 2 ]) + nBlack - static_cast<sal_Int32>(nMinSampleValue << 1U ) ) *
971                                 255L/static_cast<sal_Int32>(nMaxSampleValue-nMinSampleValue) ) ));
972                     SetPixel(nY, nx, Color(static_cast<sal_uInt8>(nRed), static_cast<sal_uInt8>(nGreen), static_cast<sal_uInt8>(nBlue)));
973                 }
974             }
975         }
976     }
977     else if ( nSamplesPerPixel == 1 && ( nPhotometricInterpretation <= 1 || nPhotometricInterpretation == 3 ) )
978     {
979         if ( nMaxSampleValue > nMinSampleValue )
980         {
981             sal_uInt8* pt = getMapData(0);
982             sal_uInt8* ptend = pt + nBytesPerRow;
983 
984             if (nBitsPerSample > 8)
985             {
986                 sal_uInt32 nMinMax = nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue );
987                 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
988                 {
989                     nVal = GetBits(pt, nx * nSamplesPerPixel * nBitsPerSample, nBitsPerSample);
990                     SetPixel(nY, nx, static_cast<sal_uInt8>(nVal - nMinMax));
991                 }
992             }
993             else
994             {
995                 sal_uInt32 nMinMax = ( ( 1 << nDstBitsPerPixel ) - 1 ) / ( nMaxSampleValue - nMinSampleValue );
996                 sal_uInt8 nShift;
997 
998                 switch ( nDstBitsPerPixel )
999                 {
1000                     case 8 :
1001                     {
1002                         if (pt + nImageWidth > ptend)
1003                             return false;
1004 
1005                         if ( bByteSwap )
1006                         {
1007                             if ( nPredictor == 2 )
1008                             {
1009                                 sal_uInt8 nLast = 0;
1010                                 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
1011                                 {
1012                                     nLast += nx == 0 ? BYTESWAP( *pt++ ) : *pt++;
1013                                     SetPixel(nY, nx, nLast);
1014                                 }
1015                             }
1016                             else
1017                             {
1018                                 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
1019                                 {
1020                                     sal_uInt8 nLast = *pt++;
1021                                     SetPixel(nY, nx, static_cast<sal_uInt8>( (BYTESWAP(static_cast<sal_uInt32>(nLast)) - nMinSampleValue) * nMinMax ));
1022                                 }
1023                             }
1024                         }
1025                         else
1026                         {
1027                             if ( nPredictor == 2 )
1028                             {
1029                                 sal_uInt8 nLast = 0;
1030                                 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
1031                                 {
1032                                     nLast += *pt++;
1033                                     SetPixel(nY, nx, nLast);
1034                                 }
1035                             }
1036                             else
1037                             {
1038                                 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
1039                                 {
1040                                     SetPixel(nY, nx, static_cast<sal_uInt8>( (static_cast<sal_uInt32>(*pt++) - nMinSampleValue) * nMinMax ));
1041                                 }
1042                             }
1043                         }
1044                     }
1045                     break;
1046 
1047                     case 7 :
1048                     case 6 :
1049                     case 5 :
1050                     case 4 :
1051                     case 3 :
1052                     case 2 :
1053                     {
1054                         for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
1055                         {
1056                             nVal = ( GetBits( pt, nx * nBitsPerSample, nBitsPerSample ) - nMinSampleValue ) * nMinMax;
1057                             SetPixel(nY, nx, static_cast<sal_uInt8>(nVal));
1058                         }
1059                     }
1060                     break;
1061 
1062                     case 1 :
1063                     {
1064                         sal_uInt32 nByteCount = nImageWidth >> 3;
1065 
1066                         sal_uInt32 nBytesNeeded = nByteCount;
1067                         if (nImageWidth & 7)
1068                             ++nBytesNeeded;
1069                         if (pt + nBytesNeeded > ptend)
1070                             return false;
1071 
1072                         if ( bByteSwap )
1073                         {
1074                             sal_Int32 nx = 0;
1075                             while (nByteCount--)
1076                             {
1077                                 nByteVal = *pt++;
1078                                 SetPixel(nY, nx++, nByteVal & 1);
1079                                 nByteVal >>= 1;
1080                                 SetPixel(nY, nx++, nByteVal & 1);
1081                                 nByteVal >>= 1;
1082                                 SetPixel(nY, nx++, nByteVal & 1);
1083                                 nByteVal >>= 1;
1084                                 SetPixel(nY, nx++, nByteVal & 1);
1085                                 nByteVal >>= 1;
1086                                 SetPixel(nY, nx++, nByteVal & 1);
1087                                 nByteVal >>= 1;
1088                                 SetPixel(nY, nx++, nByteVal & 1);
1089                                 nByteVal >>= 1;
1090                                 SetPixel(nY, nx++, nByteVal & 1);
1091                                 nByteVal >>= 1;
1092                                 SetPixel(nY, nx++, nByteVal);
1093                             }
1094                             if ( nImageWidth & 7 )
1095                             {
1096                                 nByteVal = *pt++;
1097                                 while ( nx < nImageWidth )
1098                                 {
1099                                     SetPixel(nY, nx++, nByteVal & 1);
1100                                     nByteVal >>= 1;
1101                                 }
1102                             }
1103                         }
1104                         else
1105                         {
1106                             sal_Int32 nx = 7;
1107                             while (nByteCount--)
1108                             {
1109                                 nByteVal = *pt++;
1110                                 SetPixel(nY, nx, nByteVal & 1);
1111                                 nByteVal >>= 1;
1112                                 SetPixel(nY, --nx, nByteVal & 1);
1113                                 nByteVal >>= 1;
1114                                 SetPixel(nY, --nx, nByteVal & 1);
1115                                 nByteVal >>= 1;
1116                                 SetPixel(nY, --nx, nByteVal & 1);
1117                                 nByteVal >>= 1;
1118                                 SetPixel(nY, --nx, nByteVal & 1);
1119                                 nByteVal >>= 1;
1120                                 SetPixel(nY, --nx, nByteVal & 1);
1121                                 nByteVal >>= 1;
1122                                 SetPixel(nY, --nx, nByteVal & 1);
1123                                 nByteVal >>= 1;
1124                                 SetPixel(nY, --nx, nByteVal);
1125                                 nx += 15;
1126                             }
1127                             if ( nImageWidth & 7 )
1128                             {
1129                                 nx -= 7;
1130                                 nByteVal = *pt++;
1131                                 nShift = 7;
1132                                 while ( nx < nImageWidth )
1133                                 {
1134                                     SetPixel(nY, nx++, ( nByteVal >> nShift ) & 1);
1135                                     --nShift;
1136                                 }
1137                             }
1138                         }
1139                     }
1140                     break;
1141 
1142                     default :
1143                         return false;
1144                 }
1145             }
1146         }
1147     }
1148     else if ( ( nSamplesPerPixel == 2 ) && ( nBitsPerSample == 8 ) &&
1149         ( nPlanarConfiguration == 1 ) && aColorMap.empty() )               // grayscale + alpha
1150     {
1151         if ( nMaxSampleValue > nMinSampleValue )
1152         {
1153             sal_uInt8* pt = getMapData(0);
1154 
1155             if (nPredictor == 2)
1156             {
1157                 sal_uInt8 nLastPixel = 0;
1158                 sal_uInt8 nLastAlpha = 0;
1159                 for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += 2)
1160                 {
1161                     nLastPixel = (nLastPixel + pt[0]) & 0xFF;
1162                     SetPixel(nY, nx, nLastPixel);
1163 
1164                     nLastAlpha = (nLastAlpha + pt[1]) & 0xFF;
1165                     SetPixelAlpha(nY, nx, ~nLastAlpha);
1166                 }
1167             }
1168             else
1169             {
1170                 sal_uInt32 nMinMax = ( ( 1 << 8 /*nDstBitsPerPixel*/ ) - 1 ) / ( nMaxSampleValue - nMinSampleValue );
1171                 for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += 2)
1172                 {
1173                     SetPixel(nY, nx, static_cast<sal_uInt8>( (static_cast<sal_uInt32>(pt[0]) - nMinSampleValue) * nMinMax ));
1174                     sal_uInt8 nAlpha = static_cast<sal_uInt8>( (static_cast<sal_uInt32>(pt[1]) - nMinSampleValue) * nMinMax );
1175                     SetPixelAlpha(nY, nx, ~nAlpha);
1176                 }
1177             }
1178         }
1179     }
1180     else
1181         return false;
1182     return true;
1183 }
1184 
1185 void TIFFReader::MakePalCol()
1186 {
1187     if ( nDstBitsPerPixel <= 8 )
1188     {
1189         aColorMap.resize(256);
1190         if ( nPhotometricInterpretation <= 1 )
1191         {
1192             nNumColors = sal_uInt32(1) << nBitsPerSample;
1193             if ( nNumColors > 256 )
1194                 nNumColors = 256;
1195 
1196             if (nLargestPixelIndex >= static_cast<int>(nNumColors))
1197             {
1198                 SAL_WARN("filter.tiff", "palette has less entries that largest index used. Expanding palette to match");
1199                 nNumColors = nLargestPixelIndex + 1;
1200             }
1201 
1202             for (sal_uInt32 i = 0; i < nNumColors; ++i)
1203             {
1204                 sal_uInt32 nVal = ( i * 255 / ( nNumColors - 1 ) ) & 0xff;
1205                 sal_uInt32 n0RGB = nVal | ( nVal << 8 ) | ( nVal << 16 );
1206                 if ( nPhotometricInterpretation == 1 )
1207                     aColorMap[i] = n0RGB;
1208                 else
1209                     aColorMap[nNumColors - i - 1] = n0RGB;
1210             }
1211         }
1212         mvPalette.resize(std::max<sal_uInt16>(nNumColors, mvPalette.size()));
1213         for (sal_uInt32 i = 0; i < nNumColors; ++i)
1214         {
1215             mvPalette[i] = Color( static_cast<sal_uInt8>( aColorMap[ i ] >> 16 ),
1216                 static_cast<sal_uInt8>( aColorMap[ i ] >> 8 ), static_cast<sal_uInt8>(aColorMap[ i ]) );
1217         }
1218     }
1219 
1220     if ( !(fXResolution > 1.0 && fYResolution > 1.0 && ( nResolutionUnit == 2 || nResolutionUnit == 3 )) )
1221         return;
1222 
1223     sal_uInt32 nRX, nRY;
1224     if (nResolutionUnit==2)
1225     {
1226         nRX=static_cast<sal_uInt32>(fXResolution+0.5);
1227         nRY=static_cast<sal_uInt32>(fYResolution+0.5);
1228     }
1229     else
1230     {
1231         nRX=static_cast<sal_uInt32>(fXResolution*2.54+0.5);
1232         nRY=static_cast<sal_uInt32>(fYResolution*2.54+0.5);
1233     }
1234     MapMode aMapMode(MapUnit::MapInch,Point(0,0),Fraction(1,nRX),Fraction(1,nRY));
1235     maBitmapPrefMapMode = aMapMode;
1236     maBitmapPrefSize = Size(nImageWidth,nImageLength);
1237 }
1238 
1239 
1240 void TIFFReader::ReadHeader()
1241 {
1242     sal_uInt8 nbyte1(0), nbyte2(0);
1243     sal_uInt16 nushort(0);
1244 
1245     pTIFF->ReadUChar( nbyte1 );
1246     if ( nbyte1 == 'I' )
1247         pTIFF->SetEndian( SvStreamEndian::LITTLE );
1248     else
1249         pTIFF->SetEndian( SvStreamEndian::BIG );
1250 
1251     pTIFF->ReadUChar( nbyte2 ).ReadUInt16( nushort );
1252     if ( nbyte1 != nbyte2 || ( nbyte1 != 'I' && nbyte1 != 'M' ) || nushort != 0x002a )
1253         bStatus = false;
1254 }
1255 
1256 bool TIFFReader::HasAlphaChannel() const
1257 {
1258     /*There are undoubtedly more variants we could support, but keep it simple for now*/
1259     bool bRGBA = nDstBitsPerPixel == 24 &&
1260                  nBitsPerSample == 8 &&
1261                  nSamplesPerPixel >= 4 &&
1262                  nPlanes == 1 &&
1263                  nPhotometricInterpretation == 2;
1264     if (bRGBA)
1265         return true;
1266 
1267     // additionally support the format used in tdf#126460
1268     bool bGrayScaleAlpha = nDstBitsPerPixel == 8 &&
1269                            nBitsPerSample == 8 &&
1270                            nSamplesPerPixel == 2 &&
1271                            nPlanarConfiguration == 1;
1272 
1273     return bGrayScaleAlpha;
1274 }
1275 
1276 namespace
1277 {
1278     Color SanitizePaletteIndex(sal_uInt8 nIndex, const std::vector<Color>& rPalette)
1279     {
1280         const size_t nPaletteEntryCount = rPalette.size();
1281         if (nPaletteEntryCount && nIndex >= nPaletteEntryCount)
1282         {
1283             auto nSanitizedIndex = nIndex % nPaletteEntryCount;
1284             SAL_WARN_IF(nIndex != nSanitizedIndex, "vcl", "invalid colormap index: "
1285                         << static_cast<unsigned int>(nIndex) << ", colormap len is: "
1286                         << nPaletteEntryCount);
1287             nIndex = nSanitizedIndex;
1288         }
1289 
1290         return rPalette[nIndex];
1291     }
1292 }
1293 
1294 bool TIFFReader::ReadTIFF(SvStream & rTIFF, Graphic & rGraphic )
1295 {
1296     sal_uInt16  i, nNumTags(0), nTagType(0);
1297     sal_uInt32 nFirstIfd(0), nDataLen;
1298 
1299     bStatus = true;
1300 
1301     pTIFF = &rTIFF;
1302     sal_uInt64 nMaxPos = nOrigPos = pTIFF->Tell();
1303     nEndOfFile = nOrigPos + pTIFF->remainingSize();
1304     // number format of pTIFF at the beginning
1305     SvStreamEndian nOrigNumberFormat = pTIFF->GetEndian();
1306 
1307     // read header:
1308     ReadHeader();
1309 
1310     // read first IFD:
1311     pTIFF->ReadUInt32( nFirstIfd );
1312 
1313     if( !nFirstIfd || pTIFF->GetError() )
1314         bStatus = false;
1315 
1316     if ( bStatus )
1317     {
1318         sal_uInt32 nOffset = nFirstIfd;
1319 
1320         std::vector<sal_uInt32> aSeenOffsets;
1321         // calculate length of TIFF file
1322         do
1323         {
1324             if (std::find(aSeenOffsets.begin(), aSeenOffsets.end(), nOffset) != aSeenOffsets.end())
1325             {
1326                 SAL_WARN("filter.tiff", "Parsing error: " << nOffset <<
1327                          " already processed, format loop");
1328                 bStatus = false;
1329                 break;
1330             }
1331             pTIFF->Seek(nOrigPos + nOffset);
1332             aSeenOffsets.push_back(nOffset);
1333 
1334             if( pTIFF->GetError() )
1335             {
1336                 pTIFF->ResetError();
1337                 break;
1338             }
1339             nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1340 
1341             pTIFF->ReadUInt16( nNumTags );
1342 
1343             const size_t nMinRecordSize = 12;
1344             const size_t nMaxRecords = pTIFF->remainingSize() / nMinRecordSize;
1345             if (nNumTags > nMaxRecords)
1346             {
1347                 SAL_WARN("filter.tiff", "Parsing error: " << nMaxRecords <<
1348                          " max possible entries, but " << nNumTags << " claimed, truncating");
1349                 nNumTags = nMaxRecords;
1350             }
1351 
1352             // loop through tags:
1353             for( i = 0; i < nNumTags; i++ )
1354             {
1355                 nTagType = 0;
1356                 nDataType = USHRT_MAX;
1357                 nDataLen = 0;
1358                 nOffset = 0;
1359                 pTIFF->ReadUInt16( nTagType ).ReadUInt16( nDataType ).ReadUInt32( nDataLen ).ReadUInt32( nOffset );
1360 
1361                 if( DataTypeSize() * nDataLen > 4 )
1362                     nMaxPos = std::max(nOrigPos + nOffset + DataTypeSize() * nDataLen, nMaxPos);
1363             }
1364             pTIFF->ReadUInt32( nOffset );
1365             if (!pTIFF->good())
1366                 nOffset = 0;
1367 
1368             nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1369             if ( !nOffset )
1370                 nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1371         }
1372         while( nOffset );
1373 
1374         std::vector<sal_uInt32> aSeenIfds;
1375 
1376         for ( sal_uInt32 nNextIfd = nFirstIfd; nNextIfd && bStatus; )
1377         {
1378             if (std::find(aSeenIfds.begin(), aSeenIfds.end(), nNextIfd) != aSeenIfds.end())
1379             {
1380                 SAL_WARN("filter.tiff", "Parsing error: " << nNextIfd <<
1381                          " already processed, format loop");
1382                 bStatus = false;
1383                 break;
1384             }
1385             pTIFF->Seek(nOrigPos + nNextIfd);
1386             aSeenIfds.push_back(nNextIfd);
1387             {
1388                 bByteSwap = false;
1389 
1390                 nNewSubFile = 0;
1391                 nSubFile = 0;
1392                 nImageWidth = 0;
1393                 nImageLength = 0;
1394                 nBitsPerSample = 1;                         // default value according to the documentation
1395                 nCompression = 1;
1396                 nPhotometricInterpretation = 0;
1397                 nThresholding = 1;                          // default value according to the documentation
1398                 nCellWidth = 1;
1399                 nCellLength = 1;
1400                 nFillOrder = 1;                             // default value according to the documentation
1401                 nOrientation = 1;
1402                 nSamplesPerPixel = 1;                       // default value according to the documentation
1403                 nRowsPerStrip = 0xffffffff;                 // default value according to the documentation
1404                 nMinSampleValue = 0;                        // default value according to the documentation
1405                 nMaxSampleValue = 0;
1406                 fXResolution = 0.0;
1407                 fYResolution = 0.0;
1408                 nPlanarConfiguration = 1;
1409                 nGroup3Options = 0;                         // default value according to the documentation
1410                 nGroup4Options = 0;                         // default value according to the documentation
1411                 nResolutionUnit = 2;                        // default value according to the documentation
1412                 nPredictor = 1;
1413                 nNumColors = 0;
1414 
1415                 aStripOffsets.clear();
1416                 aStripByteCounts.clear();
1417                 for (auto& j : aMap)
1418                     j.clear();
1419 
1420                 pTIFF->ReadUInt16( nNumTags );
1421                 sal_uInt64 nPos = pTIFF->Tell();
1422 
1423                 const size_t nMinRecordSize = 8;
1424                 const size_t nMaxRecords = pTIFF->remainingSize() / nMinRecordSize;
1425                 if (nNumTags > nMaxRecords)
1426                 {
1427                     SAL_WARN("filter.tiff", "Parsing error: " << nMaxRecords <<
1428                              " max possible entries, but " << nNumTags << " claimed, truncating");
1429                     nNumTags = nMaxRecords;
1430                 }
1431 
1432                 for( i = 0; i < nNumTags; i++ )
1433                 {
1434                     pTIFF->ReadUInt16( nTagType ).ReadUInt16( nDataType ).ReadUInt32( nDataLen );
1435 
1436                     if( DataTypeSize() * nDataLen > 4 )
1437                     {
1438                         pTIFF->ReadUInt32( nOffset );
1439                         if (!checkSeek(*pTIFF, nOrigPos + nOffset))
1440                         {
1441                             bStatus = false;
1442                             break;
1443                         }
1444                     }
1445                     ReadTagData( nTagType, nDataLen );
1446                     nPos += 12; pTIFF->Seek( nPos );
1447 
1448                     if ( pTIFF->GetError() )
1449                         bStatus = false;
1450 
1451                     if ( !bStatus )
1452                         break;
1453                 }
1454                 pTIFF->ReadUInt32( nNextIfd );
1455                 if (!pTIFF->good())
1456                     nNextIfd = 0;
1457             }
1458             if ( !nBitsPerSample || ( nBitsPerSample > 32 ) )
1459                 bStatus = false;
1460             if (nImageWidth <= 0 || nImageLength <= 0)
1461                 bStatus = false;
1462             if ( bStatus )
1463             {
1464                 nLargestPixelIndex = -1;
1465                 if ( nMaxSampleValue == 0 )
1466                 {
1467                     if ( nBitsPerSample == 32 )         // sj: i93300, compiler bug, 1 << 32 gives 1 one 32bit windows platforms,
1468                         nMaxSampleValue = 0xffffffff;   // (up from 80286 only the lower 5 bits are used when shifting a 32bit register)
1469                     else
1470                     {
1471                         nMaxSampleValue = (1U << nBitsPerSample) - 1;
1472                     }
1473                 }
1474                 if ( nPhotometricInterpretation == 2 || nPhotometricInterpretation == 5 || nPhotometricInterpretation == 6 )
1475                     nDstBitsPerPixel = 24;
1476                 else if ( nBitsPerSample*nSamplesPerPixel <= 1 )
1477                     nDstBitsPerPixel = 1;
1478                 else if ( nBitsPerSample*nSamplesPerPixel <= 4 )
1479                     nDstBitsPerPixel = 4;
1480                 else
1481                     nDstBitsPerPixel = 8;
1482 
1483                 if ( nPlanarConfiguration == 1 )
1484                     nPlanes = 1;
1485                 else
1486                     nPlanes = nSamplesPerPixel;
1487 
1488                 bStatus = nPlanes != 0;
1489             }
1490 
1491             sal_uInt32 nDiv = GetRowsPerStrip();
1492 
1493             if ( bStatus )
1494             {
1495                 bStatus = (nDiv != 0);
1496             }
1497 
1498             if ( bStatus )
1499             {
1500                 if ( ( nFillOrder == 2 ) && ( nCompression != 5 ) )     // in the LZW mode bits are already being inverted
1501                     bByteSwap = true;
1502                 nStripsPerPlane = ( nImageLength - 1 ) / nDiv + 1;
1503                 bStatus = nSamplesPerPixel != 0;
1504             }
1505 
1506             if ( bStatus )
1507             {
1508                 sal_uInt64 nRowSize = (static_cast<sal_uInt64>(nImageWidth) * nSamplesPerPixel / nPlanes * nBitsPerSample + 7) >> 3;
1509                 auto nMaxSize = SAL_MAX_INT32 / SAL_N_ELEMENTS(aMap);
1510                 if (utl::ConfigManager::IsFuzzing())
1511                     nMaxSize /= 2;
1512                 if (nRowSize > nMaxSize)
1513                 {
1514                     SAL_WARN("filter.tiff", "Ludicrous row size of: " << nRowSize << " required");
1515                     bStatus = false;
1516                 }
1517                 else
1518                     nBytesPerRow = nRowSize;
1519             }
1520 
1521             if (bStatus)
1522             {
1523                 //sanity check consider ReadMap condition for last row and
1524                 //last plane
1525                 if (nCompression == 1 || nCompression == 32771)
1526                 {
1527                     sal_uInt32 nStripBytesPerRow;
1528                     if (nCompression == 1)
1529                         nStripBytesPerRow = nBytesPerRow;
1530                     else
1531                         nStripBytesPerRow = ( nBytesPerRow + 1 ) & 0xfffffffe;
1532                     sal_uInt32 np = nPlanes - 1;
1533                     if (np >= SAL_N_ELEMENTS(aMap))
1534                         bStatus = false;
1535                     sal_Int32 ny = nImageLength - 1;
1536                     sal_uInt32 nStrip(0);
1537                     nDiv = GetRowsPerStrip();
1538                     if (bStatus)
1539                         bStatus = nDiv != 0;
1540                     if (bStatus)
1541                     {
1542                         nStrip = ny / nDiv + np * nStripsPerPlane;
1543                         if (nStrip >= aStripOffsets.size())
1544                             bStatus = false;
1545                     }
1546                     if (bStatus)
1547                     {
1548                         auto nStart = aStripOffsets[ nStrip ] + ( ny % GetRowsPerStrip() ) * nStripBytesPerRow;
1549                         if (nStart > nEndOfFile)
1550                             bStatus = false;
1551                     }
1552                 }
1553                 else if (nCompression == 2 || nCompression == 3 || nCompression == 4)
1554                 {
1555                     if (nCompression == 3 && nGroup3Options & 0xfffffffa)
1556                         bStatus = false;
1557                     else if (nCompression == 4 && nGroup4Options & 0xffffffff)
1558                         bStatus = false;
1559                     sal_uInt32 np = nPlanes - 1;
1560                     if (np >= SAL_N_ELEMENTS(aMap))
1561                         bStatus = false;
1562                     sal_Int32 ny = nImageLength - 1;
1563                     sal_uInt32 nStrip(0);
1564                     nDiv = GetRowsPerStrip();
1565                     if (bStatus)
1566                         bStatus = nDiv != 0;
1567                     if (bStatus)
1568                     {
1569                         nStrip = ny / nDiv + np * nStripsPerPlane;
1570                         if (nStrip >= aStripOffsets.size())
1571                             bStatus = false;
1572                     }
1573                     if (bStatus)
1574                     {
1575                         auto nStart = aStripOffsets[nStrip];
1576                         if (nStart > nEndOfFile)
1577                             bStatus = false;
1578                     }
1579 
1580                     if (bStatus)
1581                     {
1582                         sal_uInt64 nTargetBits = nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes;
1583                         if (nTargetBits > SAL_MAX_UINT16)
1584                             bStatus = false;
1585                     }
1586                 }
1587                 else if (nCompression == 5)
1588                 {
1589                     sal_uInt32 np = nPlanes - 1;
1590                     if (np >= SAL_N_ELEMENTS(aMap))
1591                         bStatus = false;
1592                     sal_Int32 ny = nImageLength - 1;
1593                     sal_uInt32 nStrip(0);
1594                     nDiv = GetRowsPerStrip();
1595                     if (bStatus)
1596                         bStatus = nDiv != 0;
1597                     if (bStatus)
1598                     {
1599                         nStrip = ny / nDiv + np * nStripsPerPlane;
1600                         if (nStrip >= aStripOffsets.size())
1601                             bStatus = false;
1602                     }
1603                     if (bStatus)
1604                     {
1605                         auto nStart = aStripOffsets[nStrip];
1606                         if (nStart > nEndOfFile)
1607                             bStatus = false;
1608                     }
1609                 }
1610                 else if (nCompression == 32773)
1611                 {
1612                 }
1613                 else
1614                 {
1615                     bStatus = false;
1616                 }
1617             }
1618 
1619             sal_Int32 nImageDataSize(0);
1620             if (bStatus)
1621             {
1622                 if (o3tl::checked_multiply<sal_Int32>(nImageWidth, nImageLength, nImageDataSize) ||
1623                     o3tl::checked_multiply<sal_Int32>(nImageDataSize, (HasAlphaChannel() ? 4 : 3), nImageDataSize) ||
1624                     nImageDataSize > SAL_MAX_INT32/4)
1625                 {
1626                     bStatus = false;
1627                 }
1628             }
1629 
1630             if (bStatus)
1631             {
1632                 sal_Int32 nResult = 0;
1633                 if (utl::ConfigManager::IsFuzzing() && (o3tl::checked_multiply(nImageWidth, nImageLength, nResult) || nResult > 4000000))
1634                     bStatus = false;
1635             }
1636 
1637             if ( bStatus )
1638             {
1639                 maBitmapPixelSize = Size(nImageWidth, nImageLength);
1640                 maBitmap.resize(nImageDataSize, 0);
1641 
1642                 if (bStatus && ReadMap())
1643                 {
1644                     nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1645                     MakePalCol();
1646                     nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1647                     // convert palette-ized images to 24-bit color
1648                     if (!mvPalette.empty())
1649                     {
1650                         for (sal_Int32 nY = 0; nY < nImageLength; ++nY)
1651                         {
1652                             for (sal_Int32 nX = 0; nX < nImageWidth; ++nX)
1653                             {
1654                                 auto p = maBitmap.data() + ((maBitmapPixelSize.Width() * nY + nX) * (HasAlphaChannel() ? 4 : 3));
1655                                 auto c = SanitizePaletteIndex(*p, mvPalette);
1656                                 *p = c.GetRed();
1657                                 p++;
1658                                 *p = c.GetGreen();
1659                                 p++;
1660                                 *p = c.GetBlue();
1661                             }
1662                         }
1663                     }
1664                 }
1665                 else
1666                     bStatus = false;
1667 
1668                 if ( bStatus )
1669                 {
1670                     BitmapEx aImage = vcl::bitmap::CreateFromData(maBitmap.data(), nImageWidth, nImageLength,
1671                             nImageWidth * (HasAlphaChannel() ? 4 : 3), // scanline bytes
1672                             HasAlphaChannel() ? vcl::PixelFormat::N32_BPP : vcl::PixelFormat::N24_BPP);
1673                     aImage.SetPrefMapMode(maBitmapPrefMapMode);
1674                     aImage.SetPrefSize(maBitmapPrefSize);
1675 
1676                     AnimationBitmap aAnimationBitmap( aImage, Point( 0, 0 ), maBitmapPixelSize,
1677                                                       ANIMATION_TIMEOUT_ON_CLICK, Disposal::Back );
1678 
1679                     aAnimation.Insert( aAnimationBitmap );
1680                 }
1681             }
1682 
1683             // Clean up:
1684             for (auto& j : aMap)
1685                 j.clear();
1686             aColorMap.clear();
1687             aStripOffsets.clear();
1688             aStripByteCounts.clear();
1689         }
1690     }
1691 
1692     // seek to end of TIFF if succeeded
1693     pTIFF->SetEndian( nOrigNumberFormat );
1694     pTIFF->Seek(bStatus ? STREAM_SEEK_TO_END: nOrigPos);
1695 
1696     if ( aAnimation.Count() )
1697     {
1698         if ( aAnimation.Count() == 1 )
1699             rGraphic = aAnimation.GetBitmapEx();
1700         else
1701             rGraphic = aAnimation;  //aBitmap;
1702 
1703         return true;
1704     }
1705     else
1706         return false;
1707 }
1708 
1709 bool ImportTiffGraphicImport(SvStream & rStream, Graphic & rGraphic)
1710 {
1711     TIFFReader aTIFFReader;
1712     try
1713     {
1714         return aTIFFReader.ReadTIFF(rStream, rGraphic);
1715     }
1716     catch (const std::bad_alloc &)
1717     {
1718         return false;
1719     }
1720 }
1721 
1722 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1723