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 .
20 #include <vcl/graph.hxx>
21 #include <vcl/bmpacc.hxx>
22 #include <vcl/animate.hxx>
23 #include "lzwdecom.hxx"
24 #include "ccidecom.hxx"
26 class FilterConfigItem
;
28 #define OOODEBUG(str,Num) //(InfoBox(NULL,String(str)+String(" ")+String(Num)).Execute();
32 template< typename T
> T
BYTESWAP(T nByte
) {
33 return ( nByte
<< 7 ) | ( ( nByte
& 2 ) << 5 ) | ( ( nByte
& 4 ) << 3 ) |
34 ( ( nByte
& 8 ) << 1 ) | ( ( nByte
& 16 ) >> 1 ) |
35 ( ( nByte
& 32 ) >> 3 ) | ( ( nByte
& 64 ) >> 5 ) |
36 ( ( nByte
& 128 ) >> 7 );
41 //============================ TIFFReader ==================================
48 sal_Bool bStatus
; // Whether until now no error occurred
50 sal_uLong nLastPercent
;
52 SvStream
* pTIFF
; // the TIFF file that should be read
54 BitmapWriteAccess
* pAcc
;
55 sal_uInt16 nDstBitsPerPixel
;
56 AlphaMask
* pAlphaMask
;
57 BitmapWriteAccess
* pMaskAcc
;
59 sal_uLong nOrigPos
; // start position in pTIFF
60 sal_uInt16 nOrigNumberFormat
; // number format of pTIFF at the beginning
64 // Data taken from the TIFF tags:
65 sal_Bool bByteSwap
; // sal_True if bits 0..7 -> 7..0 should get converted ( FILLORDER = 2 );
67 sal_uLong nNewSubFile
; //
68 sal_uLong nSubFile
; //
69 sal_uLong nImageWidth
; // picture width in pixels
70 sal_uLong nImageLength
; // picture height in pixels
71 sal_uLong nBitsPerSample
; // bits per pixel per layer
72 sal_uLong nCompression
; // kind of compression
73 sal_uLong nPhotometricInterpretation
; //
74 sal_uLong nThresholding
; //
75 sal_uLong nCellWidth
; //
76 sal_uLong nCellLength
; //
77 sal_uLong nFillOrder
; //
78 sal_uLong
* pStripOffsets
; // Fiels of offsets to the Bitmap-Data-"Strips"
79 sal_uLong nNumStripOffsets
; // size of the field above
80 sal_uLong nOrientation
; //
81 sal_uLong nSamplesPerPixel
; // number of layers
82 sal_uLong nRowsPerStrip
; // if it's not compressed: number of rows per Strip
83 sal_uLong
* pStripByteCounts
; // if compressed (in a certain way): size of the strips
84 sal_uLong nNumStripByteCounts
; // number of entries in the field above
85 sal_uLong nMinSampleValue
; //
86 sal_uLong nMaxSampleValue
; //
87 double fXResolution
; // X-resolution or 0.0
88 double fYResolution
; // Y-resolution or 0.0
89 sal_uLong nPlanarConfiguration
; //
90 sal_uLong nGroup3Options
; //
91 sal_uLong nGroup4Options
; //
92 sal_uLong nResolutionUnit
; // unit of fX/YResolution: 1=unknown, 2(default)=inch, 3=cm
93 sal_uLong nPredictor
; //
94 sal_uLong
* pColorMap
; // color palette
95 sal_uLong nNumColors
; // number of colors within the color palette
97 sal_uLong nPlanes
; // number of layers within the Tiff file
98 sal_uLong nStripsPerPlane
; // number of Strips per layer
99 sal_uLong nBytesPerRow
; // Bytes per line per Layer in the Tiff file ( uncompressed )
100 sal_uInt8
* pMap
[ 4 ]; // temporary Scanline
103 void MayCallback( sal_uLong nPercent
);
105 sal_uLong
DataTypeSize();
106 sal_uLong
ReadIntData();
107 double ReadDoubleData();
110 void ReadTagData( sal_uInt16 nTagType
, sal_uInt32 nDataLen
);
112 sal_Bool
ReadMap( sal_uLong nMinPercent
, sal_uLong nMaxPercent
);
113 // reads/decompresses the bitmap data and fills pMap
115 sal_uLong
GetBits( const sal_uInt8
* pSrc
, sal_uLong nBitsPos
, sal_uLong nBitsCount
);
116 // fetches BitsCount bits from pSrc[..] at the position nBitsPos
118 void MakePalCol( void );
119 // Create the bitmap from the temporary bitmap pMap
120 // and partly deletes pMap while doing this.
122 sal_Bool
ConvertScanline( sal_uLong nY
);
123 // converts a Scanline to the Windows-BMP format
125 bool HasAlphaChannel() const;
128 TIFFReader() : pAlphaMask(0), pMaskAcc(0) {}
134 sal_Bool
ReadTIFF( SvStream
& rTIFF
, Graphic
& rGraphic
);
137 //=================== Methods of TIFFReader ==============================
139 void TIFFReader::MayCallback( sal_uLong
/*nPercent*/ )
143 // ---------------------------------------------------------------------------------
145 sal_uLong
TIFFReader::DataTypeSize()
152 case 6 : // SIGNED Byte
153 case 7 : // UNDEFINED
166 case 10 : // SIGNED RATINAL
171 pTIFF
->SetError(SVSTREAM_FILEFORMAT_ERROR
);
177 // ---------------------------------------------------------------------------------
179 sal_uLong
TIFFReader::ReadIntData()
183 sal_uInt32 nUINT32a
, nUINT32b
;
197 nUINT32a
= (sal_uLong
)nBYTE
;
201 nUINT32a
= (sal_uLong
)nUINT16
;
208 *pTIFF
>> nUINT32a
>> nUINT32b
;
210 nUINT32a
/= nUINT32b
;
214 nUINT32a
= (sal_Int32
)nCHAR
;
218 nUINT32a
= (sal_Int32
)nINT16
;
221 *pTIFF
>> nUINT32a
>> nINT32
;
227 nUINT32a
= (sal_Int32
)nFLOAT
;
231 nUINT32a
= (sal_Int32
)nDOUBLE
;
240 // ---------------------------------------------------------------------------------
242 double TIFFReader::ReadDoubleData()
247 if ( nDataType
== 5 )
253 nd
/= (double)nulong
;
256 nd
= (double)ReadIntData();
260 // ---------------------------------------------------------------------------------
262 void TIFFReader::ReadTagData( sal_uInt16 nTagType
, sal_uInt32 nDataLen
)
264 if ( bStatus
== sal_False
)
269 case 0x00fe: // New Sub File
270 nNewSubFile
= ReadIntData();
271 OOODEBUG("NewSubFile",nNewSubFile
);
274 case 0x00ff: // Sub File
275 nSubFile
= ReadIntData();
276 OOODEBUG("SubFile",nSubFile
);
279 case 0x0100: // Image Width
280 nImageWidth
= ReadIntData();
281 OOODEBUG("ImageWidth",nImageWidth
);
284 case 0x0101: // Image Length
285 nImageLength
= ReadIntData();
286 OOODEBUG("ImageLength",nImageLength
);
289 case 0x0102: // Bits Per Sample
290 nBitsPerSample
= ReadIntData();
291 OOODEBUG("BitsPerSample",nBitsPerSample
);
292 if ( nBitsPerSample
>= 32 ) // 32 bit and larger samples are not supported
296 case 0x0103: // Compression
297 nCompression
= ReadIntData();
298 OOODEBUG("Compression",nCompression
);
301 case 0x0106: // Photometric Interpreation
302 nPhotometricInterpretation
= ReadIntData();
303 OOODEBUG("PhotometricInterpretation",nPhotometricInterpretation
);
306 case 0x0107: // Thresholding
307 nThresholding
= ReadIntData();
308 OOODEBUG("Thresholding",nThresholding
);
311 case 0x0108: // Cell Width
312 nCellWidth
= ReadIntData();
315 case 0x0109: // Cell Length
316 nCellLength
= ReadIntData();
319 case 0x010a: // Fill Order
320 nFillOrder
= ReadIntData();
321 OOODEBUG("FillOrder",nFillOrder
);
324 case 0x0111: { // Strip Offset(s)
325 sal_uLong nOldNumSO
, i
, * pOldSO
;
326 pOldSO
= pStripOffsets
;
327 if ( pOldSO
== NULL
)
328 nNumStripOffsets
= 0;
329 nOldNumSO
= nNumStripOffsets
;
330 nDataLen
+= nOldNumSO
;
331 if ( ( nDataLen
> nOldNumSO
) && ( nDataLen
< SAL_MAX_UINT32
/ sizeof( sal_uInt32
) ) )
333 nNumStripOffsets
= nDataLen
;
336 pStripOffsets
= new sal_uLong
[ nNumStripOffsets
];
338 catch (const std::bad_alloc
&)
340 pStripOffsets
= NULL
;
341 nNumStripOffsets
= 0;
345 for ( i
= 0; i
< nOldNumSO
; i
++ )
346 pStripOffsets
[ i
] = pOldSO
[ i
] + nOrigPos
;
347 for ( i
= nOldNumSO
; i
< nNumStripOffsets
; i
++ )
348 pStripOffsets
[ i
] = ReadIntData() + nOrigPos
;
352 OOODEBUG("StripOffsets (Anzahl:)",nDataLen
);
355 case 0x0112: // Orientation
356 nOrientation
= ReadIntData();
357 OOODEBUG("Orientation",nOrientation
);
360 case 0x0115: // Samples Per Pixel
361 nSamplesPerPixel
= ReadIntData();
362 OOODEBUG("SamplesPerPixel",nSamplesPerPixel
);
365 case 0x0116: // Rows Per Strip
366 nRowsPerStrip
= ReadIntData();
367 OOODEBUG("RowsPerStrip",nRowsPerStrip
);
370 case 0x0117: { // Strip Byte Counts
371 sal_uLong nOldNumSBC
, i
, * pOldSBC
;
372 pOldSBC
= pStripByteCounts
;
373 if ( pOldSBC
== NULL
)
374 nNumStripByteCounts
= 0; // to be on the safe side
375 nOldNumSBC
= nNumStripByteCounts
;
376 nDataLen
+= nOldNumSBC
;
377 if ( ( nDataLen
> nOldNumSBC
) && ( nDataLen
< SAL_MAX_UINT32
/ sizeof( sal_uInt32
) ) )
379 nNumStripByteCounts
= nDataLen
;
382 pStripByteCounts
= new sal_uLong
[ nNumStripByteCounts
];
384 catch (const std::bad_alloc
&)
386 pStripByteCounts
= NULL
;
387 nNumStripByteCounts
= 0;
389 if ( pStripByteCounts
)
391 for ( i
= 0; i
< nOldNumSBC
; i
++ )
392 pStripByteCounts
[ i
] = pOldSBC
[ i
];
393 for ( i
= nOldNumSBC
; i
< nNumStripByteCounts
; i
++)
394 pStripByteCounts
[ i
] = ReadIntData();
398 OOODEBUG("StripByteCounts (Anzahl:)",nDataLen
);
401 case 0x0118: // Min Sample Value
402 nMinSampleValue
= ReadIntData();
403 OOODEBUG("MinSampleValue",nMinSampleValue
);
406 case 0x0119: // Max Sample Value
407 nMaxSampleValue
= ReadIntData();
408 OOODEBUG("MaxSampleValue",nMaxSampleValue
);
411 case 0x011a: // X Resolution
412 fXResolution
= ReadDoubleData();
415 case 0x011b: // Y Resolution
416 fYResolution
= ReadDoubleData();
419 case 0x011c: // Planar Configuration
420 nPlanarConfiguration
= ReadIntData();
421 OOODEBUG("PlanarConfiguration",nPlanarConfiguration
);
424 case 0x0124: // Group 3 Options
425 nGroup3Options
= ReadIntData();
426 OOODEBUG("Group3Options",nGroup3Options
);
429 case 0x0125: // Group 4 Options
430 nGroup4Options
= ReadIntData();
431 OOODEBUG("Group4Options",nGroup4Options
);
434 case 0x0128: // Resolution Unit
435 nResolutionUnit
= ReadIntData();
438 case 0x013d: // Predictor
439 nPredictor
= ReadIntData();
440 OOODEBUG("Predictor",nPredictor
);
443 case 0x0140: { // Color Map
446 nNumColors
= ( 1UL << nBitsPerSample
);
447 if ( nDataType
== 3 && nNumColors
<= 256)
449 pColorMap
= new sal_uLong
[ 256 ];
450 for ( i
= 0; i
< nNumColors
; i
++ )
452 for ( i
= 0; i
< nNumColors
; i
++ )
455 pColorMap
[ i
] |= ( ( (sal_uLong
)nVal
) << 8 ) & 0x00ff0000;
457 for ( i
= 0; i
< nNumColors
; i
++ )
460 pColorMap
[ i
] |= ( (sal_uLong
)nVal
) & 0x0000ff00;
462 for ( i
= 0; i
< nNumColors
; i
++ )
465 pColorMap
[ i
] |= ( ( (sal_uLong
)nVal
) >> 8 ) & 0x000000ff;
470 OOODEBUG("ColorMap (Anzahl Farben:)", nNumColors
);
474 case 0x0153: { // SampleFormat
475 sal_uLong nSampleFormat
= ReadIntData();
476 if ( nSampleFormat
== 3 ) // IEEE floating point samples are not supported yet
482 if ( pTIFF
->GetError() )
486 // ---------------------------------------------------------------------------------
488 sal_Bool
TIFFReader::ReadMap( sal_uLong nMinPercent
, sal_uLong nMaxPercent
)
490 if ( nCompression
== 1 || nCompression
== 32771 )
492 sal_uLong ny
, np
, nStrip
, nStripBytesPerRow
;
494 if ( nCompression
== 1 )
495 nStripBytesPerRow
= nBytesPerRow
;
497 nStripBytesPerRow
= ( nBytesPerRow
+ 1 ) & 0xfffffffe;
498 for ( ny
= 0; ny
< nImageLength
; ny
++ )
500 for ( np
= 0; np
< nPlanes
; np
++ )
502 nStrip
= ny
/ nRowsPerStrip
+ np
* nStripsPerPlane
;
503 if ( nStrip
>= nNumStripOffsets
)
505 pTIFF
->Seek( pStripOffsets
[ nStrip
] + ( ny
% nRowsPerStrip
) * nStripBytesPerRow
);
506 pTIFF
->Read( pMap
[ np
], nBytesPerRow
);
507 if ( pTIFF
->GetError() )
509 MayCallback( nMinPercent
+ ( nMaxPercent
- nMinPercent
) * ( np
* nImageLength
+ ny
) / ( nImageLength
* nPlanes
) );
511 if ( !ConvertScanline( ny
) )
515 else if ( nCompression
== 2 || nCompression
== 3 || nCompression
== 4 )
517 sal_uLong ny
, np
, nStrip
, nOptions
;
518 if ( nCompression
== 2 )
520 nOptions
= CCI_OPTION_BYTEALIGNROW
;
522 else if ( nCompression
== 3 )
524 nOptions
= CCI_OPTION_EOL
;
525 if ( nGroup3Options
& 0x00000001 )
526 nOptions
|= CCI_OPTION_2D
;
527 if ( nGroup3Options
& 0x00000004 )
528 nOptions
|= CCI_OPTION_BYTEALIGNEOL
;
529 if ( nGroup3Options
& 0xfffffffa )
534 nOptions
= CCI_OPTION_2D
;
535 if ( nGroup4Options
& 0xffffffff )
538 if ( nFillOrder
== 2 )
540 nOptions
|= CCI_OPTION_INVERSEBITORDER
;
541 bByteSwap
= sal_False
;
544 if ( nStrip
>= nNumStripOffsets
)
546 pTIFF
->Seek(pStripOffsets
[nStrip
]);
548 CCIDecompressor
aCCIDecom( nOptions
, nImageWidth
);
550 aCCIDecom
.StartDecompression( *pTIFF
);
552 for ( ny
= 0; ny
< nImageLength
; ny
++ )
554 for ( np
= 0; np
< nPlanes
; np
++ )
556 if ( ny
/ nRowsPerStrip
+ np
* nStripsPerPlane
> nStrip
)
558 nStrip
=ny
/nRowsPerStrip
+np
*nStripsPerPlane
;
559 if ( nStrip
>= nNumStripOffsets
)
561 pTIFF
->Seek( pStripOffsets
[ nStrip
] );
562 aCCIDecom
.StartDecompression( *pTIFF
);
564 if ( aCCIDecom
.DecompressScanline( pMap
[ np
], nImageWidth
* nBitsPerSample
* nSamplesPerPixel
/ nPlanes
) == sal_False
)
566 if ( pTIFF
->GetError() )
568 MayCallback(nMinPercent
+(nMaxPercent
-nMinPercent
)*(np
*nImageLength
+ny
)/(nImageLength
*nPlanes
));
570 if ( !ConvertScanline( ny
) )
574 else if ( nCompression
== 5 )
576 LZWDecompressor aLZWDecom
;
577 sal_uLong ny
, np
, nStrip
;
579 if ( nStrip
>= nNumStripOffsets
)
581 pTIFF
->Seek(pStripOffsets
[nStrip
]);
582 aLZWDecom
.StartDecompression(*pTIFF
);
583 for ( ny
= 0; ny
< nImageLength
; ny
++ )
585 for ( np
= 0; np
< nPlanes
; np
++ )
587 if ( ny
/ nRowsPerStrip
+ np
* nStripsPerPlane
> nStrip
)
589 nStrip
= ny
/ nRowsPerStrip
+ np
* nStripsPerPlane
;
590 if ( nStrip
>= nNumStripOffsets
)
592 pTIFF
->Seek(pStripOffsets
[nStrip
]);
593 aLZWDecom
.StartDecompression(*pTIFF
);
595 if ( ( aLZWDecom
.Decompress( pMap
[ np
], nBytesPerRow
) != nBytesPerRow
) || pTIFF
->GetError() )
597 MayCallback(nMinPercent
+(nMaxPercent
-nMinPercent
)*(np
*nImageLength
+ny
)/(nImageLength
*nPlanes
));
599 if ( !ConvertScanline( ny
) )
603 else if ( nCompression
== 32773 )
605 sal_uLong nStrip
,nRecCount
,nRowBytesLeft
,ny
,np
,i
;
606 sal_uInt8
* pdst
, nRecHeader
, nRecData
;
608 if ( nStrip
>= nNumStripOffsets
)
610 pTIFF
->Seek(pStripOffsets
[nStrip
]);
611 for ( ny
= 0; ny
< nImageLength
; ny
++ )
613 for ( np
= 0; np
< nPlanes
; np
++ )
615 if ( ny
/ nRowsPerStrip
+ np
* nStripsPerPlane
> nStrip
)
617 nStrip
=ny
/nRowsPerStrip
+np
*nStripsPerPlane
;
618 if ( nStrip
>= nNumStripOffsets
)
620 pTIFF
->Seek(pStripOffsets
[nStrip
]);
622 nRowBytesLeft
= nBytesPerRow
;
626 *pTIFF
>> nRecHeader
;
627 if ((nRecHeader
&0x80)==0)
629 nRecCount
=0x00000001+((sal_uLong
)nRecHeader
);
630 if ( nRecCount
> nRowBytesLeft
)
632 pTIFF
->Read(pdst
,nRecCount
);
634 nRowBytesLeft
-=nRecCount
;
636 else if ( nRecHeader
!= 0x80 )
638 nRecCount
= 0x000000101 - ( (sal_uLong
)nRecHeader
);
639 if ( nRecCount
> nRowBytesLeft
)
641 nRecCount
= nRowBytesLeft
;
643 // bStatus = sal_False;
648 for ( i
= 0; i
< nRecCount
; i
++ )
649 *(pdst
++) = nRecData
;
650 nRowBytesLeft
-= nRecCount
;
652 } while ( nRowBytesLeft
!= 0 );
653 if ( pTIFF
->GetError() )
655 MayCallback(nMinPercent
+(nMaxPercent
-nMinPercent
)*(np
*nImageLength
+ny
)/(nImageLength
*nPlanes
));
657 if ( !ConvertScanline( ny
) )
666 sal_uLong
TIFFReader::GetBits( const sal_uInt8
* pSrc
, sal_uLong nBitsPos
, sal_uLong nBitsCount
)
671 pSrc
+= ( nBitsPos
>> 3 );
673 sal_uInt8 nDat
= *pSrc
;
674 nRes
= (sal_uLong
)( BYTESWAP( nDat
) & ( 0xff >> nBitsPos
) );
676 if ( nBitsCount
<= 8 - nBitsPos
)
678 nRes
>>= ( 8 - nBitsPos
- nBitsCount
);
683 nBitsCount
-= 8 - nBitsPos
;
684 while ( nBitsCount
>= 8 )
687 nRes
= ( nRes
<< 8 ) | ((sal_uLong
)BYTESWAP( nDat
) );
690 if ( nBitsCount
> 0 )
693 nRes
= ( nRes
<< nBitsCount
) | (((sal_uLong
)BYTESWAP(nDat
))>>(8-nBitsCount
));
699 pSrc
+= ( nBitsPos
>> 3 );
701 nRes
= (sal_uLong
)((*pSrc
)&(0xff>>nBitsPos
));
702 if ( nBitsCount
<= 8 - nBitsPos
)
704 nRes
>>= ( 8 - nBitsPos
- nBitsCount
);
709 nBitsCount
-= 8 - nBitsPos
;
710 while ( nBitsCount
>= 8 )
712 nRes
= ( nRes
<< 8 ) | ((sal_uLong
)*(pSrc
++));
715 if ( nBitsCount
> 0 )
716 nRes
= ( nRes
<< nBitsCount
) | (((sal_uLong
)*pSrc
)>>(8-nBitsCount
));
722 // ---------------------------------------------------------------------------------
724 sal_Bool
TIFFReader::ConvertScanline( sal_uLong nY
)
726 sal_uInt32 nRed
, nGreen
, nBlue
, ns
, nx
, nVal
, nByteCount
;
729 if ( nDstBitsPerPixel
== 24 )
731 if ( nBitsPerSample
== 8 && nSamplesPerPixel
>= 3 &&
732 nPlanes
== 1 && nPhotometricInterpretation
== 2 )
734 sal_uInt8
* pt
= pMap
[ 0 ];
736 // are the values being saved as difference?
737 if ( 2 == nPredictor
)
740 sal_uInt8 nLGreen
= 0;
741 sal_uInt8 nLBlue
= 0;
742 sal_uInt8 nLAlpha
= 0;
743 for ( nx
= 0; nx
< nImageWidth
; nx
++, pt
+= nSamplesPerPixel
)
745 nLRed
= nLRed
+ pt
[ 0 ];
746 nLGreen
= nLGreen
+ pt
[ 1 ];
747 nLBlue
= nLBlue
+ pt
[ 2 ];
748 pAcc
->SetPixel( nY
, nx
, Color( nLRed
, nLGreen
, nLBlue
) );
749 if (nSamplesPerPixel
>= 4 && pMaskAcc
)
751 nLAlpha
= nLAlpha
+ pt
[ 3 ];
752 pMaskAcc
->SetPixel( nY
, nx
, BitmapColor(~nLAlpha
) );
758 for ( nx
= 0; nx
< nImageWidth
; nx
++, pt
+= nSamplesPerPixel
)
760 pAcc
->SetPixel( nY
, nx
, Color( pt
[0], pt
[1], pt
[2] ) );
761 if (nSamplesPerPixel
>= 4 && pMaskAcc
)
763 sal_uInt8 nAlpha
= pt
[3];
764 pMaskAcc
->SetPixel( nY
, nx
, BitmapColor(~nAlpha
) );
769 else if ( nPhotometricInterpretation
== 2 && nSamplesPerPixel
>= 3 )
771 if ( nMaxSampleValue
> nMinSampleValue
)
773 sal_uLong nMinMax
= nMinSampleValue
* 255 / ( nMaxSampleValue
- nMinSampleValue
);
774 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
778 nRed
= GetBits( pMap
[ 0 ], ( nx
* nSamplesPerPixel
+ 0 ) * nBitsPerSample
, nBitsPerSample
);
779 nGreen
= GetBits( pMap
[ 1 ], ( nx
* nSamplesPerPixel
+ 1 ) * nBitsPerSample
, nBitsPerSample
);
780 nBlue
= GetBits( pMap
[ 2 ], ( nx
* nSamplesPerPixel
+ 2 ) * nBitsPerSample
, nBitsPerSample
);
784 nRed
= GetBits( pMap
[ 0 ], nx
* nBitsPerSample
, nBitsPerSample
);
785 nGreen
= GetBits( pMap
[ 1 ], nx
* nBitsPerSample
, nBitsPerSample
);
786 nBlue
= GetBits( pMap
[ 2 ], nx
* nBitsPerSample
, nBitsPerSample
);
788 pAcc
->SetPixel( nY
, nx
, Color( (sal_uInt8
)( nRed
- nMinMax
), (sal_uInt8
)( nGreen
- nMinMax
), (sal_uInt8
)(nBlue
- nMinMax
) ) );
792 else if ( nPhotometricInterpretation
== 5 && nSamplesPerPixel
== 3 )
794 if ( nMaxSampleValue
> nMinSampleValue
)
796 sal_uLong nMinMax
= nMinSampleValue
* 255 / ( nMaxSampleValue
- nMinSampleValue
);
797 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
801 nRed
= GetBits( pMap
[ 0 ],( nx
* nSamplesPerPixel
+ 0 ) * nBitsPerSample
, nBitsPerSample
);
802 nGreen
= GetBits( pMap
[ 0 ],( nx
* nSamplesPerPixel
+ 1 ) * nBitsPerSample
, nBitsPerSample
);
803 nBlue
= GetBits( pMap
[ 0 ],( nx
* nSamplesPerPixel
+ 2 ) * nBitsPerSample
, nBitsPerSample
);
807 nRed
= GetBits( pMap
[ 0 ], nx
* nBitsPerSample
, nBitsPerSample
);
808 nGreen
= GetBits( pMap
[ 1 ], nx
* nBitsPerSample
, nBitsPerSample
);
809 nBlue
= GetBits( pMap
[ 2 ], nx
* nBitsPerSample
, nBitsPerSample
);
811 nRed
= 255 - (sal_uInt8
)( nRed
- nMinMax
);
812 nGreen
= 255 - (sal_uInt8
)( nGreen
- nMinMax
);
813 nBlue
= 255 - (sal_uInt8
)( nBlue
- nMinMax
);
814 pAcc
->SetPixel( nY
, nx
, Color( (sal_uInt8
) nRed
, (sal_uInt8
) nGreen
, (sal_uInt8
) nBlue
) );
818 else if( nPhotometricInterpretation
== 5 && nSamplesPerPixel
== 4 )
820 if ( nMaxSampleValue
> nMinSampleValue
)
822 sal_uInt8 nSamp
[ 4 ];
823 sal_uInt8 nSampLast
[ 4 ] = { 0, 0, 0, 0 };
826 for( nx
= 0; nx
< nImageWidth
; nx
++ )
828 // are the values being saved as difference?
829 if( 2 == nPredictor
)
831 for( ns
= 0; ns
< 4; ns
++ )
834 nSampLast
[ ns
] = nSampLast
[ ns
] + (sal_uInt8
) GetBits( pMap
[ 0 ], ( nx
* nSamplesPerPixel
+ ns
) * nBitsPerSample
, nBitsPerSample
);
836 nSampLast
[ ns
] = nSampLast
[ ns
] + (sal_uInt8
) GetBits( pMap
[ ns
], nx
* nBitsPerSample
, nBitsPerSample
);
837 nSamp
[ ns
] = nSampLast
[ ns
];
842 for( ns
= 0; ns
< 4; ns
++ )
845 nSamp
[ ns
] = (sal_uInt8
) GetBits( pMap
[ 0 ], ( nx
* nSamplesPerPixel
+ ns
) * nBitsPerSample
, nBitsPerSample
);
847 nSamp
[ ns
]= (sal_uInt8
) GetBits( pMap
[ ns
], nx
* nBitsPerSample
, nBitsPerSample
);
851 nRed
= (sal_uInt8
) std::max( 0L, 255L - ( ( (long) nSamp
[ 0 ] + nBlack
- ( ( (long) nMinSampleValue
) << 1 ) ) *
852 255L/(long)(nMaxSampleValue
-nMinSampleValue
) ) );
853 nGreen
= (sal_uInt8
) std::max( 0L, 255L - ( ( (long) nSamp
[ 1 ] + nBlack
- ( ( (long) nMinSampleValue
) << 1 ) ) *
854 255L/(long)(nMaxSampleValue
-nMinSampleValue
) ) );
855 nBlue
= (sal_uInt8
) std::max( 0L, 255L - ( ( (long) nSamp
[ 2 ] + nBlack
- ( ( (long) nMinSampleValue
) << 1 ) ) *
856 255L/(long)(nMaxSampleValue
-nMinSampleValue
) ) );
857 pAcc
->SetPixel( nY
, nx
, Color ( (sal_uInt8
)nRed
, (sal_uInt8
)nGreen
, (sal_uInt8
)nBlue
) );
862 else if ( nSamplesPerPixel
== 1 && ( nPhotometricInterpretation
<= 1 || nPhotometricInterpretation
== 3 ) )
864 if ( nMaxSampleValue
> nMinSampleValue
)
866 sal_uLong nMinMax
= ( ( 1 << nDstBitsPerPixel
) - 1 ) / ( nMaxSampleValue
- nMinSampleValue
);
867 sal_uInt8
* pt
= pMap
[ 0 ];
870 switch ( nDstBitsPerPixel
)
877 if ( nPredictor
== 2 )
879 nLast
= BYTESWAP( (sal_uInt8
)*pt
++ );
880 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
882 pAcc
->SetPixelIndex( nY
, nx
, nLast
);
883 nLast
= nLast
+ *pt
++;
888 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
891 pAcc
->SetPixelIndex( nY
, nx
, static_cast<sal_uInt8
>( (BYTESWAP((sal_uLong
)nLast
) - nMinSampleValue
) * nMinMax
) );
897 if ( nPredictor
== 2 )
900 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
902 pAcc
->SetPixelIndex( nY
, nx
, nLast
);
903 nLast
= nLast
+ *pt
++;
908 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
910 pAcc
->SetPixelIndex( nY
, nx
, static_cast<sal_uInt8
>( ((sal_uLong
)*pt
++ - nMinSampleValue
) * nMinMax
) );
925 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
927 nVal
= ( GetBits( pt
, nx
* nBitsPerSample
, nBitsPerSample
) - nMinSampleValue
) * nMinMax
;
928 pAcc
->SetPixelIndex( nY
, nx
, static_cast<sal_uInt8
>(nVal
));
938 nByteCount
= ( nImageWidth
>> 3 ) + 1;
939 while ( --nByteCount
)
942 pAcc
->SetPixelIndex( nY
, nx
++, nByteVal
& 1 );
944 pAcc
->SetPixelIndex( nY
, nx
++, nByteVal
& 1 );
946 pAcc
->SetPixelIndex( nY
, nx
++, nByteVal
& 1 );
948 pAcc
->SetPixelIndex( nY
, nx
++, nByteVal
& 1 );
950 pAcc
->SetPixelIndex( nY
, nx
++, nByteVal
& 1 );
952 pAcc
->SetPixelIndex( nY
, nx
++, nByteVal
& 1 );
954 pAcc
->SetPixelIndex( nY
, nx
++, nByteVal
& 1 );
956 pAcc
->SetPixelIndex( nY
, nx
++, nByteVal
);
958 if ( nImageWidth
& 7 )
961 while ( nx
< nImageWidth
)
963 pAcc
->SetPixelIndex( nY
, nx
++, nByteVal
& 1 );
971 nByteCount
= ( nImageWidth
>> 3 ) + 1;
972 while ( --nByteCount
)
975 pAcc
->SetPixelIndex( nY
, nx
, nByteVal
& 1 );
977 pAcc
->SetPixelIndex( nY
, --nx
, nByteVal
& 1 );
979 pAcc
->SetPixelIndex( nY
, --nx
, nByteVal
& 1 );
981 pAcc
->SetPixelIndex( nY
, --nx
, nByteVal
& 1 );
983 pAcc
->SetPixelIndex( nY
, --nx
, nByteVal
& 1 );
985 pAcc
->SetPixelIndex( nY
, --nx
, nByteVal
& 1 );
987 pAcc
->SetPixelIndex( nY
, --nx
, nByteVal
& 1 );
989 pAcc
->SetPixelIndex( nY
, --nx
, nByteVal
);
992 if ( nImageWidth
& 7 )
997 while ( nx
< nImageWidth
)
999 pAcc
->SetPixelIndex( nY
, nx
++, ( nByteVal
>> nShift
) & 1);
1011 else if ( ( nSamplesPerPixel
== 2 ) && ( nBitsPerSample
== 8 ) &&
1012 ( nPlanarConfiguration
== 1 ) && ( pColorMap
== 0 ) ) // grayscale
1014 if ( nMaxSampleValue
> nMinSampleValue
)
1016 sal_uLong nMinMax
= ( ( 1 << 8 /*nDstBitsPerPixel*/ ) - 1 ) / ( nMaxSampleValue
- nMinSampleValue
);
1017 sal_uInt8
* pt
= pMap
[ 0 ];
1018 for ( nx
= 0; nx
< nImageWidth
; nx
++, pt
+= 2 )
1020 pAcc
->SetPixelIndex( nY
, nx
, static_cast<sal_uInt8
>( ((sal_uLong
)*pt
- nMinSampleValue
) * nMinMax
) );
1029 // ---------------------------------------------------------------------------------
1031 void TIFFReader::MakePalCol( void )
1033 if ( nDstBitsPerPixel
<= 8 )
1035 sal_uLong i
, nVal
, n0RGB
;
1036 if ( pColorMap
== NULL
)
1037 pColorMap
= new sal_uLong
[ 256 ];
1038 if ( nPhotometricInterpretation
<= 1 )
1040 nNumColors
= 1UL << nBitsPerSample
;
1041 if ( nNumColors
> 256 )
1043 pAcc
->SetPaletteEntryCount( (sal_uInt16
)nNumColors
);
1044 for ( i
= 0; i
< nNumColors
; i
++ )
1046 nVal
= ( i
* 255 / ( nNumColors
- 1 ) ) & 0xff;
1047 n0RGB
= nVal
| ( nVal
<< 8 ) | ( nVal
<< 16 );
1048 if ( nPhotometricInterpretation
== 1 )
1049 pColorMap
[ i
] = n0RGB
;
1051 pColorMap
[ nNumColors
- i
- 1 ] = n0RGB
;
1054 for ( i
= 0; i
< nNumColors
; i
++ )
1056 pAcc
->SetPaletteColor( (sal_uInt16
)i
, BitmapColor( (sal_uInt8
)( pColorMap
[ i
] >> 16 ),
1057 (sal_uInt8
)( pColorMap
[ i
] >> 8 ), (sal_uInt8
)pColorMap
[ i
] ) );
1061 if ( fXResolution
> 1.0 && fYResolution
> 1.0 && ( nResolutionUnit
== 2 || nResolutionUnit
== 3 ) )
1064 if (nResolutionUnit
==2)
1066 nRX
=(sal_uLong
)(fXResolution
+0.5);
1067 nRY
=(sal_uLong
)(fYResolution
+0.5);
1071 nRX
=(sal_uLong
)(fXResolution
*2.54+0.5);
1072 nRY
=(sal_uLong
)(fYResolution
*2.54+0.5);
1074 MapMode
aMapMode(MAP_INCH
,Point(0,0),Fraction(1,nRX
),Fraction(1,nRY
));
1075 aBitmap
.SetPrefMapMode(aMapMode
);
1076 aBitmap
.SetPrefSize(Size(nImageWidth
,nImageLength
));
1080 // ---------------------------------------------------------------------------------
1082 void TIFFReader::ReadHeader()
1084 sal_uInt8 nbyte1
, nbyte2
;
1088 if ( nbyte1
== 'I' )
1089 pTIFF
->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
1091 pTIFF
->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN
);
1093 *pTIFF
>> nbyte2
>> nushort
;
1094 if ( nbyte1
!= nbyte2
|| ( nbyte1
!= 'I' && nbyte1
!= 'M' ) || nushort
!= 0x002a )
1095 bStatus
= sal_False
;
1098 bool TIFFReader::HasAlphaChannel() const
1100 /*There are undoubtedly more variants we could support, but keep it simple for now*/
1102 nDstBitsPerPixel
== 24 &&
1103 nBitsPerSample
== 8 &&
1104 nSamplesPerPixel
>= 4 &&
1106 nPhotometricInterpretation
== 2
1110 // ---------------------------------------------------------------------------------
1112 sal_Bool
TIFFReader::ReadTIFF(SvStream
& rTIFF
, Graphic
& rGraphic
)
1114 sal_uInt16 i
, nNumTags
, nTagType
;
1117 sal_uInt32 nFirstIfd
, nDataLen
;
1123 nMaxPos
= nOrigPos
= pTIFF
->Tell();
1124 nOrigNumberFormat
= pTIFF
->GetNumberFormatInt();
1132 *pTIFF
>> nFirstIfd
;
1134 if( !nFirstIfd
|| pTIFF
->GetError() )
1135 bStatus
= sal_False
;
1139 sal_uInt32 nOffset
= nFirstIfd
;
1141 // calculate length of TIFF file
1144 pTIFF
->Seek( nOrigPos
+ nOffset
);
1146 if( pTIFF
->GetError() )
1148 pTIFF
->ResetError();
1151 nMaxPos
= std::max( pTIFF
->Tell(), nMaxPos
);
1155 // loop through tags:
1156 for( i
= 0; i
< nNumTags
; i
++ )
1158 *pTIFF
>> nTagType
>> nDataType
>> nDataLen
>> nOffset
;
1160 if( DataTypeSize() * nDataLen
> 4 )
1161 nMaxPos
= std::max( nOrigPos
+ nOffset
+ DataTypeSize() * nDataLen
, nMaxPos
);
1164 if ( pTIFF
->IsEof() )
1167 nMaxPos
= std::max( pTIFF
->Tell(), nMaxPos
);
1169 nMaxPos
= std::max( pTIFF
->Tell(), nMaxPos
);
1173 for ( sal_uInt32 nNextIfd
= nFirstIfd
; nNextIfd
&& bStatus
; )
1175 pTIFF
->Seek( nOrigPos
+ nNextIfd
);
1177 bByteSwap
= sal_False
;
1183 nBitsPerSample
= 1; // default value according to the documentation
1185 nPhotometricInterpretation
= 0;
1186 nThresholding
= 1; // default value according to the documentation
1189 nFillOrder
= 1; // default value according to the documentation
1190 nNumStripOffsets
= 0;
1192 nSamplesPerPixel
= 1; // default value according to the documentation
1193 nRowsPerStrip
= 0xffffffff; // default value according to the documentation
1194 nNumStripByteCounts
= 0;
1195 nMinSampleValue
= 0; // default value according to the documentation
1196 nMaxSampleValue
= 0;
1199 nPlanarConfiguration
= 1;
1200 nGroup3Options
= 0; // default value according to the documentation
1201 nGroup4Options
= 0; // default value according to the documentation
1202 nResolutionUnit
= 2; // default value according to the documentation
1208 pStripOffsets
= NULL
;
1209 pStripByteCounts
= NULL
;
1210 pMap
[ 0 ] = pMap
[ 1 ] = pMap
[ 2 ] = pMap
[ 3 ] = NULL
;
1213 nPos
= pTIFF
->Tell();
1215 // Schleife ueber Tags:
1216 for( i
= 0; i
< nNumTags
; i
++ )
1218 *pTIFF
>> nTagType
>> nDataType
>> nDataLen
;
1220 if( DataTypeSize() * nDataLen
> 4 )
1223 pTIFF
->Seek( nOrigPos
+ nOffset
);
1225 ReadTagData( nTagType
, nDataLen
);
1226 nPos
+= 12; pTIFF
->Seek( nPos
);
1228 if ( pTIFF
->GetError() )
1229 bStatus
= sal_False
;
1231 if ( bStatus
== sal_False
)
1235 if ( pTIFF
->IsEof() )
1238 if ( !nBitsPerSample
|| ( nBitsPerSample
> 32 ) )
1239 bStatus
= sal_False
;
1242 if ( nMaxSampleValue
== 0 )
1244 if ( nBitsPerSample
== 32 ) // sj: i93300, compiler bug, 1 << 32 gives 1 one 32bit windows platforms,
1245 nMaxSampleValue
= 0xffffffff; // (up from 80286 only the lower 5 bits are used when shifting a 32bit register)
1247 nMaxSampleValue
= ( 1 << nBitsPerSample
) - 1;
1249 if ( nPhotometricInterpretation
== 2 || nPhotometricInterpretation
== 5 || nPhotometricInterpretation
== 6 )
1250 nDstBitsPerPixel
= 24;
1251 else if ( nBitsPerSample
*nSamplesPerPixel
<= 1 )
1252 nDstBitsPerPixel
= 1;
1253 else if ( nBitsPerSample
*nSamplesPerPixel
<= 4 )
1254 nDstBitsPerPixel
= 4;
1256 nDstBitsPerPixel
= 8;
1258 Size
aTargetSize( nImageWidth
, nImageLength
);
1259 aBitmap
= Bitmap( aTargetSize
, nDstBitsPerPixel
);
1260 pAcc
= aBitmap
.AcquireWriteAccess();
1263 if ( nPlanarConfiguration
== 1 )
1266 nPlanes
= nSamplesPerPixel
;
1268 if ( ( nFillOrder
== 2 ) && ( nCompression
!= 5 ) ) // in the LZW mode bits are already being inverted
1269 bByteSwap
= sal_True
;
1271 nStripsPerPlane
= ( nImageLength
- 1 ) / nRowsPerStrip
+ 1;
1272 nBytesPerRow
= ( nImageWidth
* nSamplesPerPixel
/ nPlanes
* nBitsPerSample
+ 7 ) >> 3;
1274 for ( sal_uLong j
= 0; j
< 4; j
++ )
1278 pMap
[ j
] = new sal_uInt8
[ nBytesPerRow
];
1280 catch (const std::bad_alloc
&)
1283 bStatus
= sal_False
;
1288 if (HasAlphaChannel())
1290 pAlphaMask
= new AlphaMask( aTargetSize
);
1291 pMaskAcc
= pAlphaMask
->AcquireWriteAccess();
1294 if ( bStatus
&& ReadMap( 10, 60 ) )
1296 nMaxPos
= std::max( pTIFF
->Tell(), nMaxPos
);
1298 nMaxPos
= std::max( pTIFF
->Tell(), nMaxPos
);
1301 bStatus
= sal_False
;
1305 aBitmap
.ReleaseAccess( pAcc
);
1310 pAlphaMask
->ReleaseAccess( pMaskAcc
);
1319 aImage
= BitmapEx( aBitmap
, *pAlphaMask
);
1323 AnimationBitmap
aAnimationBitmap( aImage
, Point( 0, 0 ), aBitmap
.GetSizePixel(),
1324 ANIMATION_TIMEOUT_ON_CLICK
, DISPOSE_BACK
);
1326 aAnimation
.Insert( aAnimationBitmap
);
1330 for ( i
= 0; i
< 4; i
++ )
1334 delete[] pStripOffsets
;
1335 delete[] pStripByteCounts
;
1341 // seek to end of TIFF if succeeded
1342 pTIFF
->SetNumberFormatInt( nOrigNumberFormat
);
1343 pTIFF
->Seek( bStatus
? nMaxPos
: nOrigPos
);
1345 if ( aAnimation
.Count() )
1347 if ( aAnimation
.Count() == 1 )
1348 rGraphic
= aAnimation
.GetBitmapEx();
1350 rGraphic
= aAnimation
; //aBitmap;
1359 //================== GraphicImport - the exported function ================
1361 // this needs to be kept in sync with
1362 // ImpFilterLibCacheEntry::GetImportFunction() from
1363 // vcl/source/filter/graphicfilter.cxx
1364 #if defined(DISABLE_DYNLOADING)
1365 #define GraphicImport itiGraphicImport
1368 extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL
1369 GraphicImport(SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
*, sal_Bool
)
1371 TIFFReader aTIFFReader
;
1373 if ( aTIFFReader
.ReadTIFF( rStream
, rGraphic
) == sal_False
)
1379 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */