1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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"
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 ==================================
49 bool bStatus
; // Whether until now no error occurred
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
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
;
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();
108 void ReadTagData( sal_uInt16 nTagType
, sal_uInt32 nDataLen
);
110 sal_uInt8
* getMapData(sal_uInt32 np
);
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
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
);
136 , nDstBitsPerPixel(0)
137 , nLargestPixelIndex(-1)
148 , nPhotometricInterpretation(0)
154 , nSamplesPerPixel(1)
155 , nRowsPerStrip(0xffffffff)
160 , nPlanarConfiguration(1)
172 sal_uInt32
GetRowsPerStrip() const
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
182 return nRowsPerStrip
== 0 ? nImageLength
: nRowsPerStrip
;
185 bool ReadTIFF( SvStream
& rTIFF
, Graphic
& rGraphic
);
188 //=================== Methods of TIFFReader ==============================
190 sal_uInt32
TIFFReader::DataTypeSize()
197 case 6 : // SIGNED Byte
198 case 7 : // UNDEFINED
211 case 10 : // SIGNED RATIONAL
216 pTIFF
->SetError(SVSTREAM_FILEFORMAT_ERROR
);
222 sal_uInt32
TIFFReader::ReadIntData()
226 sal_uInt32
nUINT32a(0), nUINT32b(0);
228 sal_uInt16
nUINT16(0);
239 pTIFF
->ReadUChar( nBYTE
);
243 pTIFF
->ReadUInt16( nUINT16
);
248 pTIFF
->ReadUInt32( nUINT32a
);
251 pTIFF
->ReadUInt32( nUINT32a
).ReadUInt32( nUINT32b
);
253 nUINT32a
/= nUINT32b
;
256 pTIFF
->ReadChar( nCHAR
);
257 nUINT32a
= static_cast<sal_Int32
>(nCHAR
);
260 pTIFF
->ReadInt16( nINT16
);
261 nUINT32a
= static_cast<sal_Int32
>(nINT16
);
264 pTIFF
->ReadUInt32( nUINT32a
).ReadInt32( nINT32
);
269 pTIFF
->ReadFloat( nFLOAT
);
270 nUINT32a
= static_cast<sal_Int32
>(nFLOAT
);
273 pTIFF
->ReadDouble( nDOUBLE
);
274 nUINT32a
= static_cast<sal_Int32
>(nDOUBLE
);
277 pTIFF
->ReadUInt32( nUINT32a
);
283 double TIFFReader::ReadDoubleData()
287 if ( nDataType
== 5 )
289 sal_uInt32
nulong(0);
290 pTIFF
->ReadUInt32( nulong
);
291 nd
= static_cast<double>(nulong
);
293 pTIFF
->ReadUInt32( nulong
);
295 nd
/= static_cast<double>(nulong
);
298 nd
= static_cast<double>(ReadIntData());
302 void TIFFReader::ReadTagData( sal_uInt16 nTagType
, sal_uInt32 nDataLen
)
309 case 0x00fe: // New Sub File
310 nNewSubFile
= ReadIntData();
311 SAL_INFO("filter.tiff","NewSubFile: " << nNewSubFile
);
314 case 0x00ff: // Sub File
315 nSubFile
= ReadIntData();
316 SAL_INFO("filter.tiff","SubFile: " << nSubFile
);
319 case 0x0100: // Image Width
320 nImageWidth
= ReadIntData();
321 SAL_INFO("filter.tiff","ImageWidth: " << nImageWidth
);
324 case 0x0101: // Image Length
325 nImageLength
= ReadIntData();
326 SAL_INFO("filter.tiff","ImageLength: " << nImageLength
);
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
336 case 0x0103: // Compression
337 nCompression
= ReadIntData();
338 SAL_INFO("filter.tiff","Compression: " << nCompression
);
341 case 0x0106: // Photometric Interpretation
342 nPhotometricInterpretation
= ReadIntData();
343 SAL_INFO("filter.tiff","PhotometricInterpretation: " << nPhotometricInterpretation
);
346 case 0x0107: // Thresholding
347 nThresholding
= ReadIntData();
348 SAL_INFO("filter.tiff","Thresholding: " << nThresholding
);
351 case 0x0108: // Cell Width
352 nCellWidth
= ReadIntData();
355 case 0x0109: // Cell Length
356 nCellLength
= ReadIntData();
359 case 0x010a: // Fill Order
360 nFillOrder
= ReadIntData();
361 SAL_INFO("filter.tiff","FillOrder: " << nFillOrder
);
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
);
388 case 0x0112: // Orientation
389 nOrientation
= ReadIntData();
390 SAL_INFO("filter.tiff","Orientation: " << nOrientation
);
393 case 0x0115: // Samples Per Pixel
394 nSamplesPerPixel
= ReadIntData();
395 SAL_INFO("filter.tiff","SamplesPerPixel: " << nSamplesPerPixel
);
398 case 0x0116: // Rows Per Strip
399 nRowsPerStrip
= ReadIntData();
400 SAL_INFO("filter.tiff","RowsPerStrip: " << nRowsPerStrip
);
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
);
425 case 0x0118: // Min Sample Value
426 nMinSampleValue
= ReadIntData();
427 SAL_INFO("filter.tiff","MinSampleValue: " << nMinSampleValue
);
430 case 0x0119: // Max Sample Value
431 nMaxSampleValue
= ReadIntData();
432 SAL_INFO("filter.tiff","MaxSampleValue: " << nMaxSampleValue
);
435 case 0x011a: // X Resolution
436 fXResolution
= ReadDoubleData();
439 case 0x011b: // Y Resolution
440 fYResolution
= ReadDoubleData();
443 case 0x011c: // Planar Configuration
444 nPlanarConfiguration
= ReadIntData();
445 SAL_INFO("filter.tiff","PlanarConfiguration: " << nPlanarConfiguration
);
448 case 0x0124: // Group 3 Options
449 nGroup3Options
= ReadIntData();
450 SAL_INFO("filter.tiff","Group3Options: " << nGroup3Options
);
453 case 0x0125: // Group 4 Options
454 nGroup4Options
= ReadIntData();
455 SAL_INFO("filter.tiff","Group4Options: " << nGroup4Options
);
458 case 0x0128: // Resolution Unit
459 nResolutionUnit
= ReadIntData();
462 case 0x013d: // Predictor
463 nPredictor
= ReadIntData();
464 SAL_INFO("filter.tiff","Predictor: " << nPredictor
);
467 case 0x0140: { // Color Map
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
)
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;
493 SAL_INFO("filter.tiff","ColorMap (number of colors): " << nNumColors
);
497 case 0x0153: { // SampleFormat
498 sal_uInt32 nSampleFormat
= ReadIntData();
499 if ( nSampleFormat
== 3 ) // IEEE floating point samples are not supported yet
505 if ( pTIFF
->GetError() )
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
;
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
))
535 sal_uInt32 nStrip
= ny
/ GetRowsPerStrip() + np
* nStripsPerPlane
;
536 if ( nStrip
>= aStripOffsets
.size())
538 pTIFF
->Seek( aStripOffsets
[ nStrip
] + ( ny
% GetRowsPerStrip() ) * nStripBytesPerRow
);
539 pTIFF
->ReadBytes(getMapData(np
), nBytesPerRow
);
543 if ( !ConvertScanline( ny
) )
547 else if ( nCompression
== 2 || nCompression
== 3 || nCompression
== 4 )
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 )
566 nOptions
= CCI_OPTION_2D
;
567 if ( nGroup4Options
& 0xffffffff )
570 if ( nFillOrder
== 2 )
572 nOptions
|= CCI_OPTION_INVERSEBITORDER
;
575 sal_uInt32 nStrip
= 0;
576 if (nStrip
>= aStripOffsets
.size())
578 sal_uInt64 nOffset
= aStripOffsets
[nStrip
];
579 if (nOffset
> nEndOfFile
)
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())
598 nOffset
= aStripOffsets
[nStrip
];
599 if (nOffset
> nEndOfFile
)
601 pTIFF
->Seek(nOffset
);
602 aCCIDecom
.StartDecompression( *pTIFF
);
604 if (np
>= SAL_N_ELEMENTS(aMap
))
606 DecompressStatus aResult
= aCCIDecom
.DecompressScanline(getMapData(np
), nImageWidth
* nBitsPerSample
* nSamplesPerPixel
/ nPlanes
, np
+ 1 == nPlanes
);
607 if (!aResult
.m_bSuccess
)
609 bDifferentToPrev
|= !aResult
.m_bBufferUnchanged
;
610 if ( pTIFF
->GetError() )
612 nTotalDataRead
+= nBytesPerRow
;
613 if (nMaxAllowedDecompression
&& nTotalDataRead
> nMaxAllowedDecompression
)
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
);
628 if (!ConvertScanline(ny
))
633 else if ( nCompression
== 5 )
635 LZWDecompressor aLZWDecom
;
636 sal_uInt32
nStrip(0);
637 if (nStrip
>= aStripOffsets
.size())
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())
650 pTIFF
->Seek(aStripOffsets
[nStrip
]);
651 aLZWDecom
.StartDecompression(*pTIFF
);
653 if (np
>= SAL_N_ELEMENTS(aMap
))
655 if ( ( aLZWDecom
.Decompress(getMapData(np
), nBytesPerRow
) != nBytesPerRow
) || pTIFF
->GetError() )
659 nTotalDataRead
+= nBytesPerRow
;
660 if (nMaxAllowedDecompression
&& nTotalDataRead
> nMaxAllowedDecompression
)
663 if ( !ConvertScanline( ny
) )
667 else if ( nCompression
== 32773 )
669 sal_uInt32
nStrip(0);
670 if (nStrip
>= aStripOffsets
.size())
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())
682 pTIFF
->Seek(aStripOffsets
[nStrip
]);
684 sal_uInt32 nRowBytesLeft
= nBytesPerRow
;
685 if (np
>= SAL_N_ELEMENTS(aMap
))
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
)
698 pTIFF
->ReadBytes(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() )
721 if ( !ConvertScanline( ny
) )
730 sal_uInt32
TIFFReader::GetBits( const sal_uInt8
* pSrc
, sal_uInt32 nBitsPos
, sal_uInt32 nBitsCount
)
735 pSrc
+= ( nBitsPos
>> 3 );
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
);
747 nBitsCount
-= 8 - nBitsPos
;
748 while ( nBitsCount
>= 8 )
751 nRes
= ( nRes
<< 8 ) | static_cast<sal_uInt32
>(BYTESWAP( nDat
));
754 if ( nBitsCount
> 0 )
757 nRes
= ( nRes
<< nBitsCount
) | (static_cast<sal_uInt32
>(BYTESWAP(nDat
))>>(8-nBitsCount
));
763 pSrc
+= ( nBitsPos
>> 3 );
765 nRes
= static_cast<sal_uInt32
>((*pSrc
)&(0xff>>nBitsPos
));
766 if ( nBitsCount
<= 8 - nBitsPos
)
768 nRes
>>= ( 8 - nBitsPos
- nBitsCount
);
773 nBitsCount
-= 8 - nBitsPos
;
774 while ( nBitsCount
>= 8 )
776 nRes
= ( nRes
<< 8 ) | static_cast<sal_uInt32
>(*(pSrc
++));
779 if ( nBitsCount
> 0 )
780 nRes
= ( nRes
<< nBitsCount
) | (static_cast<sal_uInt32
>(*pSrc
)>>(8-nBitsCount
));
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));
800 if (HasAlphaChannel())
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
;
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
)
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
);
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
)
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
);
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
)
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
);
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
++ )
922 nSampLast
[ ns
] = nSampLast
[ ns
] + static_cast<sal_uInt8
>(GetBits( getMapData(0), ( nx
* nSamplesPerPixel
+ ns
) * nBitsPerSample
, nBitsPerSample
));
924 nSampLast
[ ns
] = nSampLast
[ ns
] + static_cast<sal_uInt8
>(GetBits( getMapData(ns
), nx
* nBitsPerSample
, nBitsPerSample
));
925 nSamp
[ ns
] = nSampLast
[ ns
];
930 for( ns
= 0; ns
< 4; ns
++ )
933 nSamp
[ ns
] = static_cast<sal_uInt8
>(GetBits( getMapData(0), ( nx
* nSamplesPerPixel
+ ns
) * nBitsPerSample
, nBitsPerSample
));
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
;
959 switch ( nDstBitsPerPixel
)
963 if (pt
+ nImageWidth
> ptend
)
968 if ( nPredictor
== 2 )
971 for (sal_Int32 nx
= 0; nx
< nImageWidth
; ++nx
)
973 nLast
+= nx
== 0 ? BYTESWAP( *pt
++ ) : *pt
++;
974 SetPixel(nY
, nx
, nLast
);
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
));
988 if ( nPredictor
== 2 )
991 for (sal_Int32 nx
= 0; nx
< nImageWidth
; ++nx
)
994 SetPixel(nY
, nx
, nLast
);
999 for (sal_Int32 nx
= 0; nx
< nImageWidth
; ++nx
)
1001 SetPixel(nY
, nx
, static_cast<sal_uInt8
>( (static_cast<sal_uInt32
>(*pt
++) - nMinSampleValue
) * nMinMax
));
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
));
1025 sal_uInt32 nByteCount
= nImageWidth
>> 3;
1027 sal_uInt32 nBytesNeeded
= nByteCount
;
1028 if (nImageWidth
& 7)
1030 if (pt
+ nBytesNeeded
> ptend
)
1036 while (nByteCount
--)
1039 SetPixel(nY
, nx
++, nByteVal
& 1);
1041 SetPixel(nY
, nx
++, nByteVal
& 1);
1043 SetPixel(nY
, nx
++, nByteVal
& 1);
1045 SetPixel(nY
, nx
++, nByteVal
& 1);
1047 SetPixel(nY
, nx
++, nByteVal
& 1);
1049 SetPixel(nY
, nx
++, nByteVal
& 1);
1051 SetPixel(nY
, nx
++, nByteVal
& 1);
1053 SetPixel(nY
, nx
++, nByteVal
);
1055 if ( nImageWidth
& 7 )
1058 while ( nx
< nImageWidth
)
1060 SetPixel(nY
, nx
++, nByteVal
& 1);
1068 while (nByteCount
--)
1071 SetPixel(nY
, nx
, nByteVal
& 1);
1073 SetPixel(nY
, --nx
, nByteVal
& 1);
1075 SetPixel(nY
, --nx
, nByteVal
& 1);
1077 SetPixel(nY
, --nx
, nByteVal
& 1);
1079 SetPixel(nY
, --nx
, nByteVal
& 1);
1081 SetPixel(nY
, --nx
, nByteVal
& 1);
1083 SetPixel(nY
, --nx
, nByteVal
& 1);
1085 SetPixel(nY
, --nx
, nByteVal
);
1088 if ( nImageWidth
& 7 )
1093 while ( nx
< nImageWidth
)
1095 SetPixel(nY
, nx
++, ( nByteVal
>> nShift
) & 1);
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
));
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 )
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
;
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);
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
);
1189 pTIFF
->SetEndian( SvStreamEndian::BIG
);
1191 pTIFF
->ReadUChar( nbyte2
).ReadUInt16( nushort
);
1192 if ( nbyte1
!= nbyte2
|| ( nbyte1
!= 'I' && nbyte1
!= 'M' ) || nushort
!= 0x002a )
1196 bool TIFFReader::HasAlphaChannel() const
1198 /*There are undoubtedly more variants we could support, but keep it simple for now*/
1200 nDstBitsPerPixel
== 24 &&
1201 nBitsPerSample
== 8 &&
1202 nSamplesPerPixel
>= 4 &&
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
;
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();
1226 pTIFF
->ReadUInt32( nFirstIfd
);
1228 if( !nFirstIfd
|| pTIFF
->GetError() )
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");
1246 pTIFF
->Seek(nOrigPos
+ nOffset
);
1247 aSeenOffsets
.push_back(nOffset
);
1249 if( pTIFF
->GetError() )
1251 pTIFF
->ResetError();
1254 nMaxPos
= std::max( pTIFF
->Tell(), nMaxPos
);
1256 pTIFF
->ReadUInt16( nNumTags
);
1258 // loop through tags:
1259 for( i
= 0; i
< nNumTags
; i
++ )
1262 nDataType
= USHRT_MAX
;
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
);
1274 nMaxPos
= std::max( pTIFF
->Tell(), nMaxPos
);
1276 nMaxPos
= std::max( pTIFF
->Tell(), nMaxPos
);
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");
1291 pTIFF
->Seek(nOrigPos
+ nNextIfd
);
1292 aSeenIfds
.push_back(nNextIfd
);
1300 nBitsPerSample
= 1; // default value according to the documentation
1302 nPhotometricInterpretation
= 0;
1303 nThresholding
= 1; // default value according to the documentation
1306 nFillOrder
= 1; // default value according to the documentation
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;
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
1321 aStripOffsets
.clear();
1322 aStripByteCounts
.clear();
1323 for (auto& j
: aMap
)
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
))
1351 ReadTagData( nTagType
, nDataLen
);
1352 nPos
+= 12; pTIFF
->Seek( nPos
);
1354 if ( pTIFF
->GetError() )
1360 pTIFF
->ReadUInt32( nNextIfd
);
1364 if ( !nBitsPerSample
|| ( nBitsPerSample
> 32 ) )
1366 if (nImageWidth
<= 0 || nImageLength
<= 0)
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)
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;
1387 nDstBitsPerPixel
= 8;
1389 if ( nPlanarConfiguration
== 1 )
1392 nPlanes
= nSamplesPerPixel
;
1394 bStatus
= nPlanes
!= 0;
1397 sal_uInt32 nDiv
= GetRowsPerStrip();
1401 bStatus
= (nDiv
!= 0);
1406 if ( ( nFillOrder
== 2 ) && ( nCompression
!= 5 ) ) // in the LZW mode bits are already being inverted
1408 nStripsPerPlane
= ( nImageLength
- 1 ) / nDiv
+ 1;
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");
1420 nBytesPerRow
= nRowSize
;
1425 //sanity check consider ReadMap condition for last row and
1427 if (nCompression
== 1 || nCompression
== 32771)
1429 sal_uInt32 nStripBytesPerRow
;
1430 if (nCompression
== 1)
1431 nStripBytesPerRow
= nBytesPerRow
;
1433 nStripBytesPerRow
= ( nBytesPerRow
+ 1 ) & 0xfffffffe;
1434 sal_uInt32 np
= nPlanes
- 1;
1435 if (np
>= SAL_N_ELEMENTS(aMap
))
1437 sal_Int32 ny
= nImageLength
- 1;
1438 sal_uInt32
nStrip(0);
1439 nDiv
= GetRowsPerStrip();
1441 bStatus
= nDiv
!= 0;
1444 nStrip
= ny
/ nDiv
+ np
* nStripsPerPlane
;
1445 if (nStrip
>= aStripOffsets
.size())
1450 auto nStart
= aStripOffsets
[ nStrip
] + ( ny
% GetRowsPerStrip() ) * nStripBytesPerRow
;
1451 auto nEnd
= nStart
+ nBytesPerRow
;
1452 if (nEnd
> nEndOfFile
)
1456 else if (nCompression
== 2 || nCompression
== 3 || nCompression
== 4)
1458 if (nCompression
== 3 && nGroup3Options
& 0xfffffffa)
1460 else if (nCompression
== 4 && nGroup4Options
& 0xffffffff)
1462 sal_uInt32 np
= nPlanes
- 1;
1463 if (np
>= SAL_N_ELEMENTS(aMap
))
1465 sal_Int32 ny
= nImageLength
- 1;
1466 sal_uInt32
nStrip(0);
1467 nDiv
= GetRowsPerStrip();
1469 bStatus
= nDiv
!= 0;
1472 nStrip
= ny
/ nDiv
+ np
* nStripsPerPlane
;
1473 if (nStrip
>= aStripOffsets
.size())
1478 auto nStart
= aStripOffsets
[nStrip
];
1479 if (nStart
> nEndOfFile
)
1485 sal_uLong nTargetBits
= nImageWidth
* nBitsPerSample
* nSamplesPerPixel
/ nPlanes
;
1486 if (nTargetBits
> SAL_MAX_UINT16
)
1490 else if (nCompression
== 5)
1492 sal_uInt32 np
= nPlanes
- 1;
1493 if (np
>= SAL_N_ELEMENTS(aMap
))
1495 sal_Int32 ny
= nImageLength
- 1;
1496 sal_uInt32
nStrip(0);
1497 nDiv
= GetRowsPerStrip();
1499 bStatus
= nDiv
!= 0;
1502 nStrip
= ny
/ nDiv
+ np
* nStripsPerPlane
;
1503 if (nStrip
>= aStripOffsets
.size())
1508 auto nStart
= aStripOffsets
[nStrip
];
1509 if (nStart
> nEndOfFile
)
1513 else if (nCompression
== 32773)
1522 sal_Int32
nImageDataSize(0);
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)
1535 maBitmapPixelSize
= Size(nImageWidth
, nImageLength
);
1536 maBitmap
.resize(nImageDataSize
, 0);
1538 if (bStatus
&& ReadMap())
1540 nMaxPos
= std::max( pTIFF
->Tell(), nMaxPos
);
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
];
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
);
1580 for (auto& j
: aMap
)
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();
1597 rGraphic
= aAnimation
; //aBitmap;
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
&)
1622 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */