Update ooo320-m1
[ooovba.git] / goodies / source / filter.vcl / itiff / itiff.cxx
blobc1daaa58c732ef6ab0f1685da43b04c709be4ea0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: itiff.cxx,v $
10 * $Revision: 1.16 $
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>
37 #endif
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();
44 namespace {
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 ==================================
57 class TIFFReader
60 private:
62 BOOL bStatus; // Ob bisher kein Fehler auftrat
63 Animation aAnimation;
64 ULONG nLastPercent;
66 SvStream* pTIFF; // Die einzulesende TIFF-Datei
67 Bitmap aBitmap;
68 BitmapWriteAccess* pAcc;
69 USHORT nDstBitsPerPixel;
71 ULONG nOrigPos; // Anfaengliche Position in pTIFF
72 UINT16 nOrigNumberFormat; // Anfaengliches Nummern-Format von pTIFF
75 UINT16 nDataType;
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
80 ULONG nNewSubFile; //
81 ULONG nSubFile; //
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; //
88 ULONG nCellWidth; //
89 ULONG nCellLength; //
90 ULONG nFillOrder; //
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
106 ULONG nPredictor; //
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();
119 ULONG ReadIntData();
120 double ReadDoubleData();
122 void ReadHeader();
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
137 public:
139 TIFFReader() {}
140 ~TIFFReader() {}
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 )
156 bStatus = FALSE;
162 // ---------------------------------------------------------------------------------
164 ULONG TIFFReader::DataTypeSize()
166 ULONG nSize;
167 switch ( nDataType )
169 case 1 : // BYTE
170 case 2 : // ACSII
171 case 6 : // SIGNED Byte
172 case 7 : // UNDEFINED
173 nSize = 1;
174 break;
175 case 3 : // UINT16
176 case 8 : // INT16
177 nSize = 2;
178 break;
179 case 4 : // UINT32
180 case 9 : // INT32
181 case 11 : // FLOAT
182 nSize = 4;
183 break;
184 case 5 : // RATIONAL
185 case 10 : // SIGNED RATINAL
186 case 12 : // DOUBLE
187 nSize = 8;
188 break;
189 default:
190 pTIFF->SetError(SVSTREAM_FILEFORMAT_ERROR);
191 nSize=1;
193 return nSize;
196 // ---------------------------------------------------------------------------------
198 ULONG TIFFReader::ReadIntData()
200 double nDOUBLE;
201 float nFLOAT;
202 UINT32 nUINT32a, nUINT32b;
203 INT32 nINT32;
204 UINT16 nUINT16;
205 INT16 nINT16;
206 BYTE nBYTE;
207 char nCHAR;
209 switch( nDataType )
211 case 0 : //??
212 case 1 :
213 case 2 :
214 case 7 :
215 *pTIFF >> nBYTE;
216 nUINT32a = (ULONG)nBYTE;
217 break;
218 case 3 :
219 *pTIFF >> nUINT16;
220 nUINT32a = (ULONG)nUINT16;
221 break;
222 case 9 :
223 case 4 :
224 *pTIFF >> nUINT32a;
225 break;
226 case 5 :
227 *pTIFF >> nUINT32a >> nUINT32b;
228 if ( nUINT32b != 0 )
229 nUINT32a /= nUINT32b;
230 break;
231 case 6 :
232 *pTIFF >> nCHAR;
233 nUINT32a = (INT32)nCHAR;
234 break;
235 case 8 :
236 *pTIFF >> nINT16;
237 nUINT32a = (INT32)nINT16;
238 break;
239 case 10 :
240 *pTIFF >> nUINT32a >> nINT32;
241 if ( nINT32 != 0 )
242 nUINT32a /= nINT32;
243 break;
244 case 11 :
245 *pTIFF >> nFLOAT;
246 nUINT32a = (INT32)nFLOAT;
247 break;
248 case 12 :
249 *pTIFF >> nDOUBLE;
250 nUINT32a = (INT32)nDOUBLE;
251 break;
252 default:
253 *pTIFF >> nUINT32a;
254 break;
256 return nUINT32a;
259 // ---------------------------------------------------------------------------------
261 double TIFFReader::ReadDoubleData()
263 sal_uInt32 nulong;
264 double nd;
266 if ( nDataType == 5 )
268 *pTIFF >> nulong;
269 nd = (double)nulong;
270 *pTIFF >> nulong;
271 if ( nulong != 0 )
272 nd /= (double)nulong;
274 else
275 nd = (double)ReadIntData();
276 return nd;
279 // ---------------------------------------------------------------------------------
281 void TIFFReader::ReadTagData( USHORT nTagType, sal_uInt32 nDataLen)
283 if ( bStatus == FALSE )
284 return;
286 switch ( nTagType )
288 case 0x00fe: // New Sub File
289 nNewSubFile = ReadIntData();
290 OOODEBUG("NewSubFile",nNewSubFile);
291 break;
293 case 0x00ff: // Sub File
294 nSubFile = ReadIntData();
295 OOODEBUG("SubFile",nSubFile);
296 break;
298 case 0x0100: // Image Width
299 nImageWidth = ReadIntData();
300 OOODEBUG("ImageWidth",nImageWidth);
301 break;
303 case 0x0101: // Image Length
304 nImageLength = ReadIntData();
305 OOODEBUG("ImageLength",nImageLength);
306 break;
308 case 0x0102: // Bits Per Sample
309 nBitsPerSample = ReadIntData();
310 OOODEBUG("BitsPerSample",nBitsPerSample);
311 break;
313 case 0x0103: // Compression
314 nCompression = ReadIntData();
315 OOODEBUG("Compression",nCompression);
316 break;
318 case 0x0106: // Photometric Interpreation
319 nPhotometricInterpretation = ReadIntData();
320 OOODEBUG("PhotometricInterpretation",nPhotometricInterpretation);
321 break;
323 case 0x0107: // Thresholding
324 nThresholding = ReadIntData();
325 OOODEBUG("Thresholding",nThresholding);
326 break;
328 case 0x0108: // Cell Width
329 nCellWidth = ReadIntData();
330 break;
332 case 0x0109: // Cell Length
333 nCellLength = ReadIntData();
334 break;
336 case 0x010a: // Fill Order
337 nFillOrder = ReadIntData();
338 OOODEBUG("FillOrder",nFillOrder);
339 break;
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;
360 if ( pStripOffsets )
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;
367 delete[] pOldSO;
369 OOODEBUG("StripOffsets (Anzahl:)",nDataLen);
370 break;
372 case 0x0112: // Orientation
373 nOrientation = ReadIntData();
374 OOODEBUG("Orientation",nOrientation);
375 break;
377 case 0x0115: // Samples Per Pixel
378 nSamplesPerPixel = ReadIntData();
379 OOODEBUG("SamplesPerPixel",nSamplesPerPixel);
380 break;
382 case 0x0116: // Rows Per Strip
383 nRowsPerStrip = ReadIntData();
384 OOODEBUG("RowsPerStrip",nRowsPerStrip);
385 break;
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();
413 delete[] pOldSBC;
415 OOODEBUG("StripByteCounts (Anzahl:)",nDataLen);
416 break;
418 case 0x0118: // Min Sample Value
419 nMinSampleValue = ReadIntData();
420 OOODEBUG("MinSampleValue",nMinSampleValue);
421 break;
423 case 0x0119: // Max Sample Value
424 nMaxSampleValue = ReadIntData();
425 OOODEBUG("MaxSampleValue",nMaxSampleValue);
426 break;
428 case 0x011a: // X Resolution
429 fXResolution = ReadDoubleData();
430 break;
432 case 0x011b: // Y Resolution
433 fYResolution = ReadDoubleData();
434 break;
436 case 0x011c: // Planar Configuration
437 nPlanarConfiguration = ReadIntData();
438 OOODEBUG("PlanarConfiguration",nPlanarConfiguration);
439 break;
441 case 0x0124: // Group 3 Options
442 nGroup3Options = ReadIntData();
443 OOODEBUG("Group3Options",nGroup3Options);
444 break;
446 case 0x0125: // Group 4 Options
447 nGroup4Options = ReadIntData();
448 OOODEBUG("Group4Options",nGroup4Options);
449 break;
451 case 0x0128: // Resolution Unit
452 nResolutionUnit = ReadIntData();
453 break;
455 case 0x013d: // Predictor
456 nPredictor = ReadIntData();
457 OOODEBUG("Predictor",nPredictor);
458 break;
460 case 0x0140: { // Color Map
461 USHORT nVal;
462 ULONG i;
463 nNumColors= ( 1 << nBitsPerSample );
464 if ( nDataType == 3 && nNumColors <= 256)
466 pColorMap = new ULONG[ 256 ];
467 for ( i = 0; i < nNumColors; i++ )
468 pColorMap[ i ] = 0;
469 for ( i = 0; i < nNumColors; i++ )
471 *pTIFF >> nVal;
472 pColorMap[ i ] |= ( ( (ULONG)nVal ) << 8 ) & 0x00ff0000;
474 for ( i = 0; i < nNumColors; i++ )
476 *pTIFF >> nVal;
477 pColorMap[ i ] |= ( (ULONG)nVal ) & 0x0000ff00;
479 for ( i = 0; i < nNumColors; i++ )
481 *pTIFF >> nVal;
482 pColorMap[ i ] |= ( ( (ULONG)nVal ) >> 8 ) & 0x000000ff;
485 else
486 bStatus = FALSE;
487 OOODEBUG("ColorMap (Anzahl Farben:)", nNumColors);
488 break;
492 if ( pTIFF->GetError() )
493 bStatus = FALSE;
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;
506 else
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 )
514 return FALSE;
515 pTIFF->Seek( pStripOffsets[ nStrip ] + ( ny % nRowsPerStrip ) * nStripBytesPerRow );
516 pTIFF->Read( pMap[ np ], nBytesPerRow );
517 if ( pTIFF->GetError() )
518 return FALSE;
519 MayCallback( nMinPercent + ( nMaxPercent - nMinPercent ) * ( np * nImageLength + ny) / ( nImageLength * nPlanes ) );
521 if ( !ConvertScanline( ny ) )
522 return FALSE;
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 )
540 return FALSE;
542 else
543 { // nCompression==4
544 nOptions = CCI_OPTION_2D;
545 if ( nGroup4Options & 0xffffffff )
546 return FALSE;
548 if ( nFillOrder == 2 )
550 nOptions |= CCI_OPTION_INVERSEBITORDER;
551 bByteSwap = FALSE;
553 nStrip = 0;
554 if ( nStrip >= nNumStripOffsets )
555 return FALSE;
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 )
570 return FALSE;
571 pTIFF->Seek( pStripOffsets[ nStrip ] );
572 aCCIDecom.StartDecompression( *pTIFF );
574 if ( aCCIDecom.DecompressScanline( pMap[ np ], nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes ) == FALSE )
575 return FALSE;
576 if ( pTIFF->GetError() )
577 return FALSE;
578 MayCallback(nMinPercent+(nMaxPercent-nMinPercent)*(np*nImageLength+ny)/(nImageLength*nPlanes));
580 if ( !ConvertScanline( ny ) )
581 return FALSE;
584 else if ( nCompression == 5 )
586 LZWDecompressor aLZWDecom;
587 ULONG ny, np, nStrip;
588 nStrip=0;
589 if ( nStrip >= nNumStripOffsets )
590 return FALSE;
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 )
601 return FALSE;
602 pTIFF->Seek(pStripOffsets[nStrip]);
603 aLZWDecom.StartDecompression(*pTIFF);
605 if ( ( aLZWDecom.Decompress( pMap[ np ], nBytesPerRow ) != nBytesPerRow ) || pTIFF->GetError() )
606 return FALSE;
607 MayCallback(nMinPercent+(nMaxPercent-nMinPercent)*(np*nImageLength+ny)/(nImageLength*nPlanes));
609 if ( !ConvertScanline( ny ) )
610 return FALSE;
613 else if ( nCompression == 32773 )
615 ULONG nStrip,nRecCount,nRowBytesLeft,ny,np,i;
616 BYTE * pdst, nRecHeader, nRecData;
617 nStrip = 0;
618 if ( nStrip >= nNumStripOffsets )
619 return FALSE;
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 )
629 return FALSE;
630 pTIFF->Seek(pStripOffsets[nStrip]);
632 nRowBytesLeft = nBytesPerRow;
633 pdst=pMap[ np ];
636 *pTIFF >> nRecHeader;
637 if ((nRecHeader&0x80)==0)
639 nRecCount=0x00000001+((ULONG)nRecHeader);
640 if ( nRecCount > nRowBytesLeft )
641 return FALSE;
642 pTIFF->Read(pdst,nRecCount);
643 pdst+=nRecCount;
644 nRowBytesLeft-=nRecCount;
646 else if ( nRecHeader != 0x80 )
648 nRecCount = 0x000000101 - ( (ULONG)nRecHeader );
649 if ( nRecCount > nRowBytesLeft )
651 nRecCount = nRowBytesLeft;
653 // bStatus = FALSE;
654 // return;
657 *pTIFF >> nRecData;
658 for ( i = 0; i < nRecCount; i++ )
659 *(pdst++) = nRecData;
660 nRowBytesLeft -= nRecCount;
662 } while ( nRowBytesLeft != 0 );
663 if ( pTIFF->GetError() )
664 return FALSE;
665 MayCallback(nMinPercent+(nMaxPercent-nMinPercent)*(np*nImageLength+ny)/(nImageLength*nPlanes));
667 if ( !ConvertScanline( ny ) )
668 return FALSE;
671 else
672 return FALSE;
673 return TRUE;
676 ULONG TIFFReader::GetBits( const BYTE * pSrc, ULONG nBitsPos, ULONG nBitsCount )
678 ULONG nRes;
679 if ( bByteSwap )
681 pSrc += ( nBitsPos >> 3 );
682 nBitsPos &= 7;
683 BYTE nDat = *pSrc;
684 nRes = (ULONG)( BYTESWAP( nDat ) & ( 0xff >> nBitsPos ) );
686 if ( nBitsCount <= 8 - nBitsPos )
688 nRes >>= ( 8 - nBitsPos - nBitsCount );
690 else
692 pSrc++;
693 nBitsCount -= 8 - nBitsPos;
694 while ( nBitsCount >= 8 )
696 nDat = *(pSrc++);
697 nRes = ( nRes << 8 ) | ((ULONG)BYTESWAP( nDat ) );
698 nBitsCount -= 8;
700 if ( nBitsCount > 0 )
702 nDat = *pSrc;
703 nRes = ( nRes << nBitsCount ) | (((ULONG)BYTESWAP(nDat))>>(8-nBitsCount));
707 else
709 pSrc += ( nBitsPos >> 3 );
710 nBitsPos &= 7;
711 nRes = (ULONG)((*pSrc)&(0xff>>nBitsPos));
712 if ( nBitsCount <= 8 - nBitsPos )
714 nRes >>= ( 8 - nBitsPos - nBitsCount );
716 else
718 pSrc++;
719 nBitsCount -= 8 - nBitsPos;
720 while ( nBitsCount >= 8 )
722 nRes = ( nRes << 8 ) | ((ULONG)*(pSrc++));
723 nBitsCount -= 8;
725 if ( nBitsCount > 0 )
726 nRes = ( nRes << nBitsCount ) | (((ULONG)*pSrc)>>(8-nBitsCount));
729 return nRes;
732 // ---------------------------------------------------------------------------------
734 BOOL TIFFReader::ConvertScanline( ULONG nY )
736 UINT32 nRed, nGreen, nBlue, ns, nx, nVal, nByteCount;
737 BYTE nByteVal;
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 )
749 BYTE nLRed = 0;
750 BYTE nLGreen = 0;
751 BYTE nLBlue = 0;
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 ) );
760 else
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++ )
773 if ( nPlanes < 3 )
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 );
779 else
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++ )
793 if ( nPlanes < 3 )
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 );
799 else
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 )
813 BYTE nSamp[ 4 ];
814 BYTE nSampLast[ 4 ] = { 0, 0, 0, 0 };
815 long nBlack;
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++ )
824 if( nPlanes < 3 )
825 nSampLast[ ns ] = nSampLast[ ns ] + (BYTE) GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample );
826 else
827 nSampLast[ ns ] = nSampLast[ ns ] + (BYTE) GetBits( pMap[ ns ], nx * nBitsPerSample, nBitsPerSample );
828 nSamp[ ns ] = nSampLast[ ns ];
831 else
833 for( ns = 0; ns < 4; ns++ )
835 if( nPlanes < 3 )
836 nSamp[ ns ] = (BYTE) GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample );
837 else
838 nSamp[ ns ]= (BYTE) GetBits( pMap[ ns ], nx * nBitsPerSample, nBitsPerSample );
841 nBlack = nSamp[ 3 ];
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 ];
857 BYTE nShift;
859 switch ( nDstBitsPerPixel )
861 case 8 :
863 BYTE nLast;
864 if ( bByteSwap )
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++;
875 else
877 for ( nx = 0; nx < nImageWidth; nx++ )
879 nLast = *pt++;
880 pAcc->SetPixel( nY, nx, (BYTE)( ( (BYTESWAP((ULONG)nLast ) - nMinSampleValue ) * nMinMax ) ) );
884 else
886 if ( nPredictor == 2 )
888 nLast = *pt++;
889 for ( nx = 0; nx < nImageWidth; nx++ )
891 pAcc->SetPixel( nY, nx, nLast );
892 nLast = nLast + *pt++;
895 else
897 for ( nx = 0; nx < nImageWidth; nx++ )
899 pAcc->SetPixel( nY, nx, (BYTE)( ( (ULONG)*pt++ - nMinSampleValue ) * nMinMax ) );
905 break;
907 case 7 :
908 case 6 :
909 case 5 :
910 case 4 :
911 case 3 :
912 case 2 :
914 for ( nx = 0; nx < nImageWidth; nx++ )
916 nVal = ( GetBits( pt, nx * nBitsPerSample, nBitsPerSample ) - nMinSampleValue ) * nMinMax;
917 pAcc->SetPixel( nY, nx, (BYTE)nVal );
920 break;
922 case 1 :
924 if ( bByteSwap )
926 nx = 0;
927 nByteCount = ( nImageWidth >> 3 ) + 1;
928 while ( --nByteCount )
930 nByteVal = *pt++;
931 pAcc->SetPixel( nY, nx++, nByteVal & 1 );
932 nByteVal >>= 1;
933 pAcc->SetPixel( nY, nx++, nByteVal & 1 );
934 nByteVal >>= 1;
935 pAcc->SetPixel( nY, nx++, nByteVal & 1 );
936 nByteVal >>= 1;
937 pAcc->SetPixel( nY, nx++, nByteVal & 1 );
938 nByteVal >>= 1;
939 pAcc->SetPixel( nY, nx++, nByteVal & 1 );
940 nByteVal >>= 1;
941 pAcc->SetPixel( nY, nx++, nByteVal & 1 );
942 nByteVal >>= 1;
943 pAcc->SetPixel( nY, nx++, nByteVal & 1 );
944 nByteVal >>= 1;
945 pAcc->SetPixel( nY, nx++, nByteVal );
947 if ( nImageWidth & 7 )
949 nByteVal = *pt++;
950 while ( nx < nImageWidth )
952 pAcc->SetPixel( nY, nx++, nByteVal & 1 );
953 nByteVal >>= 1;
957 else
959 nx = 7;
960 nByteCount = ( nImageWidth >> 3 ) + 1;
961 while ( --nByteCount )
963 nByteVal = *pt++;
964 pAcc->SetPixel( nY, nx, nByteVal & 1 );
965 nByteVal >>= 1;
966 pAcc->SetPixel( nY, --nx, nByteVal & 1 );
967 nByteVal >>= 1;
968 pAcc->SetPixel( nY, --nx, nByteVal & 1 );
969 nByteVal >>= 1;
970 pAcc->SetPixel( nY, --nx, nByteVal & 1 );
971 nByteVal >>= 1;
972 pAcc->SetPixel( nY, --nx, nByteVal & 1 );
973 nByteVal >>= 1;
974 pAcc->SetPixel( nY, --nx, nByteVal & 1 );
975 nByteVal >>= 1;
976 pAcc->SetPixel( nY, --nx, nByteVal & 1 );
977 nByteVal >>= 1;
978 pAcc->SetPixel( nY, --nx, nByteVal );
979 nx += 15;
981 if ( nImageWidth & 7 )
983 nx -= 7;
984 nByteVal = *pt++;
985 nShift = 7;
986 while ( nx < nImageWidth )
988 pAcc->SetPixel( nY, nx++, ( nByteVal >> nShift ) & 1);
993 break;
995 default :
996 return FALSE;
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' )
1005 pt++;
1006 for ( nx = 0; nx < nImageWidth; nx++, pt += 2 )
1008 pAcc->SetPixel( nY, nx, (BYTE)( ( (ULONG)*pt - nMinSampleValue ) * nMinMax ) );
1011 else
1012 return FALSE;
1013 return TRUE;
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 )
1029 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;
1037 else
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 ) )
1050 ULONG nRX,nRY;
1051 if (nResolutionUnit==2)
1053 nRX=(ULONG)(fXResolution+0.5);
1054 nRY=(ULONG)(fYResolution+0.5);
1056 else
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;
1072 USHORT nushort;
1074 *pTIFF >> nbyte1;
1075 if ( nbyte1 == 'I' )
1076 pTIFF->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1077 else
1078 pTIFF->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
1080 *pTIFF >> nbyte2 >> nushort;
1081 if ( nbyte1 != nbyte2 || ( nbyte1 != 'I' && nbyte1 != 'M' ) || nushort != 0x002a )
1082 bStatus = FALSE;
1085 // ---------------------------------------------------------------------------------
1087 BOOL TIFFReader::ReadTIFF(SvStream & rTIFF, Graphic & rGraphic )
1089 USHORT i, nNumTags, nTagType;
1090 ULONG nMaxPos;
1091 ULONG nPos;
1092 sal_uInt32 nFirstIfd, nDataLen;
1094 bStatus = TRUE;
1095 nLastPercent = 0;
1097 pTIFF = &rTIFF;
1098 nMaxPos = nOrigPos = pTIFF->Tell();
1099 nOrigNumberFormat = pTIFF->GetNumberFormatInt();
1101 MayCallback( 0 );
1103 // Kopf einlesen:
1104 ReadHeader();
1106 // Ersten IFD einlesen:
1107 *pTIFF >> nFirstIfd;
1109 if( !nFirstIfd || pTIFF->GetError() )
1110 bStatus = FALSE;
1112 if ( bStatus )
1114 sal_uInt32 nOffset = nFirstIfd;
1116 // calculate length of TIFF file
1119 pTIFF->Seek( nOrigPos + nOffset );
1121 if( pTIFF->GetError() )
1123 pTIFF->ResetError();
1124 break;
1126 nMaxPos = Max( pTIFF->Tell(), nMaxPos );
1128 *pTIFF >> nNumTags;
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 );
1138 *pTIFF >> nOffset;
1139 if ( pTIFF->IsEof() )
1140 nOffset = 0;
1142 nMaxPos = Max( pTIFF->Tell(), nMaxPos );
1143 if ( !nOffset )
1144 nMaxPos = Max( pTIFF->Tell(), nMaxPos );
1146 while( nOffset );
1148 for ( UINT32 nNextIfd = nFirstIfd; nNextIfd && bStatus; )
1150 pTIFF->Seek( nOrigPos + nNextIfd );
1152 bByteSwap = FALSE;
1154 nNewSubFile = 0;
1155 nSubFile = 0;
1156 nImageWidth = 0;
1157 nImageLength = 0;
1158 nBitsPerSample = 1; // Defaultwert laut Doku
1159 nCompression = 1;
1160 nPhotometricInterpretation = 0;
1161 nThresholding = 1; // Defaultwert laut Doku
1162 nCellWidth = 1;
1163 nCellLength = 1;
1164 nFillOrder = 1; // Defaultwert laut Doku
1165 nNumStripOffsets = 0;
1166 nOrientation = 1;
1167 nSamplesPerPixel = 1; // Defaultwert laut Doku
1168 nRowsPerStrip = 0xffffffff; // Defaultwert laut Doku
1169 nNumStripByteCounts = 0;
1170 nMinSampleValue = 0; // Defaultwert laut Doku
1171 nMaxSampleValue = 0;
1172 fXResolution = 0.0;
1173 fYResolution = 0.0;
1174 nPlanarConfiguration = 1;
1175 nGroup3Options = 0; // Defaultwert laut Doku
1176 nGroup4Options = 0; // Defaultwert laut Doku
1177 nResolutionUnit = 2; // Defaultwert laut Doku
1178 nPredictor = 1;
1179 nNumColors = 0;
1181 pAcc = NULL;
1182 pColorMap = NULL;
1183 pStripOffsets = NULL;
1184 pStripByteCounts = NULL;
1185 pMap[ 0 ] = pMap[ 1 ] = pMap[ 2 ] = pMap[ 3 ] = NULL;
1187 *pTIFF >> nNumTags;
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 )
1197 *pTIFF >> nOffset;
1198 pTIFF->Seek( nOrigPos + nOffset );
1200 ReadTagData( nTagType, nDataLen );
1201 nPos += 12; pTIFF->Seek( nPos );
1203 if ( pTIFF->GetError() )
1204 bStatus = FALSE;
1206 if ( bStatus == FALSE )
1207 break;
1209 *pTIFF >> nNextIfd;
1210 if ( pTIFF->IsEof() )
1211 nNextIfd = 0;
1213 if ( bStatus )
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;
1224 else
1225 nDstBitsPerPixel = 8;
1227 aBitmap = Bitmap( Size( nImageWidth, nImageLength ), nDstBitsPerPixel );
1228 pAcc = aBitmap.AcquireWriteAccess();
1229 if ( pAcc )
1231 if ( nPlanarConfiguration == 1 )
1232 nPlanes = 1;
1233 else
1234 nPlanes = nSamplesPerPixel;
1236 if ( ( nFillOrder == 2 ) && ( nCompression != 5 ) ) // im LZW Mode werden die bits schon invertiert
1237 bByteSwap = TRUE;
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)
1250 pMap[ j ] = NULL;
1251 bStatus = FALSE;
1252 break;
1256 if ( bStatus && ReadMap( 10, 60 ) )
1258 nMaxPos = Max( pTIFF->Tell(), nMaxPos );
1259 MakePalCol();
1260 nMaxPos = Max( pTIFF->Tell(), nMaxPos );
1262 else
1263 bStatus = FALSE;
1265 if( pAcc )
1267 aBitmap.ReleaseAccess( pAcc );
1268 if ( bStatus )
1270 AnimationBitmap aAnimationBitmap( aBitmap, Point( 0, 0 ), aBitmap.GetSizePixel(),
1271 ANIMATION_TIMEOUT_ON_CLICK, DISPOSE_BACK );
1273 aAnimation.Insert( aAnimationBitmap );
1276 // Aufraeumen:
1277 for ( i = 0; i < 4; i++ )
1278 delete[] pMap[ i ];
1280 delete[] pColorMap;
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();
1296 else
1297 rGraphic = aAnimation; //aBitmap;
1299 return TRUE;
1301 else
1302 return FALSE;
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 )
1313 return FALSE;
1315 return TRUE;
1318 //============================= fuer Windows ==================================
1319 #ifndef GCC
1320 #endif
1322 #ifdef WIN
1324 static HINSTANCE hDLLInst = 0; // HANDLE der DLL
1326 extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR )
1328 #ifndef WNT
1329 if ( nHeap )
1330 UnlockData( 0 );
1331 #endif
1333 hDLLInst = hDLL;
1335 return TRUE;
1338 extern "C" int CALLBACK WEP( int )
1340 return 1;
1343 #endif