1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: itiff.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_goodies.hxx"
33 #include <vcl/graph.hxx>
34 #include <vcl/bmpacc.hxx>
35 #ifndef _SV_FLTCALL_HXX
36 #include <svtools/fltcall.hxx>
38 #include <vcl/animate.hxx>
39 #include "lzwdecom.hxx"
40 #include "ccidecom.hxx"
42 #define OOODEBUG(str,Num) //(InfoBox(NULL,String(str)+String(" ")+String(Num)).Execute();
46 template< typename T
> T
BYTESWAP(T nByte
) {
47 return ( nByte
<< 7 ) | ( ( nByte
& 2 ) << 5 ) | ( ( nByte
& 4 ) << 3 ) |
48 ( ( nByte
& 8 ) << 1 ) | ( ( nByte
& 16 ) >> 1 ) |
49 ( ( nByte
& 32 ) >> 3 ) | ( ( nByte
& 64 ) >> 5 ) |
50 ( ( nByte
& 128 ) >> 7 );
55 //============================ TIFFReader ==================================
62 BOOL bStatus
; // Ob bisher kein Fehler auftrat
66 SvStream
* pTIFF
; // Die einzulesende TIFF-Datei
68 BitmapWriteAccess
* pAcc
;
69 USHORT nDstBitsPerPixel
;
71 ULONG nOrigPos
; // Anfaengliche Position in pTIFF
72 UINT16 nOrigNumberFormat
; // Anfaengliches Nummern-Format von pTIFF
76 // Daten, die aus dem TIFF-Tags entnommen werden:
77 BOOL bByteSwap
; // TRUE wenn bits 0..7 -> 7..0 invertiert werden sollen ( FILLORDER = 2 );
78 BYTE nByte1
; // 'I', wenn Format LittleEndian
82 ULONG nImageWidth
; // Bildbreite in Pixel
83 ULONG nImageLength
; // Bildhoehe in Pixel
84 ULONG nBitsPerSample
; // Bits pro Pixel pro Ebene
85 ULONG nCompression
; // Art der Kompriemierung
86 ULONG nPhotometricInterpretation
; //
87 ULONG nThresholding
; //
91 ULONG
* pStripOffsets
; // Feld von Offsets zu den Bitmap-Daten-"Strips"
92 ULONG nNumStripOffsets
; // Groesse obigen Feldes
93 ULONG nOrientation
; //
94 ULONG nSamplesPerPixel
; // Anzahl der Ebenen
95 ULONG nRowsPerStrip
; // Wenn nicht komprimiert: Zahl der Zeilen pro Strip
96 ULONG
* pStripByteCounts
; // Wenn komprimiert (bestimmte Art): Groesse der Strips
97 ULONG nNumStripByteCounts
; // Anzahl der Eintraege in obiges Feld
98 ULONG nMinSampleValue
; //
99 ULONG nMaxSampleValue
; //
100 double fXResolution
; // X-Aufloesung oder 0.0
101 double fYResolution
; // Y-Aufloesung oder 0.0
102 ULONG nPlanarConfiguration
; //
103 ULONG nGroup3Options
; //
104 ULONG nGroup4Options
; //
105 ULONG nResolutionUnit
; // Einheit von fX/YResolution: 1=unbekannt, 2(default)=Zoll, 3=cm
107 ULONG
* pColorMap
; // Farb-Palette
108 ULONG nNumColors
; // Anzahl Farben in der Farbpalette
110 ULONG nPlanes
; // Anzahl der Ebenen in der Tiff-Datei
111 ULONG nStripsPerPlane
; // Anzahl der Strips pro Ebene
112 ULONG nBytesPerRow
; // Bytes pro Zeile pro Ebene in der Tiff-Datei ( unkomprimiert )
113 BYTE
* pMap
[ 4 ]; // Temporaere Scanline
116 void MayCallback( ULONG nPercent
);
118 ULONG
DataTypeSize();
120 double ReadDoubleData();
123 void ReadTagData( USHORT nTagType
, sal_uInt32 nDataLen
);
125 BOOL
ReadMap( ULONG nMinPercent
, ULONG nMaxPercent
);
126 // Liesst/dekomprimert die Bitmap-Daten, und fuellt pMap
128 ULONG
GetBits( const BYTE
* pSrc
, ULONG nBitsPos
, ULONG nBitsCount
);
129 // Holt nBitsCount Bits aus pSrc[..] an der Bit-Position nBitsPos
131 void MakePalCol( void );
132 // Erzeugt die Bitmap aus der temporaeren Bitmap pMap
133 // und loescht dabei pMap teilweise
134 BOOL
ConvertScanline( ULONG nY
);
135 // Konvertiert eine Scanline in das Windows-BMP-Format
142 BOOL
ReadTIFF( SvStream
& rTIFF
, Graphic
& rGraphic
);
145 //=================== Methoden von TIFFReader ==============================
147 void TIFFReader::MayCallback( ULONG
/*nPercent*/ )
150 if ( nPercent >= nLastPercent + 3 )
152 nLastPercent=nPercent;
153 if ( pCallback != NULL && nPercent <= 100 && bStatus == TRUE )
155 if (((*pCallback)(pCallerData,(USHORT)nPercent)) == TRUE )
162 // ---------------------------------------------------------------------------------
164 ULONG
TIFFReader::DataTypeSize()
171 case 6 : // SIGNED Byte
172 case 7 : // UNDEFINED
185 case 10 : // SIGNED RATINAL
190 pTIFF
->SetError(SVSTREAM_FILEFORMAT_ERROR
);
196 // ---------------------------------------------------------------------------------
198 ULONG
TIFFReader::ReadIntData()
202 UINT32 nUINT32a
, nUINT32b
;
216 nUINT32a
= (ULONG
)nBYTE
;
220 nUINT32a
= (ULONG
)nUINT16
;
227 *pTIFF
>> nUINT32a
>> nUINT32b
;
229 nUINT32a
/= nUINT32b
;
233 nUINT32a
= (INT32
)nCHAR
;
237 nUINT32a
= (INT32
)nINT16
;
240 *pTIFF
>> nUINT32a
>> nINT32
;
246 nUINT32a
= (INT32
)nFLOAT
;
250 nUINT32a
= (INT32
)nDOUBLE
;
259 // ---------------------------------------------------------------------------------
261 double TIFFReader::ReadDoubleData()
266 if ( nDataType
== 5 )
272 nd
/= (double)nulong
;
275 nd
= (double)ReadIntData();
279 // ---------------------------------------------------------------------------------
281 void TIFFReader::ReadTagData( USHORT nTagType
, sal_uInt32 nDataLen
)
283 if ( bStatus
== FALSE
)
288 case 0x00fe: // New Sub File
289 nNewSubFile
= ReadIntData();
290 OOODEBUG("NewSubFile",nNewSubFile
);
293 case 0x00ff: // Sub File
294 nSubFile
= ReadIntData();
295 OOODEBUG("SubFile",nSubFile
);
298 case 0x0100: // Image Width
299 nImageWidth
= ReadIntData();
300 OOODEBUG("ImageWidth",nImageWidth
);
303 case 0x0101: // Image Length
304 nImageLength
= ReadIntData();
305 OOODEBUG("ImageLength",nImageLength
);
308 case 0x0102: // Bits Per Sample
309 nBitsPerSample
= ReadIntData();
310 OOODEBUG("BitsPerSample",nBitsPerSample
);
313 case 0x0103: // Compression
314 nCompression
= ReadIntData();
315 OOODEBUG("Compression",nCompression
);
318 case 0x0106: // Photometric Interpreation
319 nPhotometricInterpretation
= ReadIntData();
320 OOODEBUG("PhotometricInterpretation",nPhotometricInterpretation
);
323 case 0x0107: // Thresholding
324 nThresholding
= ReadIntData();
325 OOODEBUG("Thresholding",nThresholding
);
328 case 0x0108: // Cell Width
329 nCellWidth
= ReadIntData();
332 case 0x0109: // Cell Length
333 nCellLength
= ReadIntData();
336 case 0x010a: // Fill Order
337 nFillOrder
= ReadIntData();
338 OOODEBUG("FillOrder",nFillOrder
);
341 case 0x0111: { // Strip Offset(s)
342 ULONG nOldNumSO
, i
, * pOldSO
;
343 pOldSO
= pStripOffsets
;
344 if ( pOldSO
== NULL
)
345 nNumStripOffsets
= 0;
346 nOldNumSO
= nNumStripOffsets
;
347 nDataLen
+= nOldNumSO
;
348 if ( ( nDataLen
> nOldNumSO
) && ( nDataLen
< SAL_MAX_UINT32
/ sizeof( sal_uInt32
) ) )
350 nNumStripOffsets
= nDataLen
;
353 pStripOffsets
= new ULONG
[ nNumStripOffsets
];
355 catch (std::bad_alloc
)
357 pStripOffsets
= NULL
;
358 nNumStripOffsets
= 0;
362 for ( i
= 0; i
< nOldNumSO
; i
++ )
363 pStripOffsets
[ i
] = pOldSO
[ i
] + nOrigPos
;
364 for ( i
= nOldNumSO
; i
< nNumStripOffsets
; i
++ )
365 pStripOffsets
[ i
] = ReadIntData() + nOrigPos
;
369 OOODEBUG("StripOffsets (Anzahl:)",nDataLen
);
372 case 0x0112: // Orientation
373 nOrientation
= ReadIntData();
374 OOODEBUG("Orientation",nOrientation
);
377 case 0x0115: // Samples Per Pixel
378 nSamplesPerPixel
= ReadIntData();
379 OOODEBUG("SamplesPerPixel",nSamplesPerPixel
);
382 case 0x0116: // Rows Per Strip
383 nRowsPerStrip
= ReadIntData();
384 OOODEBUG("RowsPerStrip",nRowsPerStrip
);
387 case 0x0117: { // Strip Byte Counts
388 ULONG nOldNumSBC
, i
, * pOldSBC
;
389 pOldSBC
= pStripByteCounts
;
390 if ( pOldSBC
== NULL
)
391 nNumStripByteCounts
= 0; // Sicherheitshalber
392 nOldNumSBC
= nNumStripByteCounts
;
393 nDataLen
+= nOldNumSBC
;
394 if ( ( nDataLen
> nOldNumSBC
) && ( nDataLen
< SAL_MAX_UINT32
/ sizeof( sal_uInt32
) ) )
396 nNumStripByteCounts
= nDataLen
;
399 pStripByteCounts
= new ULONG
[ nNumStripByteCounts
];
401 catch (std::bad_alloc
)
403 pStripByteCounts
= NULL
;
404 nNumStripByteCounts
= 0;
406 if ( pStripByteCounts
)
408 for ( i
= 0; i
< nOldNumSBC
; i
++ )
409 pStripByteCounts
[ i
] = pOldSBC
[ i
];
410 for ( i
= nOldNumSBC
; i
< nNumStripByteCounts
; i
++)
411 pStripByteCounts
[ i
] = ReadIntData();
415 OOODEBUG("StripByteCounts (Anzahl:)",nDataLen
);
418 case 0x0118: // Min Sample Value
419 nMinSampleValue
= ReadIntData();
420 OOODEBUG("MinSampleValue",nMinSampleValue
);
423 case 0x0119: // Max Sample Value
424 nMaxSampleValue
= ReadIntData();
425 OOODEBUG("MaxSampleValue",nMaxSampleValue
);
428 case 0x011a: // X Resolution
429 fXResolution
= ReadDoubleData();
432 case 0x011b: // Y Resolution
433 fYResolution
= ReadDoubleData();
436 case 0x011c: // Planar Configuration
437 nPlanarConfiguration
= ReadIntData();
438 OOODEBUG("PlanarConfiguration",nPlanarConfiguration
);
441 case 0x0124: // Group 3 Options
442 nGroup3Options
= ReadIntData();
443 OOODEBUG("Group3Options",nGroup3Options
);
446 case 0x0125: // Group 4 Options
447 nGroup4Options
= ReadIntData();
448 OOODEBUG("Group4Options",nGroup4Options
);
451 case 0x0128: // Resolution Unit
452 nResolutionUnit
= ReadIntData();
455 case 0x013d: // Predictor
456 nPredictor
= ReadIntData();
457 OOODEBUG("Predictor",nPredictor
);
460 case 0x0140: { // Color Map
463 nNumColors
= ( 1 << nBitsPerSample
);
464 if ( nDataType
== 3 && nNumColors
<= 256)
466 pColorMap
= new ULONG
[ 256 ];
467 for ( i
= 0; i
< nNumColors
; i
++ )
469 for ( i
= 0; i
< nNumColors
; i
++ )
472 pColorMap
[ i
] |= ( ( (ULONG
)nVal
) << 8 ) & 0x00ff0000;
474 for ( i
= 0; i
< nNumColors
; i
++ )
477 pColorMap
[ i
] |= ( (ULONG
)nVal
) & 0x0000ff00;
479 for ( i
= 0; i
< nNumColors
; i
++ )
482 pColorMap
[ i
] |= ( ( (ULONG
)nVal
) >> 8 ) & 0x000000ff;
487 OOODEBUG("ColorMap (Anzahl Farben:)", nNumColors
);
492 if ( pTIFF
->GetError() )
496 // ---------------------------------------------------------------------------------
498 BOOL
TIFFReader::ReadMap( ULONG nMinPercent
, ULONG nMaxPercent
)
500 if ( nCompression
== 1 || nCompression
== 32771 )
502 ULONG ny
, np
, nStrip
, nStripBytesPerRow
;
504 if ( nCompression
== 1 )
505 nStripBytesPerRow
= nBytesPerRow
;
507 nStripBytesPerRow
= ( nBytesPerRow
+ 1 ) & 0xfffffffe;
508 for ( ny
= 0; ny
< nImageLength
; ny
++ )
510 for ( np
= 0; np
< nPlanes
; np
++ )
512 nStrip
= ny
/ nRowsPerStrip
+ np
* nStripsPerPlane
;
513 if ( nStrip
>= nNumStripOffsets
)
515 pTIFF
->Seek( pStripOffsets
[ nStrip
] + ( ny
% nRowsPerStrip
) * nStripBytesPerRow
);
516 pTIFF
->Read( pMap
[ np
], nBytesPerRow
);
517 if ( pTIFF
->GetError() )
519 MayCallback( nMinPercent
+ ( nMaxPercent
- nMinPercent
) * ( np
* nImageLength
+ ny
) / ( nImageLength
* nPlanes
) );
521 if ( !ConvertScanline( ny
) )
525 else if ( nCompression
== 2 || nCompression
== 3 || nCompression
== 4 )
527 ULONG ny
, np
, nStrip
, nOptions
;
528 if ( nCompression
== 2 )
530 nOptions
= CCI_OPTION_BYTEALIGNROW
;
532 else if ( nCompression
== 3 )
534 nOptions
= CCI_OPTION_EOL
;
535 if ( nGroup3Options
& 0x00000001 )
536 nOptions
|= CCI_OPTION_2D
;
537 if ( nGroup3Options
& 0x00000004 )
538 nOptions
|= CCI_OPTION_BYTEALIGNEOL
;
539 if ( nGroup3Options
& 0xfffffffa )
544 nOptions
= CCI_OPTION_2D
;
545 if ( nGroup4Options
& 0xffffffff )
548 if ( nFillOrder
== 2 )
550 nOptions
|= CCI_OPTION_INVERSEBITORDER
;
554 if ( nStrip
>= nNumStripOffsets
)
556 pTIFF
->Seek(pStripOffsets
[nStrip
]);
558 CCIDecompressor
aCCIDecom( nOptions
, nImageWidth
);
560 aCCIDecom
.StartDecompression( *pTIFF
);
562 for ( ny
= 0; ny
< nImageLength
; ny
++ )
564 for ( np
= 0; np
< nPlanes
; np
++ )
566 if ( ny
/ nRowsPerStrip
+ np
* nStripsPerPlane
> nStrip
)
568 nStrip
=ny
/nRowsPerStrip
+np
*nStripsPerPlane
;
569 if ( nStrip
>= nNumStripOffsets
)
571 pTIFF
->Seek( pStripOffsets
[ nStrip
] );
572 aCCIDecom
.StartDecompression( *pTIFF
);
574 if ( aCCIDecom
.DecompressScanline( pMap
[ np
], nImageWidth
* nBitsPerSample
* nSamplesPerPixel
/ nPlanes
) == FALSE
)
576 if ( pTIFF
->GetError() )
578 MayCallback(nMinPercent
+(nMaxPercent
-nMinPercent
)*(np
*nImageLength
+ny
)/(nImageLength
*nPlanes
));
580 if ( !ConvertScanline( ny
) )
584 else if ( nCompression
== 5 )
586 LZWDecompressor aLZWDecom
;
587 ULONG ny
, np
, nStrip
;
589 if ( nStrip
>= nNumStripOffsets
)
591 pTIFF
->Seek(pStripOffsets
[nStrip
]);
592 aLZWDecom
.StartDecompression(*pTIFF
);
593 for ( ny
= 0; ny
< nImageLength
; ny
++ )
595 for ( np
= 0; np
< nPlanes
; np
++ )
597 if ( ny
/ nRowsPerStrip
+ np
* nStripsPerPlane
> nStrip
)
599 nStrip
= ny
/ nRowsPerStrip
+ np
* nStripsPerPlane
;
600 if ( nStrip
>= nNumStripOffsets
)
602 pTIFF
->Seek(pStripOffsets
[nStrip
]);
603 aLZWDecom
.StartDecompression(*pTIFF
);
605 if ( ( aLZWDecom
.Decompress( pMap
[ np
], nBytesPerRow
) != nBytesPerRow
) || pTIFF
->GetError() )
607 MayCallback(nMinPercent
+(nMaxPercent
-nMinPercent
)*(np
*nImageLength
+ny
)/(nImageLength
*nPlanes
));
609 if ( !ConvertScanline( ny
) )
613 else if ( nCompression
== 32773 )
615 ULONG nStrip
,nRecCount
,nRowBytesLeft
,ny
,np
,i
;
616 BYTE
* pdst
, nRecHeader
, nRecData
;
618 if ( nStrip
>= nNumStripOffsets
)
620 pTIFF
->Seek(pStripOffsets
[nStrip
]);
621 for ( ny
= 0; ny
< nImageLength
; ny
++ )
623 for ( np
= 0; np
< nPlanes
; np
++ )
625 if ( ny
/ nRowsPerStrip
+ np
* nStripsPerPlane
> nStrip
)
627 nStrip
=ny
/nRowsPerStrip
+np
*nStripsPerPlane
;
628 if ( nStrip
>= nNumStripOffsets
)
630 pTIFF
->Seek(pStripOffsets
[nStrip
]);
632 nRowBytesLeft
= nBytesPerRow
;
636 *pTIFF
>> nRecHeader
;
637 if ((nRecHeader
&0x80)==0)
639 nRecCount
=0x00000001+((ULONG
)nRecHeader
);
640 if ( nRecCount
> nRowBytesLeft
)
642 pTIFF
->Read(pdst
,nRecCount
);
644 nRowBytesLeft
-=nRecCount
;
646 else if ( nRecHeader
!= 0x80 )
648 nRecCount
= 0x000000101 - ( (ULONG
)nRecHeader
);
649 if ( nRecCount
> nRowBytesLeft
)
651 nRecCount
= nRowBytesLeft
;
658 for ( i
= 0; i
< nRecCount
; i
++ )
659 *(pdst
++) = nRecData
;
660 nRowBytesLeft
-= nRecCount
;
662 } while ( nRowBytesLeft
!= 0 );
663 if ( pTIFF
->GetError() )
665 MayCallback(nMinPercent
+(nMaxPercent
-nMinPercent
)*(np
*nImageLength
+ny
)/(nImageLength
*nPlanes
));
667 if ( !ConvertScanline( ny
) )
676 ULONG
TIFFReader::GetBits( const BYTE
* pSrc
, ULONG nBitsPos
, ULONG nBitsCount
)
681 pSrc
+= ( nBitsPos
>> 3 );
684 nRes
= (ULONG
)( BYTESWAP( nDat
) & ( 0xff >> nBitsPos
) );
686 if ( nBitsCount
<= 8 - nBitsPos
)
688 nRes
>>= ( 8 - nBitsPos
- nBitsCount
);
693 nBitsCount
-= 8 - nBitsPos
;
694 while ( nBitsCount
>= 8 )
697 nRes
= ( nRes
<< 8 ) | ((ULONG
)BYTESWAP( nDat
) );
700 if ( nBitsCount
> 0 )
703 nRes
= ( nRes
<< nBitsCount
) | (((ULONG
)BYTESWAP(nDat
))>>(8-nBitsCount
));
709 pSrc
+= ( nBitsPos
>> 3 );
711 nRes
= (ULONG
)((*pSrc
)&(0xff>>nBitsPos
));
712 if ( nBitsCount
<= 8 - nBitsPos
)
714 nRes
>>= ( 8 - nBitsPos
- nBitsCount
);
719 nBitsCount
-= 8 - nBitsPos
;
720 while ( nBitsCount
>= 8 )
722 nRes
= ( nRes
<< 8 ) | ((ULONG
)*(pSrc
++));
725 if ( nBitsCount
> 0 )
726 nRes
= ( nRes
<< nBitsCount
) | (((ULONG
)*pSrc
)>>(8-nBitsCount
));
732 // ---------------------------------------------------------------------------------
734 BOOL
TIFFReader::ConvertScanline( ULONG nY
)
736 UINT32 nRed
, nGreen
, nBlue
, ns
, nx
, nVal
, nByteCount
;
739 if ( nDstBitsPerPixel
== 24 )
741 if ( nBitsPerSample
== 8 && nSamplesPerPixel
>= 3 &&
742 nPlanes
== 1 && nPhotometricInterpretation
== 2 )
744 BYTE
* pt
= pMap
[ 0 ];
746 // sind die Werte als Differenz abgelegt?
747 if ( 2 == nPredictor
)
752 for ( nx
= 0; nx
< nImageWidth
; nx
++, pt
+= nSamplesPerPixel
)
754 nLRed
= nLRed
+ pt
[ 0 ];
755 nLGreen
= nLGreen
+ pt
[ 1 ];
756 nLBlue
= nLBlue
+ pt
[ 2 ];
757 pAcc
->SetPixel( nY
, nx
, Color( nLRed
, nLGreen
, nLBlue
) );
762 for ( nx
= 0; nx
< nImageWidth
; nx
++, pt
+= nSamplesPerPixel
)
764 pAcc
->SetPixel( nY
, nx
, Color( pt
[0], pt
[1], pt
[2] ) );
768 else if ( nPhotometricInterpretation
== 2 && nSamplesPerPixel
>= 3 )
770 ULONG nMinMax
= nMinSampleValue
* 255 / ( nMaxSampleValue
- nMinSampleValue
);
771 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
775 nRed
= GetBits( pMap
[ 0 ], ( nx
* nSamplesPerPixel
+ 0 ) * nBitsPerSample
, nBitsPerSample
);
776 nGreen
= GetBits( pMap
[ 1 ], ( nx
* nSamplesPerPixel
+ 1 ) * nBitsPerSample
, nBitsPerSample
);
777 nBlue
= GetBits( pMap
[ 2 ], ( nx
* nSamplesPerPixel
+ 2 ) * nBitsPerSample
, nBitsPerSample
);
781 nRed
= GetBits( pMap
[ 0 ], nx
* nBitsPerSample
, nBitsPerSample
);
782 nGreen
= GetBits( pMap
[ 1 ], nx
* nBitsPerSample
, nBitsPerSample
);
783 nBlue
= GetBits( pMap
[ 2 ], nx
* nBitsPerSample
, nBitsPerSample
);
785 pAcc
->SetPixel( nY
, nx
, Color( (BYTE
)( nRed
- nMinMax
), (BYTE
)( nGreen
- nMinMax
), (BYTE
)(nBlue
- nMinMax
) ) );
788 else if ( nPhotometricInterpretation
== 5 && nSamplesPerPixel
== 3 )
790 ULONG nMinMax
= nMinSampleValue
* 255 / ( nMaxSampleValue
- nMinSampleValue
);
791 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
795 nRed
= GetBits( pMap
[ 0 ],( nx
* nSamplesPerPixel
+ 0 ) * nBitsPerSample
, nBitsPerSample
);
796 nGreen
= GetBits( pMap
[ 0 ],( nx
* nSamplesPerPixel
+ 1 ) * nBitsPerSample
, nBitsPerSample
);
797 nBlue
= GetBits( pMap
[ 0 ],( nx
* nSamplesPerPixel
+ 2 ) * nBitsPerSample
, nBitsPerSample
);
801 nRed
= GetBits( pMap
[ 0 ], nx
* nBitsPerSample
, nBitsPerSample
);
802 nGreen
= GetBits( pMap
[ 1 ], nx
* nBitsPerSample
, nBitsPerSample
);
803 nBlue
= GetBits( pMap
[ 2 ], nx
* nBitsPerSample
, nBitsPerSample
);
805 nRed
= 255 - (BYTE
)( nRed
- nMinMax
);
806 nGreen
= 255 - (BYTE
)( nGreen
- nMinMax
);
807 nBlue
= 255 - (BYTE
)( nBlue
- nMinMax
);
808 pAcc
->SetPixel( nY
, nx
, Color( (BYTE
) nRed
, (BYTE
) nGreen
, (BYTE
) nBlue
) );
811 else if( nPhotometricInterpretation
== 5 && nSamplesPerPixel
== 4 )
814 BYTE nSampLast
[ 4 ] = { 0, 0, 0, 0 };
817 for( nx
= 0; nx
< nImageWidth
; nx
++ )
819 // sind die Werte als Differenz abgelegt?
820 if( 2 == nPredictor
)
822 for( ns
= 0; ns
< 4; ns
++ )
825 nSampLast
[ ns
] = nSampLast
[ ns
] + (BYTE
) GetBits( pMap
[ 0 ], ( nx
* nSamplesPerPixel
+ ns
) * nBitsPerSample
, nBitsPerSample
);
827 nSampLast
[ ns
] = nSampLast
[ ns
] + (BYTE
) GetBits( pMap
[ ns
], nx
* nBitsPerSample
, nBitsPerSample
);
828 nSamp
[ ns
] = nSampLast
[ ns
];
833 for( ns
= 0; ns
< 4; ns
++ )
836 nSamp
[ ns
] = (BYTE
) GetBits( pMap
[ 0 ], ( nx
* nSamplesPerPixel
+ ns
) * nBitsPerSample
, nBitsPerSample
);
838 nSamp
[ ns
]= (BYTE
) GetBits( pMap
[ ns
], nx
* nBitsPerSample
, nBitsPerSample
);
842 nRed
= (BYTE
) Max( 0L, 255L - ( ( (long) nSamp
[ 0 ] + nBlack
- ( ( (long) nMinSampleValue
) << 1 ) ) *
843 255L/(long)(nMaxSampleValue
-nMinSampleValue
) ) );
844 nGreen
= (BYTE
) Max( 0L, 255L - ( ( (long) nSamp
[ 1 ] + nBlack
- ( ( (long) nMinSampleValue
) << 1 ) ) *
845 255L/(long)(nMaxSampleValue
-nMinSampleValue
) ) );
846 nBlue
= (BYTE
) Max( 0L, 255L - ( ( (long) nSamp
[ 2 ] + nBlack
- ( ( (long) nMinSampleValue
) << 1 ) ) *
847 255L/(long)(nMaxSampleValue
-nMinSampleValue
) ) );
848 pAcc
->SetPixel( nY
, nx
, Color ( (BYTE
)nRed
, (BYTE
)nGreen
, (BYTE
)nBlue
) );
853 else if ( nSamplesPerPixel
== 1 && ( nPhotometricInterpretation
<= 1 || nPhotometricInterpretation
== 3 ) )
855 ULONG nMinMax
= ( ( 1 << nDstBitsPerPixel
) - 1 ) / ( nMaxSampleValue
- nMinSampleValue
);
856 BYTE
* pt
= pMap
[ 0 ];
859 switch ( nDstBitsPerPixel
)
866 if ( nPredictor
== 2 )
868 nLast
= BYTESWAP( (BYTE
)*pt
++ );
869 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
871 pAcc
->SetPixel( nY
, nx
, nLast
);
872 nLast
= nLast
+ *pt
++;
877 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
880 pAcc
->SetPixel( nY
, nx
, (BYTE
)( ( (BYTESWAP((ULONG
)nLast
) - nMinSampleValue
) * nMinMax
) ) );
886 if ( nPredictor
== 2 )
889 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
891 pAcc
->SetPixel( nY
, nx
, nLast
);
892 nLast
= nLast
+ *pt
++;
897 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
899 pAcc
->SetPixel( nY
, nx
, (BYTE
)( ( (ULONG
)*pt
++ - nMinSampleValue
) * nMinMax
) );
914 for ( nx
= 0; nx
< nImageWidth
; nx
++ )
916 nVal
= ( GetBits( pt
, nx
* nBitsPerSample
, nBitsPerSample
) - nMinSampleValue
) * nMinMax
;
917 pAcc
->SetPixel( nY
, nx
, (BYTE
)nVal
);
927 nByteCount
= ( nImageWidth
>> 3 ) + 1;
928 while ( --nByteCount
)
931 pAcc
->SetPixel( nY
, nx
++, nByteVal
& 1 );
933 pAcc
->SetPixel( nY
, nx
++, nByteVal
& 1 );
935 pAcc
->SetPixel( nY
, nx
++, nByteVal
& 1 );
937 pAcc
->SetPixel( nY
, nx
++, nByteVal
& 1 );
939 pAcc
->SetPixel( nY
, nx
++, nByteVal
& 1 );
941 pAcc
->SetPixel( nY
, nx
++, nByteVal
& 1 );
943 pAcc
->SetPixel( nY
, nx
++, nByteVal
& 1 );
945 pAcc
->SetPixel( nY
, nx
++, nByteVal
);
947 if ( nImageWidth
& 7 )
950 while ( nx
< nImageWidth
)
952 pAcc
->SetPixel( nY
, nx
++, nByteVal
& 1 );
960 nByteCount
= ( nImageWidth
>> 3 ) + 1;
961 while ( --nByteCount
)
964 pAcc
->SetPixel( nY
, nx
, nByteVal
& 1 );
966 pAcc
->SetPixel( nY
, --nx
, nByteVal
& 1 );
968 pAcc
->SetPixel( nY
, --nx
, nByteVal
& 1 );
970 pAcc
->SetPixel( nY
, --nx
, nByteVal
& 1 );
972 pAcc
->SetPixel( nY
, --nx
, nByteVal
& 1 );
974 pAcc
->SetPixel( nY
, --nx
, nByteVal
& 1 );
976 pAcc
->SetPixel( nY
, --nx
, nByteVal
& 1 );
978 pAcc
->SetPixel( nY
, --nx
, nByteVal
);
981 if ( nImageWidth
& 7 )
986 while ( nx
< nImageWidth
)
988 pAcc
->SetPixel( nY
, nx
++, ( nByteVal
>> nShift
) & 1);
999 else if ( ( nSamplesPerPixel
== 2 ) && ( nBitsPerSample
== 8 ) &&
1000 ( nPlanarConfiguration
== 1 ) && ( pColorMap
== 0 ) ) // grayscale
1002 ULONG nMinMax
= ( ( 1 << 8 /*nDstBitsPerPixel*/ ) - 1 ) / ( nMaxSampleValue
- nMinSampleValue
);
1003 BYTE
* pt
= pMap
[ 0 ];
1004 if ( nByte1
== 'I' )
1006 for ( nx
= 0; nx
< nImageWidth
; nx
++, pt
+= 2 )
1008 pAcc
->SetPixel( nY
, nx
, (BYTE
)( ( (ULONG
)*pt
- nMinSampleValue
) * nMinMax
) );
1016 // ---------------------------------------------------------------------------------
1018 void TIFFReader::MakePalCol( void )
1020 if ( nDstBitsPerPixel
<= 8 )
1022 ULONG i
, nVal
, n0RGB
;
1023 if ( pColorMap
== NULL
)
1024 pColorMap
= new ULONG
[ 256 ];
1025 if ( nPhotometricInterpretation
<= 1 )
1027 nNumColors
= 1 << nBitsPerSample
;
1028 if ( nNumColors
> 256 )
1030 pAcc
->SetPaletteEntryCount( (USHORT
)nNumColors
);
1031 for ( i
= 0; i
< nNumColors
; i
++ )
1033 nVal
= ( i
* 255 / ( nNumColors
- 1 ) ) & 0xff;
1034 n0RGB
= nVal
| ( nVal
<< 8 ) | ( nVal
<< 16 );
1035 if ( nPhotometricInterpretation
== 1 )
1036 pColorMap
[ i
] = n0RGB
;
1038 pColorMap
[ nNumColors
- i
- 1 ] = n0RGB
;
1041 for ( i
= 0; i
< nNumColors
; i
++ )
1043 pAcc
->SetPaletteColor( (USHORT
)i
, BitmapColor( (BYTE
)( pColorMap
[ i
] >> 16 ),
1044 (BYTE
)( pColorMap
[ i
] >> 8 ), (BYTE
)pColorMap
[ i
] ) );
1048 if ( fXResolution
> 1.0 && fYResolution
> 1.0 && ( nResolutionUnit
== 2 || nResolutionUnit
== 3 ) )
1051 if (nResolutionUnit
==2)
1053 nRX
=(ULONG
)(fXResolution
+0.5);
1054 nRY
=(ULONG
)(fYResolution
+0.5);
1058 nRX
=(ULONG
)(fXResolution
*2.54+0.5);
1059 nRY
=(ULONG
)(fYResolution
*2.54+0.5);
1061 MapMode
aMapMode(MAP_INCH
,Point(0,0),Fraction(1,nRX
),Fraction(1,nRY
));
1062 aBitmap
.SetPrefMapMode(aMapMode
);
1063 aBitmap
.SetPrefSize(Size(nImageWidth
,nImageLength
));
1067 // ---------------------------------------------------------------------------------
1069 void TIFFReader::ReadHeader()
1071 BYTE nbyte1
, nbyte2
;
1075 if ( nbyte1
== 'I' )
1076 pTIFF
->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
1078 pTIFF
->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN
);
1080 *pTIFF
>> nbyte2
>> nushort
;
1081 if ( nbyte1
!= nbyte2
|| ( nbyte1
!= 'I' && nbyte1
!= 'M' ) || nushort
!= 0x002a )
1085 // ---------------------------------------------------------------------------------
1087 BOOL
TIFFReader::ReadTIFF(SvStream
& rTIFF
, Graphic
& rGraphic
)
1089 USHORT i
, nNumTags
, nTagType
;
1092 sal_uInt32 nFirstIfd
, nDataLen
;
1098 nMaxPos
= nOrigPos
= pTIFF
->Tell();
1099 nOrigNumberFormat
= pTIFF
->GetNumberFormatInt();
1106 // Ersten IFD einlesen:
1107 *pTIFF
>> nFirstIfd
;
1109 if( !nFirstIfd
|| pTIFF
->GetError() )
1114 sal_uInt32 nOffset
= nFirstIfd
;
1116 // calculate length of TIFF file
1119 pTIFF
->Seek( nOrigPos
+ nOffset
);
1121 if( pTIFF
->GetError() )
1123 pTIFF
->ResetError();
1126 nMaxPos
= Max( pTIFF
->Tell(), nMaxPos
);
1130 // Schleife ueber Tags:
1131 for( i
= 0; i
< nNumTags
; i
++ )
1133 *pTIFF
>> nTagType
>> nDataType
>> nDataLen
>> nOffset
;
1135 if( DataTypeSize() * nDataLen
> 4 )
1136 nMaxPos
= Max( nOrigPos
+ nOffset
+ DataTypeSize() * nDataLen
, nMaxPos
);
1139 if ( pTIFF
->IsEof() )
1142 nMaxPos
= Max( pTIFF
->Tell(), nMaxPos
);
1144 nMaxPos
= Max( pTIFF
->Tell(), nMaxPos
);
1148 for ( UINT32 nNextIfd
= nFirstIfd
; nNextIfd
&& bStatus
; )
1150 pTIFF
->Seek( nOrigPos
+ nNextIfd
);
1158 nBitsPerSample
= 1; // Defaultwert laut Doku
1160 nPhotometricInterpretation
= 0;
1161 nThresholding
= 1; // Defaultwert laut Doku
1164 nFillOrder
= 1; // Defaultwert laut Doku
1165 nNumStripOffsets
= 0;
1167 nSamplesPerPixel
= 1; // Defaultwert laut Doku
1168 nRowsPerStrip
= 0xffffffff; // Defaultwert laut Doku
1169 nNumStripByteCounts
= 0;
1170 nMinSampleValue
= 0; // Defaultwert laut Doku
1171 nMaxSampleValue
= 0;
1174 nPlanarConfiguration
= 1;
1175 nGroup3Options
= 0; // Defaultwert laut Doku
1176 nGroup4Options
= 0; // Defaultwert laut Doku
1177 nResolutionUnit
= 2; // Defaultwert laut Doku
1183 pStripOffsets
= NULL
;
1184 pStripByteCounts
= NULL
;
1185 pMap
[ 0 ] = pMap
[ 1 ] = pMap
[ 2 ] = pMap
[ 3 ] = NULL
;
1188 nPos
= pTIFF
->Tell();
1190 // Schleife ueber Tags:
1191 for( i
= 0; i
< nNumTags
; i
++ )
1193 *pTIFF
>> nTagType
>> nDataType
>> nDataLen
;
1195 if( DataTypeSize() * nDataLen
> 4 )
1198 pTIFF
->Seek( nOrigPos
+ nOffset
);
1200 ReadTagData( nTagType
, nDataLen
);
1201 nPos
+= 12; pTIFF
->Seek( nPos
);
1203 if ( pTIFF
->GetError() )
1206 if ( bStatus
== FALSE
)
1210 if ( pTIFF
->IsEof() )
1215 if ( nMaxSampleValue
== 0 )
1216 nMaxSampleValue
= ( 1 << nBitsPerSample
) - 1;
1218 if ( nPhotometricInterpretation
== 2 || nPhotometricInterpretation
== 5 || nPhotometricInterpretation
== 6 )
1219 nDstBitsPerPixel
= 24;
1220 else if ( nBitsPerSample
*nSamplesPerPixel
<= 1 )
1221 nDstBitsPerPixel
= 1;
1222 else if ( nBitsPerSample
*nSamplesPerPixel
<= 4 )
1223 nDstBitsPerPixel
= 4;
1225 nDstBitsPerPixel
= 8;
1227 aBitmap
= Bitmap( Size( nImageWidth
, nImageLength
), nDstBitsPerPixel
);
1228 pAcc
= aBitmap
.AcquireWriteAccess();
1231 if ( nPlanarConfiguration
== 1 )
1234 nPlanes
= nSamplesPerPixel
;
1236 if ( ( nFillOrder
== 2 ) && ( nCompression
!= 5 ) ) // im LZW Mode werden die bits schon invertiert
1239 nStripsPerPlane
= ( nImageLength
- 1 ) / nRowsPerStrip
+ 1;
1240 nBytesPerRow
= ( nImageWidth
* nSamplesPerPixel
/ nPlanes
* nBitsPerSample
+ 7 ) >> 3;
1242 for ( ULONG j
= 0; j
< 4; j
++ )
1246 pMap
[ j
] = new BYTE
[ nBytesPerRow
];
1248 catch (std::bad_alloc
)
1256 if ( bStatus
&& ReadMap( 10, 60 ) )
1258 nMaxPos
= Max( pTIFF
->Tell(), nMaxPos
);
1260 nMaxPos
= Max( pTIFF
->Tell(), nMaxPos
);
1267 aBitmap
.ReleaseAccess( pAcc
);
1270 AnimationBitmap
aAnimationBitmap( aBitmap
, Point( 0, 0 ), aBitmap
.GetSizePixel(),
1271 ANIMATION_TIMEOUT_ON_CLICK
, DISPOSE_BACK
);
1273 aAnimation
.Insert( aAnimationBitmap
);
1277 for ( i
= 0; i
< 4; i
++ )
1281 delete[] pStripOffsets
;
1282 delete[] pStripByteCounts
;
1288 // seek to end of TIFF if succeeded
1289 pTIFF
->SetNumberFormatInt( nOrigNumberFormat
);
1290 pTIFF
->Seek( bStatus
? nMaxPos
: nOrigPos
);
1292 if ( aAnimation
.Count() )
1294 if ( aAnimation
.Count() == 1 )
1295 rGraphic
= aAnimation
.GetBitmapEx();
1297 rGraphic
= aAnimation
; //aBitmap;
1306 //================== GraphicImport - die exportierte Funktion ================
1308 extern "C" BOOL __LOADONCALLAPI
GraphicImport(SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
*, BOOL
)
1310 TIFFReader aTIFFReader
;
1312 if ( aTIFFReader
.ReadTIFF( rStream
, rGraphic
) == FALSE
)
1318 //============================= fuer Windows ==================================
1324 static HINSTANCE hDLLInst
= 0; // HANDLE der DLL
1326 extern "C" int CALLBACK
LibMain( HINSTANCE hDLL
, WORD
, WORD nHeap
, LPSTR
)
1338 extern "C" int CALLBACK
WEP( int )