tdf#115863: fix TIFF import
[LibreOffice.git] / filter / source / graphicfilter / itiff / itiff.cxx
blobe19d6b2d5f9c8f893b69a683e0314002c99e4457
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <memory>
21 #include <sal/config.h>
23 #include <vcl/FilterConfigItem.hxx>
24 #include <vcl/graph.hxx>
25 #include <vcl/BitmapTools.hxx>
26 #include <vcl/animate.hxx>
27 #include <tools/fract.hxx>
28 #include "lzwdecom.hxx"
29 #include "ccidecom.hxx"
31 namespace {
33 template< typename T > T BYTESWAP(T nByte) {
34 return ( nByte << 7 ) | ( ( nByte & 2 ) << 5 ) | ( ( nByte & 4 ) << 3 ) |
35 ( ( nByte & 8 ) << 1 ) | ( ( nByte & 16 ) >> 1 ) |
36 ( ( nByte & 32 ) >> 3 ) | ( ( nByte & 64 ) >> 5 ) |
37 ( ( nByte & 128 ) >> 7 );
42 //============================ TIFFReader ==================================
44 class TIFFReader
47 private:
49 bool bStatus; // Whether until now no error occurred
50 Animation aAnimation;
52 SvStream* pTIFF; // the TIFF file that should be read
53 std::vector<sal_uInt8> maBitmap;
54 Size maBitmapPixelSize;
55 std::vector<Color> mvPalette;
56 MapMode maBitmapPrefMapMode;
57 Size maBitmapPrefSize;
58 sal_uInt16 nDstBitsPerPixel;
59 int nLargestPixelIndex;
61 sal_uInt64 nOrigPos; // start position in pTIFF
62 sal_uInt64 nEndOfFile; // end of file position in pTIFF
65 sal_uInt16 nDataType;
66 // Data taken from the TIFF tags:
67 bool bByteSwap; // sal_True if bits 0..7 -> 7..0 should get converted ( FILLORDER = 2 );
69 sal_uInt32 nNewSubFile;
70 sal_uInt32 nSubFile;
71 sal_Int32 nImageWidth; // picture width in pixels
72 sal_Int32 nImageLength; // picture height in pixels
73 sal_uInt32 nBitsPerSample; // bits per pixel per layer
74 sal_uInt32 nCompression; // kind of compression
75 sal_uInt32 nPhotometricInterpretation;
76 sal_uInt32 nThresholding;
77 sal_uInt32 nCellWidth;
78 sal_uInt32 nCellLength;
79 sal_uInt32 nFillOrder;
80 std::vector<sal_uInt64> aStripOffsets; // field of offsets to the Bitmap-Data-"Strips"
81 sal_uInt32 nOrientation;
82 sal_uInt32 nSamplesPerPixel; // number of layers
83 sal_uInt32 nRowsPerStrip; // if it's not compressed: number of rows per Strip
84 std::vector<sal_uInt32> aStripByteCounts; // if compressed (in a certain way): size of the strips
85 sal_uInt32 nMinSampleValue;
86 sal_uInt32 nMaxSampleValue;
87 double fXResolution; // X-resolution or 0.0
88 double fYResolution; // Y-resolution or 0.0
89 sal_uInt32 nPlanarConfiguration;
90 sal_uInt32 nGroup3Options;
91 sal_uInt32 nGroup4Options;
92 sal_uInt32 nResolutionUnit; // unit of fX/YResolution: 1=unknown, 2(default)=inch, 3=cm
93 sal_uInt32 nPredictor;
94 std::vector<sal_uInt32> aColorMap; // color palette
95 sal_uInt32 nNumColors; // number of colors within the color palette
97 sal_uInt32 nPlanes; // number of layers within the Tiff file
98 sal_uInt32 nStripsPerPlane; // number of Strips per layer
99 sal_uInt32 nBytesPerRow; // Bytes per line per Layer in the Tiff file ( uncompressed )
100 std::vector<sal_uInt8> aMap[4]; // temporary Scanline
103 sal_uInt32 DataTypeSize();
104 sal_uInt32 ReadIntData();
105 double ReadDoubleData();
107 void ReadHeader();
108 void ReadTagData( sal_uInt16 nTagType, sal_uInt32 nDataLen );
110 sal_uInt8* getMapData(sal_uInt32 np);
112 bool ReadMap();
113 // reads/decompresses the bitmap data and fills aMap
115 sal_uInt32 GetBits(const sal_uInt8 * pSrc, sal_uInt32 nBitsPos, sal_uInt32 nBitsCount);
116 // fetches BitsCount bits from pSrc[..] at the position nBitsPos
118 void MakePalCol();
119 // Create the bitmap from the temporary bitmap aMap
120 // and partly deletes aMap while doing this.
122 bool ConvertScanline(sal_Int32 nY);
123 // converts a Scanline to the Windows-BMP format
125 bool HasAlphaChannel() const;
127 void SetPixel(long nY, long nX, sal_uInt8 cIndex);
128 void SetPixel(long nY, long nX, Color c);
129 void SetPixelAlpha(long nY, long nX, sal_uInt8 nAlpha);
131 public:
133 TIFFReader()
134 : bStatus(false)
135 , pTIFF(nullptr)
136 , nDstBitsPerPixel(0)
137 , nLargestPixelIndex(-1)
138 , nOrigPos(0)
139 , nEndOfFile(0)
140 , nDataType(0)
141 , bByteSwap(false)
142 , nNewSubFile(0)
143 , nSubFile(0)
144 , nImageWidth(0)
145 , nImageLength(0)
146 , nBitsPerSample(1)
147 , nCompression(1)
148 , nPhotometricInterpretation(0)
149 , nThresholding(1)
150 , nCellWidth(1)
151 , nCellLength(1)
152 , nFillOrder(1)
153 , nOrientation(1)
154 , nSamplesPerPixel(1)
155 , nRowsPerStrip(0xffffffff)
156 , nMinSampleValue(0)
157 , nMaxSampleValue(0)
158 , fXResolution(0.0)
159 , fYResolution(0.0)
160 , nPlanarConfiguration(1)
161 , nGroup3Options(0)
162 , nGroup4Options(0)
163 , nResolutionUnit(2)
164 , nPredictor(0)
165 , nNumColors(0)
166 , nPlanes(0)
167 , nStripsPerPlane(0)
168 , nBytesPerRow(0)
172 sal_uInt32 GetRowsPerStrip() const
174 //Rows Per Strip:
176 //(TIFF format only) The number of rows of pixels per strip to use for
177 //encoding the TIFF image. A value greater than zero specifies the
178 //number of rows per strip. A value of 0 sets the rows per strip equal
179 //to the image length, resulting in a single strip. A value of -1 (the
180 //default) sets the rows per strip equal to infinity, resulting in a
181 //single strip.
182 return nRowsPerStrip == 0 ? nImageLength : nRowsPerStrip;
185 bool ReadTIFF( SvStream & rTIFF, Graphic & rGraphic );
188 //=================== Methods of TIFFReader ==============================
190 sal_uInt32 TIFFReader::DataTypeSize()
192 sal_uInt32 nSize;
193 switch ( nDataType )
195 case 1 : // BYTE
196 case 2 : // ASCII
197 case 6 : // SIGNED Byte
198 case 7 : // UNDEFINED
199 nSize = 1;
200 break;
201 case 3 : // UINT16
202 case 8 : // INT16
203 nSize = 2;
204 break;
205 case 4 : // UINT32
206 case 9 : // INT32
207 case 11 : // FLOAT
208 nSize = 4;
209 break;
210 case 5 : // RATIONAL
211 case 10 : // SIGNED RATIONAL
212 case 12 : // DOUBLE
213 nSize = 8;
214 break;
215 default:
216 pTIFF->SetError(SVSTREAM_FILEFORMAT_ERROR);
217 nSize=1;
219 return nSize;
222 sal_uInt32 TIFFReader::ReadIntData()
224 double nDOUBLE(0.0);
225 float nFLOAT(0);
226 sal_uInt32 nUINT32a(0), nUINT32b(0);
227 sal_Int32 nINT32(0);
228 sal_uInt16 nUINT16(0);
229 sal_Int16 nINT16(0);
230 sal_uInt8 nBYTE(0);
231 char nCHAR(0);
233 switch( nDataType )
235 case 0 : //??
236 case 1 :
237 case 2 :
238 case 7 :
239 pTIFF->ReadUChar( nBYTE );
240 nUINT32a = nBYTE;
241 break;
242 case 3 :
243 pTIFF->ReadUInt16( nUINT16 );
244 nUINT32a = nUINT16;
245 break;
246 case 9 :
247 case 4 :
248 pTIFF->ReadUInt32( nUINT32a );
249 break;
250 case 5 :
251 pTIFF->ReadUInt32( nUINT32a ).ReadUInt32( nUINT32b );
252 if ( nUINT32b != 0 )
253 nUINT32a /= nUINT32b;
254 break;
255 case 6 :
256 pTIFF->ReadChar( nCHAR );
257 nUINT32a = static_cast<sal_Int32>(nCHAR);
258 break;
259 case 8 :
260 pTIFF->ReadInt16( nINT16 );
261 nUINT32a = static_cast<sal_Int32>(nINT16);
262 break;
263 case 10 :
264 pTIFF->ReadUInt32( nUINT32a ).ReadInt32( nINT32 );
265 if ( nINT32 != 0 )
266 nUINT32a /= nINT32;
267 break;
268 case 11 :
269 pTIFF->ReadFloat( nFLOAT );
270 nUINT32a = static_cast<sal_Int32>(nFLOAT);
271 break;
272 case 12 :
273 pTIFF->ReadDouble( nDOUBLE );
274 nUINT32a = static_cast<sal_Int32>(nDOUBLE);
275 break;
276 default:
277 pTIFF->ReadUInt32( nUINT32a );
278 break;
280 return nUINT32a;
283 double TIFFReader::ReadDoubleData()
285 double nd;
287 if ( nDataType == 5 )
289 sal_uInt32 nulong(0);
290 pTIFF->ReadUInt32( nulong );
291 nd = static_cast<double>(nulong);
292 nulong = 0;
293 pTIFF->ReadUInt32( nulong );
294 if ( nulong != 0 )
295 nd /= static_cast<double>(nulong);
297 else
298 nd = static_cast<double>(ReadIntData());
299 return nd;
302 void TIFFReader::ReadTagData( sal_uInt16 nTagType, sal_uInt32 nDataLen)
304 if ( !bStatus )
305 return;
307 switch ( nTagType )
309 case 0x00fe: // New Sub File
310 nNewSubFile = ReadIntData();
311 SAL_INFO("filter.tiff","NewSubFile: " << nNewSubFile);
312 break;
314 case 0x00ff: // Sub File
315 nSubFile = ReadIntData();
316 SAL_INFO("filter.tiff","SubFile: " << nSubFile);
317 break;
319 case 0x0100: // Image Width
320 nImageWidth = ReadIntData();
321 SAL_INFO("filter.tiff","ImageWidth: " << nImageWidth);
322 break;
324 case 0x0101: // Image Length
325 nImageLength = ReadIntData();
326 SAL_INFO("filter.tiff","ImageLength: " << nImageLength);
327 break;
329 case 0x0102: // Bits Per Sample
330 nBitsPerSample = ReadIntData();
331 SAL_INFO("filter.tiff","BitsPerSample: " << nBitsPerSample);
332 if ( nBitsPerSample >= 32 ) // 32 bit and larger samples are not supported
333 bStatus = false;
334 break;
336 case 0x0103: // Compression
337 nCompression = ReadIntData();
338 SAL_INFO("filter.tiff","Compression: " << nCompression);
339 break;
341 case 0x0106: // Photometric Interpretation
342 nPhotometricInterpretation = ReadIntData();
343 SAL_INFO("filter.tiff","PhotometricInterpretation: " << nPhotometricInterpretation);
344 break;
346 case 0x0107: // Thresholding
347 nThresholding = ReadIntData();
348 SAL_INFO("filter.tiff","Thresholding: " << nThresholding);
349 break;
351 case 0x0108: // Cell Width
352 nCellWidth = ReadIntData();
353 break;
355 case 0x0109: // Cell Length
356 nCellLength = ReadIntData();
357 break;
359 case 0x010a: // Fill Order
360 nFillOrder = ReadIntData();
361 SAL_INFO("filter.tiff","FillOrder: " << nFillOrder);
362 break;
364 case 0x0111: { // Strip Offset(s)
365 size_t nOldNumSO = aStripOffsets.size();
366 nDataLen += nOldNumSO;
367 size_t const nMaxAllocAllowed = SAL_MAX_UINT32 / sizeof(sal_uInt32);
368 size_t nMaxRecordsAvailable = pTIFF->remainingSize() / DataTypeSize();
369 if (nDataLen > nOldNumSO && nDataLen < nMaxAllocAllowed &&
370 (nDataLen - nOldNumSO) <= nMaxRecordsAvailable)
374 aStripOffsets.resize(nDataLen);
375 for (size_t i = 0; i < nOldNumSO; ++i)
376 aStripOffsets[i] += nOrigPos;
377 for (size_t i = nOldNumSO; i < aStripOffsets.size(); ++i)
378 aStripOffsets[i] = ReadIntData() + nOrigPos;
380 catch (const std::bad_alloc &)
382 aStripOffsets.clear();
385 SAL_INFO("filter.tiff","StripOffsets (Number:) " << nDataLen);
386 break;
388 case 0x0112: // Orientation
389 nOrientation = ReadIntData();
390 SAL_INFO("filter.tiff","Orientation: " << nOrientation);
391 break;
393 case 0x0115: // Samples Per Pixel
394 nSamplesPerPixel = ReadIntData();
395 SAL_INFO("filter.tiff","SamplesPerPixel: " << nSamplesPerPixel);
396 break;
398 case 0x0116: // Rows Per Strip
399 nRowsPerStrip = ReadIntData();
400 SAL_INFO("filter.tiff","RowsPerStrip: " << nRowsPerStrip);
401 break;
403 case 0x0117: { // Strip Byte Counts
404 size_t nOldNumSBC = aStripByteCounts.size();
405 nDataLen += nOldNumSBC;
406 size_t const nMaxAllocAllowed = SAL_MAX_UINT32 / sizeof(sal_uInt32);
407 size_t nMaxRecordsAvailable = pTIFF->remainingSize() / DataTypeSize();
408 if (nDataLen > nOldNumSBC && nDataLen < nMaxAllocAllowed &&
409 (nDataLen - nOldNumSBC) <= nMaxRecordsAvailable)
413 aStripByteCounts.resize(nDataLen);
414 for (size_t i = nOldNumSBC; i < aStripByteCounts.size(); ++i)
415 aStripByteCounts[i] = ReadIntData();
417 catch (const std::bad_alloc &)
419 aStripByteCounts.clear();
422 SAL_INFO("filter.tiff","StripByteCounts (Number:) " << nDataLen);
423 break;
425 case 0x0118: // Min Sample Value
426 nMinSampleValue = ReadIntData();
427 SAL_INFO("filter.tiff","MinSampleValue: " << nMinSampleValue);
428 break;
430 case 0x0119: // Max Sample Value
431 nMaxSampleValue = ReadIntData();
432 SAL_INFO("filter.tiff","MaxSampleValue: " << nMaxSampleValue);
433 break;
435 case 0x011a: // X Resolution
436 fXResolution = ReadDoubleData();
437 break;
439 case 0x011b: // Y Resolution
440 fYResolution = ReadDoubleData();
441 break;
443 case 0x011c: // Planar Configuration
444 nPlanarConfiguration = ReadIntData();
445 SAL_INFO("filter.tiff","PlanarConfiguration: " << nPlanarConfiguration);
446 break;
448 case 0x0124: // Group 3 Options
449 nGroup3Options = ReadIntData();
450 SAL_INFO("filter.tiff","Group3Options: " << nGroup3Options);
451 break;
453 case 0x0125: // Group 4 Options
454 nGroup4Options = ReadIntData();
455 SAL_INFO("filter.tiff","Group4Options: " << nGroup4Options);
456 break;
458 case 0x0128: // Resolution Unit
459 nResolutionUnit = ReadIntData();
460 break;
462 case 0x013d: // Predictor
463 nPredictor = ReadIntData();
464 SAL_INFO("filter.tiff","Predictor: " << nPredictor);
465 break;
467 case 0x0140: { // Color Map
468 sal_uInt16 nVal;
469 nNumColors = (sal_uInt32(1) << nBitsPerSample);
470 if ( nDataType == 3 && nNumColors <= 256)
472 aColorMap.resize(256);
473 for (sal_uInt32 i = 0; i < nNumColors; ++i)
474 aColorMap[i] = 0;
475 for (sal_uInt32 i = 0; i < nNumColors; ++i)
477 pTIFF->ReadUInt16( nVal );
478 aColorMap[i] |= ( static_cast<sal_uInt32>(nVal) << 8 ) & 0x00ff0000;
480 for (sal_uInt32 i = 0; i < nNumColors; ++i)
482 pTIFF->ReadUInt16( nVal );
483 aColorMap[i] |= static_cast<sal_uInt32>(nVal) & 0x0000ff00;
485 for (sal_uInt32 i = 0; i < nNumColors; ++i)
487 pTIFF->ReadUInt16( nVal );
488 aColorMap[i] |= ( static_cast<sal_uInt32>(nVal) >> 8 ) & 0x000000ff;
491 else
492 bStatus = false;
493 SAL_INFO("filter.tiff","ColorMap (number of colors): " << nNumColors);
494 break;
497 case 0x0153: { // SampleFormat
498 sal_uInt32 nSampleFormat = ReadIntData();
499 if ( nSampleFormat == 3 ) // IEEE floating point samples are not supported yet
500 bStatus = false;
501 break;
505 if ( pTIFF->GetError() )
506 bStatus = false;
509 sal_uInt8* TIFFReader::getMapData(sal_uInt32 np)
511 aMap[np].resize(nBytesPerRow);
512 return aMap[np].data();
515 bool TIFFReader::ReadMap()
517 //when fuzzing with a max len set, max decompress to 2000 times that limit
518 static size_t nMaxAllowedDecompression = [](const char* pEnv) { size_t nRet = pEnv ? std::atoi(pEnv) : 0; return nRet * 2000; }(std::getenv("FUZZ_MAX_INPUT_LEN"));
519 size_t nTotalDataRead = 0;
521 if ( nCompression == 1 || nCompression == 32771 )
523 sal_uInt32 nStripBytesPerRow;
525 if ( nCompression == 1 )
526 nStripBytesPerRow = nBytesPerRow;
527 else
528 nStripBytesPerRow = ( nBytesPerRow + 1 ) & 0xfffffffe;
529 for (sal_Int32 ny = 0; ny < nImageLength; ++ny)
531 for (sal_uInt32 np = 0; np < nPlanes; ++np)
533 if (np >= SAL_N_ELEMENTS(aMap))
534 return false;
535 sal_uInt32 nStrip = ny / GetRowsPerStrip() + np * nStripsPerPlane;
536 if ( nStrip >= aStripOffsets.size())
537 return false;
538 pTIFF->Seek( aStripOffsets[ nStrip ] + ( ny % GetRowsPerStrip() ) * nStripBytesPerRow );
539 pTIFF->ReadBytes(getMapData(np), nBytesPerRow);
540 if (!pTIFF->good())
541 return false;
543 if ( !ConvertScanline( ny ) )
544 return false;
547 else if ( nCompression == 2 || nCompression == 3 || nCompression == 4 )
549 sal_uInt32 nOptions;
550 if ( nCompression == 2 )
552 nOptions = CCI_OPTION_BYTEALIGNROW;
554 else if ( nCompression == 3 )
556 nOptions = CCI_OPTION_EOL;
557 if ( nGroup3Options & 0x00000001 )
558 nOptions |= CCI_OPTION_2D;
559 if ( nGroup3Options & 0x00000004 )
560 nOptions |= CCI_OPTION_BYTEALIGNEOL;
561 if ( nGroup3Options & 0xfffffffa )
562 return false;
564 else
565 { // nCompression==4
566 nOptions = CCI_OPTION_2D;
567 if ( nGroup4Options & 0xffffffff )
568 return false;
570 if ( nFillOrder == 2 )
572 nOptions |= CCI_OPTION_INVERSEBITORDER;
573 bByteSwap = false;
575 sal_uInt32 nStrip = 0;
576 if (nStrip >= aStripOffsets.size())
577 return false;
578 sal_uInt64 nOffset = aStripOffsets[nStrip];
579 if (nOffset > nEndOfFile)
580 return false;
581 pTIFF->Seek(aStripOffsets[nStrip]);
583 CCIDecompressor aCCIDecom( nOptions, nImageWidth );
585 aCCIDecom.StartDecompression( *pTIFF );
587 const bool bHasAlphaChannel = HasAlphaChannel();
588 for (sal_Int32 ny = 0; ny < nImageLength; ++ny)
590 bool bDifferentToPrev = ny == 0;
591 for (sal_uInt32 np = 0; np < nPlanes; ++np)
593 if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip )
595 nStrip=ny/GetRowsPerStrip()+np*nStripsPerPlane;
596 if (nStrip >= aStripOffsets.size())
597 return false;
598 nOffset = aStripOffsets[nStrip];
599 if (nOffset > nEndOfFile)
600 return false;
601 pTIFF->Seek(nOffset);
602 aCCIDecom.StartDecompression( *pTIFF );
604 if (np >= SAL_N_ELEMENTS(aMap))
605 return false;
606 DecompressStatus aResult = aCCIDecom.DecompressScanline(getMapData(np), nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes, np + 1 == nPlanes);
607 if (!aResult.m_bSuccess)
608 return false;
609 bDifferentToPrev |= !aResult.m_bBufferUnchanged;
610 if ( pTIFF->GetError() )
611 return false;
612 nTotalDataRead += nBytesPerRow;
613 if (nMaxAllowedDecompression && nTotalDataRead > nMaxAllowedDecompression)
614 return false;
616 if (!bDifferentToPrev)
618 //if the buffer for this line didn't change, then just copy the
619 //previous scanline instead of painfully decoding and setting
620 //each pixel one by one again
621 const int nColorSize = bHasAlphaChannel ? 4 : 3;
622 memcpy( maBitmap.data() + (ny * maBitmapPixelSize.Width()) * nColorSize,
623 maBitmap.data() + ((ny-1) * maBitmapPixelSize.Width()) * nColorSize,
624 maBitmapPixelSize.Width() * nColorSize);
626 else
628 if (!ConvertScanline(ny))
629 return false;
633 else if ( nCompression == 5 )
635 LZWDecompressor aLZWDecom;
636 sal_uInt32 nStrip(0);
637 if (nStrip >= aStripOffsets.size())
638 return false;
639 pTIFF->Seek(aStripOffsets[nStrip]);
640 aLZWDecom.StartDecompression(*pTIFF);
641 for (sal_Int32 ny = 0; ny < nImageLength; ++ny)
643 for (sal_uInt32 np = 0; np < nPlanes; ++np)
645 if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip )
647 nStrip = ny / GetRowsPerStrip() + np * nStripsPerPlane;
648 if (nStrip >= aStripOffsets.size())
649 return false;
650 pTIFF->Seek(aStripOffsets[nStrip]);
651 aLZWDecom.StartDecompression(*pTIFF);
653 if (np >= SAL_N_ELEMENTS(aMap))
654 return false;
655 if ( ( aLZWDecom.Decompress(getMapData(np), nBytesPerRow) != nBytesPerRow ) || pTIFF->GetError() )
656 return false;
659 nTotalDataRead += nBytesPerRow;
660 if (nMaxAllowedDecompression && nTotalDataRead > nMaxAllowedDecompression)
661 return false;
663 if ( !ConvertScanline( ny ) )
664 return false;
667 else if ( nCompression == 32773 )
669 sal_uInt32 nStrip(0);
670 if (nStrip >= aStripOffsets.size())
671 return false;
672 pTIFF->Seek(aStripOffsets[nStrip]);
673 for (sal_Int32 ny = 0; ny < nImageLength; ++ny)
675 for (sal_uInt32 np = 0; np < nPlanes; ++np)
677 if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip )
679 nStrip=ny/GetRowsPerStrip()+np*nStripsPerPlane;
680 if (nStrip >= aStripOffsets.size())
681 return false;
682 pTIFF->Seek(aStripOffsets[nStrip]);
684 sal_uInt32 nRowBytesLeft = nBytesPerRow;
685 if (np >= SAL_N_ELEMENTS(aMap))
686 return false;
687 sal_uInt8* pdst = getMapData(np);
690 sal_uInt8 nRecHeader(0);
691 pTIFF->ReadUChar(nRecHeader);
692 sal_uInt32 nRecCount;
693 if ((nRecHeader&0x80)==0)
695 nRecCount=0x00000001 + static_cast<sal_uInt32>(nRecHeader);
696 if ( nRecCount > nRowBytesLeft )
697 return false;
698 pTIFF->ReadBytes(pdst, nRecCount);
699 if (!pTIFF->good())
700 return false;
701 pdst+=nRecCount;
702 nRowBytesLeft-=nRecCount;
704 else if ( nRecHeader != 0x80 )
706 nRecCount = 0x000000101 - static_cast<sal_uInt32>(nRecHeader);
707 if ( nRecCount > nRowBytesLeft )
709 nRecCount = nRowBytesLeft;
711 sal_uInt8 nRecData(0);
712 pTIFF->ReadUChar( nRecData );
713 for (sal_uInt32 i = 0; i < nRecCount; ++i)
714 *(pdst++) = nRecData;
715 nRowBytesLeft -= nRecCount;
717 } while ( nRowBytesLeft != 0 );
718 if ( pTIFF->GetError() )
719 return false;
721 if ( !ConvertScanline( ny ) )
722 return false;
725 else
726 return false;
727 return true;
730 sal_uInt32 TIFFReader::GetBits( const sal_uInt8 * pSrc, sal_uInt32 nBitsPos, sal_uInt32 nBitsCount)
732 sal_uInt32 nRes;
733 if ( bByteSwap )
735 pSrc += ( nBitsPos >> 3 );
736 nBitsPos &= 7;
737 sal_uInt8 nDat = *pSrc;
738 nRes = static_cast<sal_uInt32>( BYTESWAP( nDat ) & ( 0xff >> nBitsPos ) );
740 if ( nBitsCount <= 8 - nBitsPos )
742 nRes >>= ( 8 - nBitsPos - nBitsCount );
744 else
746 pSrc++;
747 nBitsCount -= 8 - nBitsPos;
748 while ( nBitsCount >= 8 )
750 nDat = *(pSrc++);
751 nRes = ( nRes << 8 ) | static_cast<sal_uInt32>(BYTESWAP( nDat ));
752 nBitsCount -= 8;
754 if ( nBitsCount > 0 )
756 nDat = *pSrc;
757 nRes = ( nRes << nBitsCount ) | (static_cast<sal_uInt32>(BYTESWAP(nDat))>>(8-nBitsCount));
761 else
763 pSrc += ( nBitsPos >> 3 );
764 nBitsPos &= 7;
765 nRes = static_cast<sal_uInt32>((*pSrc)&(0xff>>nBitsPos));
766 if ( nBitsCount <= 8 - nBitsPos )
768 nRes >>= ( 8 - nBitsPos - nBitsCount );
770 else
772 pSrc++;
773 nBitsCount -= 8 - nBitsPos;
774 while ( nBitsCount >= 8 )
776 nRes = ( nRes << 8 ) | static_cast<sal_uInt32>(*(pSrc++));
777 nBitsCount -= 8;
779 if ( nBitsCount > 0 )
780 nRes = ( nRes << nBitsCount ) | (static_cast<sal_uInt32>(*pSrc)>>(8-nBitsCount));
783 return nRes;
786 void TIFFReader::SetPixel(long nY, long nX, sal_uInt8 cIndex)
788 maBitmap[(maBitmapPixelSize.Width() * nY + nX) * (HasAlphaChannel() ? 4 : 3)] = cIndex;
789 nLargestPixelIndex = std::max<int>(nLargestPixelIndex, cIndex);
792 void TIFFReader::SetPixel(long nY, long nX, Color c)
794 auto p = maBitmap.data() + ((maBitmapPixelSize.Width() * nY + nX) * (HasAlphaChannel() ? 4 : 3));
795 *p = c.GetRed();
796 p++;
797 *p = c.GetGreen();
798 p++;
799 *p = c.GetBlue();
800 if (HasAlphaChannel())
802 p++;
803 *p = 0xff; // alpha
807 void TIFFReader::SetPixelAlpha(long nY, long nX, sal_uInt8 nAlpha)
809 assert(HasAlphaChannel());
810 maBitmap[((maBitmapPixelSize.Width() * nY + nX) * 4) + 3] = nAlpha;
813 bool TIFFReader::ConvertScanline(sal_Int32 nY)
815 sal_uInt32 nRed, nGreen, nBlue, ns, nVal;
816 sal_uInt8 nByteVal;
818 if ( nDstBitsPerPixel == 24 )
820 if ( nBitsPerSample == 8 && nSamplesPerPixel >= 3 &&
821 nPlanes == 1 && nPhotometricInterpretation == 2 )
823 sal_uInt8* pt = getMapData(0);
825 // are the values being saved as difference?
826 if ( 2 == nPredictor )
828 sal_uInt8 nLRed = 0;
829 sal_uInt8 nLGreen = 0;
830 sal_uInt8 nLBlue = 0;
831 sal_uInt8 nLAlpha = 0;
832 for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel)
834 nLRed = nLRed + pt[ 0 ];
835 nLGreen = nLGreen + pt[ 1 ];
836 nLBlue = nLBlue + pt[ 2 ];
837 SetPixel(nY, nx, Color(nLRed, nLGreen, nLBlue));
838 if (HasAlphaChannel())
840 nLAlpha = nLAlpha + pt[ 3 ];
841 SetPixelAlpha(nY, nx, ~nLAlpha);
845 else
847 for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel)
849 SetPixel(nY, nx, Color(pt[0], pt[1], pt[2]));
850 if (HasAlphaChannel())
852 sal_uInt8 nAlpha = pt[3];
853 SetPixelAlpha(nY, nx, ~nAlpha);
858 else if ( nPhotometricInterpretation == 2 && nSamplesPerPixel >= 3 )
860 if ( nMaxSampleValue > nMinSampleValue )
862 sal_uInt32 nMinMax = nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue );
863 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
865 if ( nPlanes < 3 )
867 nRed = GetBits( getMapData(0), ( nx * nSamplesPerPixel + 0 ) * nBitsPerSample, nBitsPerSample );
868 nGreen = GetBits( getMapData(1), ( nx * nSamplesPerPixel + 1 ) * nBitsPerSample, nBitsPerSample );
869 nBlue = GetBits( getMapData(2), ( nx * nSamplesPerPixel + 2 ) * nBitsPerSample, nBitsPerSample );
871 else
873 nRed = GetBits( getMapData(0), nx * nBitsPerSample, nBitsPerSample );
874 nGreen = GetBits( getMapData(1), nx * nBitsPerSample, nBitsPerSample );
875 nBlue = GetBits( getMapData(2), nx * nBitsPerSample, nBitsPerSample );
877 SetPixel(nY, nx, Color(static_cast<sal_uInt8>(nRed - nMinMax), static_cast<sal_uInt8>(nGreen - nMinMax), static_cast<sal_uInt8>(nBlue - nMinMax)));
881 else if ( nPhotometricInterpretation == 5 && nSamplesPerPixel == 3 )
883 if ( nMaxSampleValue > nMinSampleValue )
885 sal_uInt32 nMinMax = nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue );
886 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
888 if ( nPlanes < 3 )
890 nRed = GetBits( getMapData(0), ( nx * nSamplesPerPixel + 0 ) * nBitsPerSample, nBitsPerSample );
891 nGreen = GetBits( getMapData(0), ( nx * nSamplesPerPixel + 1 ) * nBitsPerSample, nBitsPerSample );
892 nBlue = GetBits( getMapData(0), ( nx * nSamplesPerPixel + 2 ) * nBitsPerSample, nBitsPerSample );
894 else
896 nRed = GetBits( getMapData(0), nx * nBitsPerSample, nBitsPerSample );
897 nGreen = GetBits( getMapData(1), nx * nBitsPerSample, nBitsPerSample );
898 nBlue = GetBits( getMapData(2), nx * nBitsPerSample, nBitsPerSample );
900 nRed = 255 - static_cast<sal_uInt8>( nRed - nMinMax );
901 nGreen = 255 - static_cast<sal_uInt8>( nGreen - nMinMax );
902 nBlue = 255 - static_cast<sal_uInt8>( nBlue - nMinMax );
903 SetPixel(nY, nx, Color(static_cast<sal_uInt8>(nRed), static_cast<sal_uInt8>(nGreen), static_cast<sal_uInt8>(nBlue)));
907 else if( nPhotometricInterpretation == 5 && nSamplesPerPixel == 4 )
909 if ( nMaxSampleValue > nMinSampleValue )
911 sal_uInt8 nSamp[ 4 ];
912 sal_uInt8 nSampLast[ 4 ] = { 0, 0, 0, 0 };
914 for(sal_Int32 nx = 0; nx < nImageWidth; ++nx)
916 // are the values being saved as difference?
917 if( 2 == nPredictor )
919 for( ns = 0; ns < 4; ns++ )
921 if( nPlanes < 3 )
922 nSampLast[ ns ] = nSampLast[ ns ] + static_cast<sal_uInt8>(GetBits( getMapData(0), ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample ));
923 else
924 nSampLast[ ns ] = nSampLast[ ns ] + static_cast<sal_uInt8>(GetBits( getMapData(ns), nx * nBitsPerSample, nBitsPerSample ));
925 nSamp[ ns ] = nSampLast[ ns ];
928 else
930 for( ns = 0; ns < 4; ns++ )
932 if( nPlanes < 3 )
933 nSamp[ ns ] = static_cast<sal_uInt8>(GetBits( getMapData(0), ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample ));
934 else
935 nSamp[ ns ]= static_cast<sal_uInt8>(GetBits( getMapData(ns), nx * nBitsPerSample, nBitsPerSample ));
938 const long nBlack = nSamp[ 3 ];
939 nRed = static_cast<sal_uInt8>(std::max( 0L, 255L - ( ( static_cast<sal_Int32>(nSamp[ 0 ]) + nBlack - ( static_cast<sal_Int32>(nMinSampleValue) << 1 ) ) *
940 255L/static_cast<sal_Int32>(nMaxSampleValue-nMinSampleValue) ) ));
941 nGreen = static_cast<sal_uInt8>(std::max( 0L, 255L - ( ( static_cast<sal_Int32>(nSamp[ 1 ]) + nBlack - ( static_cast<sal_Int32>(nMinSampleValue) << 1 ) ) *
942 255L/static_cast<sal_Int32>(nMaxSampleValue-nMinSampleValue) ) ));
943 nBlue = static_cast<sal_uInt8>(std::max( 0L, 255L - ( ( static_cast<sal_Int32>(nSamp[ 2 ]) + nBlack - ( static_cast<sal_Int32>(nMinSampleValue) << 1 ) ) *
944 255L/static_cast<sal_Int32>(nMaxSampleValue-nMinSampleValue) ) ));
945 SetPixel(nY, nx, Color(static_cast<sal_uInt8>(nRed), static_cast<sal_uInt8>(nGreen), static_cast<sal_uInt8>(nBlue)));
950 else if ( nSamplesPerPixel == 1 && ( nPhotometricInterpretation <= 1 || nPhotometricInterpretation == 3 ) )
952 if ( nMaxSampleValue > nMinSampleValue )
954 sal_uInt32 nMinMax = ( ( 1 << nDstBitsPerPixel ) - 1 ) / ( nMaxSampleValue - nMinSampleValue );
955 sal_uInt8* pt = getMapData(0);
956 sal_uInt8* ptend = pt + nBytesPerRow;
957 sal_uInt8 nShift;
959 switch ( nDstBitsPerPixel )
961 case 8 :
963 if (pt + nImageWidth > ptend)
964 return false;
966 if ( bByteSwap )
968 if ( nPredictor == 2 )
970 sal_uInt8 nLast = 0;
971 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
973 nLast += nx == 0 ? BYTESWAP( *pt++ ) : *pt++;
974 SetPixel(nY, nx, nLast);
977 else
979 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
981 sal_uInt8 nLast = *pt++;
982 SetPixel(nY, nx, static_cast<sal_uInt8>( (BYTESWAP(static_cast<sal_uInt32>(nLast)) - nMinSampleValue) * nMinMax ));
986 else
988 if ( nPredictor == 2 )
990 sal_uInt8 nLast = 0;
991 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
993 nLast += *pt++;
994 SetPixel(nY, nx, nLast);
997 else
999 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
1001 SetPixel(nY, nx, static_cast<sal_uInt8>( (static_cast<sal_uInt32>(*pt++) - nMinSampleValue) * nMinMax ));
1006 break;
1008 case 7 :
1009 case 6 :
1010 case 5 :
1011 case 4 :
1012 case 3 :
1013 case 2 :
1015 for (sal_Int32 nx = 0; nx < nImageWidth; ++nx)
1017 nVal = ( GetBits( pt, nx * nBitsPerSample, nBitsPerSample ) - nMinSampleValue ) * nMinMax;
1018 SetPixel(nY, nx, static_cast<sal_uInt8>(nVal));
1021 break;
1023 case 1 :
1025 sal_uInt32 nByteCount = nImageWidth >> 3;
1027 sal_uInt32 nBytesNeeded = nByteCount;
1028 if (nImageWidth & 7)
1029 ++nBytesNeeded;
1030 if (pt + nBytesNeeded > ptend)
1031 return false;
1033 if ( bByteSwap )
1035 sal_Int32 nx = 0;
1036 while (nByteCount--)
1038 nByteVal = *pt++;
1039 SetPixel(nY, nx++, nByteVal & 1);
1040 nByteVal >>= 1;
1041 SetPixel(nY, nx++, nByteVal & 1);
1042 nByteVal >>= 1;
1043 SetPixel(nY, nx++, nByteVal & 1);
1044 nByteVal >>= 1;
1045 SetPixel(nY, nx++, nByteVal & 1);
1046 nByteVal >>= 1;
1047 SetPixel(nY, nx++, nByteVal & 1);
1048 nByteVal >>= 1;
1049 SetPixel(nY, nx++, nByteVal & 1);
1050 nByteVal >>= 1;
1051 SetPixel(nY, nx++, nByteVal & 1);
1052 nByteVal >>= 1;
1053 SetPixel(nY, nx++, nByteVal);
1055 if ( nImageWidth & 7 )
1057 nByteVal = *pt++;
1058 while ( nx < nImageWidth )
1060 SetPixel(nY, nx++, nByteVal & 1);
1061 nByteVal >>= 1;
1065 else
1067 sal_Int32 nx = 7;
1068 while (nByteCount--)
1070 nByteVal = *pt++;
1071 SetPixel(nY, nx, nByteVal & 1);
1072 nByteVal >>= 1;
1073 SetPixel(nY, --nx, nByteVal & 1);
1074 nByteVal >>= 1;
1075 SetPixel(nY, --nx, nByteVal & 1);
1076 nByteVal >>= 1;
1077 SetPixel(nY, --nx, nByteVal & 1);
1078 nByteVal >>= 1;
1079 SetPixel(nY, --nx, nByteVal & 1);
1080 nByteVal >>= 1;
1081 SetPixel(nY, --nx, nByteVal & 1);
1082 nByteVal >>= 1;
1083 SetPixel(nY, --nx, nByteVal & 1);
1084 nByteVal >>= 1;
1085 SetPixel(nY, --nx, nByteVal);
1086 nx += 15;
1088 if ( nImageWidth & 7 )
1090 nx -= 7;
1091 nByteVal = *pt++;
1092 nShift = 7;
1093 while ( nx < nImageWidth )
1095 SetPixel(nY, nx++, ( nByteVal >> nShift ) & 1);
1100 break;
1102 default :
1103 return false;
1107 else if ( ( nSamplesPerPixel == 2 ) && ( nBitsPerSample == 8 ) &&
1108 ( nPlanarConfiguration == 1 ) && aColorMap.empty() ) // grayscale
1110 if ( nMaxSampleValue > nMinSampleValue )
1112 sal_uInt32 nMinMax = ( ( 1 << 8 /*nDstBitsPerPixel*/ ) - 1 ) / ( nMaxSampleValue - nMinSampleValue );
1113 sal_uInt8* pt = getMapData(0);
1114 for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += 2 )
1116 SetPixel(nY, nx, static_cast<sal_uInt8>( (static_cast<sal_uInt32>(*pt) - nMinSampleValue) * nMinMax));
1120 else
1121 return false;
1122 return true;
1125 void TIFFReader::MakePalCol()
1127 if ( nDstBitsPerPixel <= 8 )
1129 aColorMap.resize(256);
1130 if ( nPhotometricInterpretation <= 1 )
1132 nNumColors = sal_uInt32(1) << nBitsPerSample;
1133 if ( nNumColors > 256 )
1134 nNumColors = 256;
1136 if (nLargestPixelIndex >= static_cast<int>(nNumColors))
1138 SAL_WARN("filter.tiff", "palette has less entries that largest index used. Expanding palette to match");
1139 nNumColors = nLargestPixelIndex + 1;
1142 for (sal_uInt32 i = 0; i < nNumColors; ++i)
1144 sal_uInt32 nVal = ( i * 255 / ( nNumColors - 1 ) ) & 0xff;
1145 sal_uInt32 n0RGB = nVal | ( nVal << 8 ) | ( nVal << 16 );
1146 if ( nPhotometricInterpretation == 1 )
1147 aColorMap[i] = n0RGB;
1148 else
1149 aColorMap[nNumColors - i - 1] = n0RGB;
1152 mvPalette.resize(std::max<sal_uInt16>(nNumColors, mvPalette.size()));
1153 for (sal_uInt32 i = 0; i < nNumColors; ++i)
1155 mvPalette[i] = Color( static_cast<sal_uInt8>( aColorMap[ i ] >> 16 ),
1156 static_cast<sal_uInt8>( aColorMap[ i ] >> 8 ), static_cast<sal_uInt8>(aColorMap[ i ]) );
1160 if ( fXResolution > 1.0 && fYResolution > 1.0 && ( nResolutionUnit == 2 || nResolutionUnit == 3 ) )
1162 sal_uInt32 nRX, nRY;
1163 if (nResolutionUnit==2)
1165 nRX=static_cast<sal_uInt32>(fXResolution+0.5);
1166 nRY=static_cast<sal_uInt32>(fYResolution+0.5);
1168 else
1170 nRX=static_cast<sal_uInt32>(fXResolution*2.54+0.5);
1171 nRY=static_cast<sal_uInt32>(fYResolution*2.54+0.5);
1173 MapMode aMapMode(MapUnit::MapInch,Point(0,0),Fraction(1,nRX),Fraction(1,nRY));
1174 maBitmapPrefMapMode = aMapMode;
1175 maBitmapPrefSize = Size(nImageWidth,nImageLength);
1180 void TIFFReader::ReadHeader()
1182 sal_uInt8 nbyte1(0), nbyte2(0);
1183 sal_uInt16 nushort(0);
1185 pTIFF->ReadUChar( nbyte1 );
1186 if ( nbyte1 == 'I' )
1187 pTIFF->SetEndian( SvStreamEndian::LITTLE );
1188 else
1189 pTIFF->SetEndian( SvStreamEndian::BIG );
1191 pTIFF->ReadUChar( nbyte2 ).ReadUInt16( nushort );
1192 if ( nbyte1 != nbyte2 || ( nbyte1 != 'I' && nbyte1 != 'M' ) || nushort != 0x002a )
1193 bStatus = false;
1196 bool TIFFReader::HasAlphaChannel() const
1198 /*There are undoubtedly more variants we could support, but keep it simple for now*/
1199 return (
1200 nDstBitsPerPixel == 24 &&
1201 nBitsPerSample == 8 &&
1202 nSamplesPerPixel >= 4 &&
1203 nPlanes == 1 &&
1204 nPhotometricInterpretation == 2
1209 bool TIFFReader::ReadTIFF(SvStream & rTIFF, Graphic & rGraphic )
1211 sal_uInt16 i, nNumTags(0), nTagType(0);
1212 sal_uInt32 nFirstIfd(0), nDataLen;
1214 bStatus = true;
1216 pTIFF = &rTIFF;
1217 sal_uInt64 nMaxPos = nOrigPos = pTIFF->Tell();
1218 nEndOfFile = nOrigPos + pTIFF->remainingSize();
1219 // number format of pTIFF at the beginning
1220 SvStreamEndian nOrigNumberFormat = pTIFF->GetEndian();
1222 // read header:
1223 ReadHeader();
1225 // read first IFD:
1226 pTIFF->ReadUInt32( nFirstIfd );
1228 if( !nFirstIfd || pTIFF->GetError() )
1229 bStatus = false;
1231 if ( bStatus )
1233 sal_uInt32 nOffset = nFirstIfd;
1235 std::vector<sal_uInt32> aSeenOffsets;
1236 // calculate length of TIFF file
1239 if (std::find(aSeenOffsets.begin(), aSeenOffsets.end(), nOffset) != aSeenOffsets.end())
1241 SAL_WARN("filter.tiff", "Parsing error: " << nOffset <<
1242 " already processed, format loop");
1243 bStatus = false;
1244 break;
1246 pTIFF->Seek(nOrigPos + nOffset);
1247 aSeenOffsets.push_back(nOffset);
1249 if( pTIFF->GetError() )
1251 pTIFF->ResetError();
1252 break;
1254 nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1256 pTIFF->ReadUInt16( nNumTags );
1258 // loop through tags:
1259 for( i = 0; i < nNumTags; i++ )
1261 nTagType = 0;
1262 nDataType = USHRT_MAX;
1263 nDataLen = 0;
1264 nOffset = 0;
1265 pTIFF->ReadUInt16( nTagType ).ReadUInt16( nDataType ).ReadUInt32( nDataLen ).ReadUInt32( nOffset );
1267 if( DataTypeSize() * nDataLen > 4 )
1268 nMaxPos = std::max(nOrigPos + nOffset + DataTypeSize() * nDataLen, nMaxPos);
1270 pTIFF->ReadUInt32( nOffset );
1271 if (!pTIFF->good())
1272 nOffset = 0;
1274 nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1275 if ( !nOffset )
1276 nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1278 while( nOffset );
1280 std::vector<sal_uInt32> aSeenIfds;
1282 for ( sal_uInt32 nNextIfd = nFirstIfd; nNextIfd && bStatus; )
1284 if (std::find(aSeenIfds.begin(), aSeenIfds.end(), nNextIfd) != aSeenIfds.end())
1286 SAL_WARN("filter.tiff", "Parsing error: " << nNextIfd <<
1287 " already processed, format loop");
1288 bStatus = false;
1289 break;
1291 pTIFF->Seek(nOrigPos + nNextIfd);
1292 aSeenIfds.push_back(nNextIfd);
1294 bByteSwap = false;
1296 nNewSubFile = 0;
1297 nSubFile = 0;
1298 nImageWidth = 0;
1299 nImageLength = 0;
1300 nBitsPerSample = 1; // default value according to the documentation
1301 nCompression = 1;
1302 nPhotometricInterpretation = 0;
1303 nThresholding = 1; // default value according to the documentation
1304 nCellWidth = 1;
1305 nCellLength = 1;
1306 nFillOrder = 1; // default value according to the documentation
1307 nOrientation = 1;
1308 nSamplesPerPixel = 1; // default value according to the documentation
1309 nRowsPerStrip = 0xffffffff; // default value according to the documentation
1310 nMinSampleValue = 0; // default value according to the documentation
1311 nMaxSampleValue = 0;
1312 fXResolution = 0.0;
1313 fYResolution = 0.0;
1314 nPlanarConfiguration = 1;
1315 nGroup3Options = 0; // default value according to the documentation
1316 nGroup4Options = 0; // default value according to the documentation
1317 nResolutionUnit = 2; // default value according to the documentation
1318 nPredictor = 1;
1319 nNumColors = 0;
1321 aStripOffsets.clear();
1322 aStripByteCounts.clear();
1323 for (auto& j : aMap)
1324 j.clear();
1326 pTIFF->ReadUInt16( nNumTags );
1327 sal_uInt64 nPos = pTIFF->Tell();
1329 const size_t nMinRecordSize = 8;
1330 const size_t nMaxRecords = pTIFF->remainingSize() / nMinRecordSize;
1331 if (nNumTags > nMaxRecords)
1333 SAL_WARN("filter.tiff", "Parsing error: " << nMaxRecords <<
1334 " max possible entries, but " << nNumTags << " claimed, truncating");
1335 nNumTags = nMaxRecords;
1338 for( i = 0; i < nNumTags; i++ )
1340 pTIFF->ReadUInt16( nTagType ).ReadUInt16( nDataType ).ReadUInt32( nDataLen );
1342 if( DataTypeSize() * nDataLen > 4 )
1344 pTIFF->ReadUInt32( nOffset );
1345 if (!checkSeek(*pTIFF, nOrigPos + nOffset))
1347 bStatus = false;
1348 break;
1351 ReadTagData( nTagType, nDataLen );
1352 nPos += 12; pTIFF->Seek( nPos );
1354 if ( pTIFF->GetError() )
1355 bStatus = false;
1357 if ( !bStatus )
1358 break;
1360 pTIFF->ReadUInt32( nNextIfd );
1361 if (!pTIFF->good())
1362 nNextIfd = 0;
1364 if ( !nBitsPerSample || ( nBitsPerSample > 32 ) )
1365 bStatus = false;
1366 if (nImageWidth <= 0 || nImageLength <= 0)
1367 bStatus = false;
1368 if ( bStatus )
1370 nLargestPixelIndex = -1;
1371 if ( nMaxSampleValue == 0 )
1373 if ( nBitsPerSample == 32 ) // sj: i93300, compiler bug, 1 << 32 gives 1 one 32bit windows platforms,
1374 nMaxSampleValue = 0xffffffff; // (up from 80286 only the lower 5 bits are used when shifting a 32bit register)
1375 else
1377 nMaxSampleValue = (1U << nBitsPerSample) - 1;
1380 if ( nPhotometricInterpretation == 2 || nPhotometricInterpretation == 5 || nPhotometricInterpretation == 6 )
1381 nDstBitsPerPixel = 24;
1382 else if ( nBitsPerSample*nSamplesPerPixel <= 1 )
1383 nDstBitsPerPixel = 1;
1384 else if ( nBitsPerSample*nSamplesPerPixel <= 4 )
1385 nDstBitsPerPixel = 4;
1386 else
1387 nDstBitsPerPixel = 8;
1389 if ( nPlanarConfiguration == 1 )
1390 nPlanes = 1;
1391 else
1392 nPlanes = nSamplesPerPixel;
1394 bStatus = nPlanes != 0;
1397 sal_uInt32 nDiv = GetRowsPerStrip();
1399 if ( bStatus )
1401 bStatus = (nDiv != 0);
1404 if ( bStatus )
1406 if ( ( nFillOrder == 2 ) && ( nCompression != 5 ) ) // in the LZW mode bits are already being inverted
1407 bByteSwap = true;
1408 nStripsPerPlane = ( nImageLength - 1 ) / nDiv + 1;
1411 if ( bStatus )
1413 sal_uInt64 nRowSize = (static_cast<sal_uInt64>(nImageWidth) * nSamplesPerPixel / nPlanes * nBitsPerSample + 7) >> 3;
1414 if (nRowSize > SAL_MAX_INT32 / SAL_N_ELEMENTS(aMap))
1416 SAL_WARN("filter.tiff", "Ludicrous row size of: " << nRowSize << " required");
1417 bStatus = false;
1419 else
1420 nBytesPerRow = nRowSize;
1423 if (bStatus)
1425 //sanity check consider ReadMap condition for last row and
1426 //last plane
1427 if (nCompression == 1 || nCompression == 32771)
1429 sal_uInt32 nStripBytesPerRow;
1430 if (nCompression == 1)
1431 nStripBytesPerRow = nBytesPerRow;
1432 else
1433 nStripBytesPerRow = ( nBytesPerRow + 1 ) & 0xfffffffe;
1434 sal_uInt32 np = nPlanes - 1;
1435 if (np >= SAL_N_ELEMENTS(aMap))
1436 bStatus = false;
1437 sal_Int32 ny = nImageLength - 1;
1438 sal_uInt32 nStrip(0);
1439 nDiv = GetRowsPerStrip();
1440 if (bStatus)
1441 bStatus = nDiv != 0;
1442 if (bStatus)
1444 nStrip = ny / nDiv + np * nStripsPerPlane;
1445 if (nStrip >= aStripOffsets.size())
1446 bStatus = false;
1448 if (bStatus)
1450 auto nStart = aStripOffsets[ nStrip ] + ( ny % GetRowsPerStrip() ) * nStripBytesPerRow;
1451 auto nEnd = nStart + nBytesPerRow;
1452 if (nEnd > nEndOfFile)
1453 bStatus = false;
1456 else if (nCompression == 2 || nCompression == 3 || nCompression == 4)
1458 if (nCompression == 3 && nGroup3Options & 0xfffffffa)
1459 bStatus = false;
1460 else if (nCompression == 4 && nGroup4Options & 0xffffffff)
1461 bStatus = false;
1462 sal_uInt32 np = nPlanes - 1;
1463 if (np >= SAL_N_ELEMENTS(aMap))
1464 bStatus = false;
1465 sal_Int32 ny = nImageLength - 1;
1466 sal_uInt32 nStrip(0);
1467 nDiv = GetRowsPerStrip();
1468 if (bStatus)
1469 bStatus = nDiv != 0;
1470 if (bStatus)
1472 nStrip = ny / nDiv + np * nStripsPerPlane;
1473 if (nStrip >= aStripOffsets.size())
1474 bStatus = false;
1476 if (bStatus)
1478 auto nStart = aStripOffsets[nStrip];
1479 if (nStart > nEndOfFile)
1480 bStatus = false;
1483 if (bStatus)
1485 sal_uLong nTargetBits = nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes;
1486 if (nTargetBits > SAL_MAX_UINT16)
1487 bStatus = false;
1490 else if (nCompression == 5)
1492 sal_uInt32 np = nPlanes - 1;
1493 if (np >= SAL_N_ELEMENTS(aMap))
1494 bStatus = false;
1495 sal_Int32 ny = nImageLength - 1;
1496 sal_uInt32 nStrip(0);
1497 nDiv = GetRowsPerStrip();
1498 if (bStatus)
1499 bStatus = nDiv != 0;
1500 if (bStatus)
1502 nStrip = ny / nDiv + np * nStripsPerPlane;
1503 if (nStrip >= aStripOffsets.size())
1504 bStatus = false;
1506 if (bStatus)
1508 auto nStart = aStripOffsets[nStrip];
1509 if (nStart > nEndOfFile)
1510 bStatus = false;
1513 else if (nCompression == 32773)
1516 else
1518 bStatus = false;
1522 sal_Int32 nImageDataSize(0);
1523 if (bStatus)
1525 if (o3tl::checked_multiply<sal_Int32>(nImageWidth, nImageLength, nImageDataSize) ||
1526 o3tl::checked_multiply<sal_Int32>(nImageDataSize, (HasAlphaChannel() ? 4 : 3), nImageDataSize) ||
1527 nImageDataSize > SAL_MAX_INT32/2)
1529 bStatus = false;
1533 if ( bStatus )
1535 maBitmapPixelSize = Size(nImageWidth, nImageLength);
1536 maBitmap.resize(nImageDataSize, 0);
1538 if (bStatus && ReadMap())
1540 nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1541 MakePalCol();
1542 nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1543 // convert palette-ized images to 24-bit color
1544 if (!mvPalette.empty())
1546 for (sal_Int32 nY = 0; nY < nImageLength; ++nY)
1548 for (sal_Int32 nX = 0; nX < nImageWidth; ++nX)
1550 auto p = maBitmap.data() + ((maBitmapPixelSize.Width() * nY + nX) * 3);
1551 auto c = mvPalette[*p];
1552 *p = c.GetRed();
1553 p++;
1554 *p = c.GetGreen();
1555 p++;
1556 *p = c.GetBlue();
1561 else
1562 bStatus = false;
1564 if ( bStatus )
1566 BitmapEx aImage = vcl::bitmap::CreateFromData(maBitmap.data(), nImageWidth, nImageLength,
1567 nImageWidth * (HasAlphaChannel() ? 4 : 3), // scanline bytes
1568 HasAlphaChannel() ? 32 : 24);
1569 aImage.SetPrefMapMode(maBitmapPrefMapMode);
1570 aImage.SetPrefSize(maBitmapPrefSize);
1572 AnimationBitmap aAnimationBitmap( aImage, Point( 0, 0 ), maBitmapPixelSize,
1573 ANIMATION_TIMEOUT_ON_CLICK, Disposal::Back );
1575 aAnimation.Insert( aAnimationBitmap );
1579 // Clean up:
1580 for (auto& j : aMap)
1581 j.clear();
1582 aColorMap.clear();
1583 aStripOffsets.clear();
1584 aStripByteCounts.clear();
1588 // seek to end of TIFF if succeeded
1589 pTIFF->SetEndian( nOrigNumberFormat );
1590 pTIFF->Seek(bStatus ? nMaxPos : nOrigPos);
1592 if ( aAnimation.Count() )
1594 if ( aAnimation.Count() == 1 )
1595 rGraphic = aAnimation.GetBitmapEx();
1596 else
1597 rGraphic = aAnimation; //aBitmap;
1599 return true;
1601 else
1602 return false;
1606 //================== GraphicImport - the exported function ================
1608 extern "C" SAL_DLLPUBLIC_EXPORT bool
1609 itiGraphicImport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* )
1611 TIFFReader aTIFFReader;
1614 return aTIFFReader.ReadTIFF(rStream, rGraphic);
1616 catch (const std::bad_alloc &)
1618 return false;
1622 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */