bump product version to 4.1.6.2
[LibreOffice.git] / filter / source / graphicfilter / itiff / itiff.cxx
blob71bd7e027e816d9ab6dc86bed60fa8e41c939990
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <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();
30 namespace {
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 ==================================
43 class TIFFReader
46 private:
48 sal_Bool bStatus; // Whether until now no error occurred
49 Animation aAnimation;
50 sal_uLong nLastPercent;
52 SvStream* pTIFF; // the TIFF file that should be read
53 Bitmap aBitmap;
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
63 sal_uInt16 nDataType;
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();
109 void ReadHeader();
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;
126 public:
128 TIFFReader() : pAlphaMask(0), pMaskAcc(0) {}
129 ~TIFFReader()
131 delete pAlphaMask;
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()
147 sal_uLong nSize;
148 switch ( nDataType )
150 case 1 : // BYTE
151 case 2 : // ACSII
152 case 6 : // SIGNED Byte
153 case 7 : // UNDEFINED
154 nSize = 1;
155 break;
156 case 3 : // UINT16
157 case 8 : // INT16
158 nSize = 2;
159 break;
160 case 4 : // UINT32
161 case 9 : // INT32
162 case 11 : // FLOAT
163 nSize = 4;
164 break;
165 case 5 : // RATIONAL
166 case 10 : // SIGNED RATINAL
167 case 12 : // DOUBLE
168 nSize = 8;
169 break;
170 default:
171 pTIFF->SetError(SVSTREAM_FILEFORMAT_ERROR);
172 nSize=1;
174 return nSize;
177 // ---------------------------------------------------------------------------------
179 sal_uLong TIFFReader::ReadIntData()
181 double nDOUBLE;
182 float nFLOAT;
183 sal_uInt32 nUINT32a, nUINT32b;
184 sal_Int32 nINT32;
185 sal_uInt16 nUINT16;
186 sal_Int16 nINT16;
187 sal_uInt8 nBYTE;
188 char nCHAR;
190 switch( nDataType )
192 case 0 : //??
193 case 1 :
194 case 2 :
195 case 7 :
196 *pTIFF >> nBYTE;
197 nUINT32a = (sal_uLong)nBYTE;
198 break;
199 case 3 :
200 *pTIFF >> nUINT16;
201 nUINT32a = (sal_uLong)nUINT16;
202 break;
203 case 9 :
204 case 4 :
205 *pTIFF >> nUINT32a;
206 break;
207 case 5 :
208 *pTIFF >> nUINT32a >> nUINT32b;
209 if ( nUINT32b != 0 )
210 nUINT32a /= nUINT32b;
211 break;
212 case 6 :
213 *pTIFF >> nCHAR;
214 nUINT32a = (sal_Int32)nCHAR;
215 break;
216 case 8 :
217 *pTIFF >> nINT16;
218 nUINT32a = (sal_Int32)nINT16;
219 break;
220 case 10 :
221 *pTIFF >> nUINT32a >> nINT32;
222 if ( nINT32 != 0 )
223 nUINT32a /= nINT32;
224 break;
225 case 11 :
226 *pTIFF >> nFLOAT;
227 nUINT32a = (sal_Int32)nFLOAT;
228 break;
229 case 12 :
230 *pTIFF >> nDOUBLE;
231 nUINT32a = (sal_Int32)nDOUBLE;
232 break;
233 default:
234 *pTIFF >> nUINT32a;
235 break;
237 return nUINT32a;
240 // ---------------------------------------------------------------------------------
242 double TIFFReader::ReadDoubleData()
244 sal_uInt32 nulong;
245 double nd;
247 if ( nDataType == 5 )
249 *pTIFF >> nulong;
250 nd = (double)nulong;
251 *pTIFF >> nulong;
252 if ( nulong != 0 )
253 nd /= (double)nulong;
255 else
256 nd = (double)ReadIntData();
257 return nd;
260 // ---------------------------------------------------------------------------------
262 void TIFFReader::ReadTagData( sal_uInt16 nTagType, sal_uInt32 nDataLen)
264 if ( bStatus == sal_False )
265 return;
267 switch ( nTagType )
269 case 0x00fe: // New Sub File
270 nNewSubFile = ReadIntData();
271 OOODEBUG("NewSubFile",nNewSubFile);
272 break;
274 case 0x00ff: // Sub File
275 nSubFile = ReadIntData();
276 OOODEBUG("SubFile",nSubFile);
277 break;
279 case 0x0100: // Image Width
280 nImageWidth = ReadIntData();
281 OOODEBUG("ImageWidth",nImageWidth);
282 break;
284 case 0x0101: // Image Length
285 nImageLength = ReadIntData();
286 OOODEBUG("ImageLength",nImageLength);
287 break;
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
293 bStatus = sal_False;
294 break;
296 case 0x0103: // Compression
297 nCompression = ReadIntData();
298 OOODEBUG("Compression",nCompression);
299 break;
301 case 0x0106: // Photometric Interpreation
302 nPhotometricInterpretation = ReadIntData();
303 OOODEBUG("PhotometricInterpretation",nPhotometricInterpretation);
304 break;
306 case 0x0107: // Thresholding
307 nThresholding = ReadIntData();
308 OOODEBUG("Thresholding",nThresholding);
309 break;
311 case 0x0108: // Cell Width
312 nCellWidth = ReadIntData();
313 break;
315 case 0x0109: // Cell Length
316 nCellLength = ReadIntData();
317 break;
319 case 0x010a: // Fill Order
320 nFillOrder = ReadIntData();
321 OOODEBUG("FillOrder",nFillOrder);
322 break;
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;
343 if ( pStripOffsets )
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;
350 delete[] pOldSO;
352 OOODEBUG("StripOffsets (Anzahl:)",nDataLen);
353 break;
355 case 0x0112: // Orientation
356 nOrientation = ReadIntData();
357 OOODEBUG("Orientation",nOrientation);
358 break;
360 case 0x0115: // Samples Per Pixel
361 nSamplesPerPixel = ReadIntData();
362 OOODEBUG("SamplesPerPixel",nSamplesPerPixel);
363 break;
365 case 0x0116: // Rows Per Strip
366 nRowsPerStrip = ReadIntData();
367 OOODEBUG("RowsPerStrip",nRowsPerStrip);
368 break;
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();
396 delete[] pOldSBC;
398 OOODEBUG("StripByteCounts (Anzahl:)",nDataLen);
399 break;
401 case 0x0118: // Min Sample Value
402 nMinSampleValue = ReadIntData();
403 OOODEBUG("MinSampleValue",nMinSampleValue);
404 break;
406 case 0x0119: // Max Sample Value
407 nMaxSampleValue = ReadIntData();
408 OOODEBUG("MaxSampleValue",nMaxSampleValue);
409 break;
411 case 0x011a: // X Resolution
412 fXResolution = ReadDoubleData();
413 break;
415 case 0x011b: // Y Resolution
416 fYResolution = ReadDoubleData();
417 break;
419 case 0x011c: // Planar Configuration
420 nPlanarConfiguration = ReadIntData();
421 OOODEBUG("PlanarConfiguration",nPlanarConfiguration);
422 break;
424 case 0x0124: // Group 3 Options
425 nGroup3Options = ReadIntData();
426 OOODEBUG("Group3Options",nGroup3Options);
427 break;
429 case 0x0125: // Group 4 Options
430 nGroup4Options = ReadIntData();
431 OOODEBUG("Group4Options",nGroup4Options);
432 break;
434 case 0x0128: // Resolution Unit
435 nResolutionUnit = ReadIntData();
436 break;
438 case 0x013d: // Predictor
439 nPredictor = ReadIntData();
440 OOODEBUG("Predictor",nPredictor);
441 break;
443 case 0x0140: { // Color Map
444 sal_uInt16 nVal;
445 sal_uLong i;
446 nNumColors= ( 1UL << nBitsPerSample );
447 if ( nDataType == 3 && nNumColors <= 256)
449 pColorMap = new sal_uLong[ 256 ];
450 for ( i = 0; i < nNumColors; i++ )
451 pColorMap[ i ] = 0;
452 for ( i = 0; i < nNumColors; i++ )
454 *pTIFF >> nVal;
455 pColorMap[ i ] |= ( ( (sal_uLong)nVal ) << 8 ) & 0x00ff0000;
457 for ( i = 0; i < nNumColors; i++ )
459 *pTIFF >> nVal;
460 pColorMap[ i ] |= ( (sal_uLong)nVal ) & 0x0000ff00;
462 for ( i = 0; i < nNumColors; i++ )
464 *pTIFF >> nVal;
465 pColorMap[ i ] |= ( ( (sal_uLong)nVal ) >> 8 ) & 0x000000ff;
468 else
469 bStatus = sal_False;
470 OOODEBUG("ColorMap (Anzahl Farben:)", nNumColors);
471 break;
474 case 0x0153: { // SampleFormat
475 sal_uLong nSampleFormat = ReadIntData();
476 if ( nSampleFormat == 3 ) // IEEE floating point samples are not supported yet
477 bStatus = sal_False;
478 break;
482 if ( pTIFF->GetError() )
483 bStatus = sal_False;
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;
496 else
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 )
504 return sal_False;
505 pTIFF->Seek( pStripOffsets[ nStrip ] + ( ny % nRowsPerStrip ) * nStripBytesPerRow );
506 pTIFF->Read( pMap[ np ], nBytesPerRow );
507 if ( pTIFF->GetError() )
508 return sal_False;
509 MayCallback( nMinPercent + ( nMaxPercent - nMinPercent ) * ( np * nImageLength + ny) / ( nImageLength * nPlanes ) );
511 if ( !ConvertScanline( ny ) )
512 return sal_False;
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 )
530 return sal_False;
532 else
533 { // nCompression==4
534 nOptions = CCI_OPTION_2D;
535 if ( nGroup4Options & 0xffffffff )
536 return sal_False;
538 if ( nFillOrder == 2 )
540 nOptions |= CCI_OPTION_INVERSEBITORDER;
541 bByteSwap = sal_False;
543 nStrip = 0;
544 if ( nStrip >= nNumStripOffsets )
545 return sal_False;
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 )
560 return sal_False;
561 pTIFF->Seek( pStripOffsets[ nStrip ] );
562 aCCIDecom.StartDecompression( *pTIFF );
564 if ( aCCIDecom.DecompressScanline( pMap[ np ], nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes ) == sal_False )
565 return sal_False;
566 if ( pTIFF->GetError() )
567 return sal_False;
568 MayCallback(nMinPercent+(nMaxPercent-nMinPercent)*(np*nImageLength+ny)/(nImageLength*nPlanes));
570 if ( !ConvertScanline( ny ) )
571 return sal_False;
574 else if ( nCompression == 5 )
576 LZWDecompressor aLZWDecom;
577 sal_uLong ny, np, nStrip;
578 nStrip=0;
579 if ( nStrip >= nNumStripOffsets )
580 return sal_False;
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 )
591 return sal_False;
592 pTIFF->Seek(pStripOffsets[nStrip]);
593 aLZWDecom.StartDecompression(*pTIFF);
595 if ( ( aLZWDecom.Decompress( pMap[ np ], nBytesPerRow ) != nBytesPerRow ) || pTIFF->GetError() )
596 return sal_False;
597 MayCallback(nMinPercent+(nMaxPercent-nMinPercent)*(np*nImageLength+ny)/(nImageLength*nPlanes));
599 if ( !ConvertScanline( ny ) )
600 return sal_False;
603 else if ( nCompression == 32773 )
605 sal_uLong nStrip,nRecCount,nRowBytesLeft,ny,np,i;
606 sal_uInt8 * pdst, nRecHeader, nRecData;
607 nStrip = 0;
608 if ( nStrip >= nNumStripOffsets )
609 return sal_False;
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 )
619 return sal_False;
620 pTIFF->Seek(pStripOffsets[nStrip]);
622 nRowBytesLeft = nBytesPerRow;
623 pdst=pMap[ np ];
626 *pTIFF >> nRecHeader;
627 if ((nRecHeader&0x80)==0)
629 nRecCount=0x00000001+((sal_uLong)nRecHeader);
630 if ( nRecCount > nRowBytesLeft )
631 return sal_False;
632 pTIFF->Read(pdst,nRecCount);
633 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;
644 // return;
647 *pTIFF >> nRecData;
648 for ( i = 0; i < nRecCount; i++ )
649 *(pdst++) = nRecData;
650 nRowBytesLeft -= nRecCount;
652 } while ( nRowBytesLeft != 0 );
653 if ( pTIFF->GetError() )
654 return sal_False;
655 MayCallback(nMinPercent+(nMaxPercent-nMinPercent)*(np*nImageLength+ny)/(nImageLength*nPlanes));
657 if ( !ConvertScanline( ny ) )
658 return sal_False;
661 else
662 return sal_False;
663 return sal_True;
666 sal_uLong TIFFReader::GetBits( const sal_uInt8 * pSrc, sal_uLong nBitsPos, sal_uLong nBitsCount )
668 sal_uLong nRes;
669 if ( bByteSwap )
671 pSrc += ( nBitsPos >> 3 );
672 nBitsPos &= 7;
673 sal_uInt8 nDat = *pSrc;
674 nRes = (sal_uLong)( BYTESWAP( nDat ) & ( 0xff >> nBitsPos ) );
676 if ( nBitsCount <= 8 - nBitsPos )
678 nRes >>= ( 8 - nBitsPos - nBitsCount );
680 else
682 pSrc++;
683 nBitsCount -= 8 - nBitsPos;
684 while ( nBitsCount >= 8 )
686 nDat = *(pSrc++);
687 nRes = ( nRes << 8 ) | ((sal_uLong)BYTESWAP( nDat ) );
688 nBitsCount -= 8;
690 if ( nBitsCount > 0 )
692 nDat = *pSrc;
693 nRes = ( nRes << nBitsCount ) | (((sal_uLong)BYTESWAP(nDat))>>(8-nBitsCount));
697 else
699 pSrc += ( nBitsPos >> 3 );
700 nBitsPos &= 7;
701 nRes = (sal_uLong)((*pSrc)&(0xff>>nBitsPos));
702 if ( nBitsCount <= 8 - nBitsPos )
704 nRes >>= ( 8 - nBitsPos - nBitsCount );
706 else
708 pSrc++;
709 nBitsCount -= 8 - nBitsPos;
710 while ( nBitsCount >= 8 )
712 nRes = ( nRes << 8 ) | ((sal_uLong)*(pSrc++));
713 nBitsCount -= 8;
715 if ( nBitsCount > 0 )
716 nRes = ( nRes << nBitsCount ) | (((sal_uLong)*pSrc)>>(8-nBitsCount));
719 return nRes;
722 // ---------------------------------------------------------------------------------
724 sal_Bool TIFFReader::ConvertScanline( sal_uLong nY )
726 sal_uInt32 nRed, nGreen, nBlue, ns, nx, nVal, nByteCount;
727 sal_uInt8 nByteVal;
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 )
739 sal_uInt8 nLRed = 0;
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) );
756 else
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++ )
776 if ( nPlanes < 3 )
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 );
782 else
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++ )
799 if ( nPlanes < 3 )
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 );
805 else
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 };
824 long nBlack;
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++ )
833 if( nPlanes < 3 )
834 nSampLast[ ns ] = nSampLast[ ns ] + (sal_uInt8) GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample );
835 else
836 nSampLast[ ns ] = nSampLast[ ns ] + (sal_uInt8) GetBits( pMap[ ns ], nx * nBitsPerSample, nBitsPerSample );
837 nSamp[ ns ] = nSampLast[ ns ];
840 else
842 for( ns = 0; ns < 4; ns++ )
844 if( nPlanes < 3 )
845 nSamp[ ns ] = (sal_uInt8) GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample );
846 else
847 nSamp[ ns ]= (sal_uInt8) GetBits( pMap[ ns ], nx * nBitsPerSample, nBitsPerSample );
850 nBlack = nSamp[ 3 ];
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 ];
868 sal_uInt8 nShift;
870 switch ( nDstBitsPerPixel )
872 case 8 :
874 sal_uInt8 nLast;
875 if ( bByteSwap )
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++;
886 else
888 for ( nx = 0; nx < nImageWidth; nx++ )
890 nLast = *pt++;
891 pAcc->SetPixelIndex( nY, nx, static_cast<sal_uInt8>( (BYTESWAP((sal_uLong)nLast) - nMinSampleValue) * nMinMax ) );
895 else
897 if ( nPredictor == 2 )
899 nLast = *pt++;
900 for ( nx = 0; nx < nImageWidth; nx++ )
902 pAcc->SetPixelIndex( nY, nx, nLast );
903 nLast = nLast + *pt++;
906 else
908 for ( nx = 0; nx < nImageWidth; nx++ )
910 pAcc->SetPixelIndex( nY, nx, static_cast<sal_uInt8>( ((sal_uLong)*pt++ - nMinSampleValue) * nMinMax ) );
916 break;
918 case 7 :
919 case 6 :
920 case 5 :
921 case 4 :
922 case 3 :
923 case 2 :
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));
931 break;
933 case 1 :
935 if ( bByteSwap )
937 nx = 0;
938 nByteCount = ( nImageWidth >> 3 ) + 1;
939 while ( --nByteCount )
941 nByteVal = *pt++;
942 pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
943 nByteVal >>= 1;
944 pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
945 nByteVal >>= 1;
946 pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
947 nByteVal >>= 1;
948 pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
949 nByteVal >>= 1;
950 pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
951 nByteVal >>= 1;
952 pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
953 nByteVal >>= 1;
954 pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
955 nByteVal >>= 1;
956 pAcc->SetPixelIndex( nY, nx++, nByteVal );
958 if ( nImageWidth & 7 )
960 nByteVal = *pt++;
961 while ( nx < nImageWidth )
963 pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
964 nByteVal >>= 1;
968 else
970 nx = 7;
971 nByteCount = ( nImageWidth >> 3 ) + 1;
972 while ( --nByteCount )
974 nByteVal = *pt++;
975 pAcc->SetPixelIndex( nY, nx, nByteVal & 1 );
976 nByteVal >>= 1;
977 pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
978 nByteVal >>= 1;
979 pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
980 nByteVal >>= 1;
981 pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
982 nByteVal >>= 1;
983 pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
984 nByteVal >>= 1;
985 pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
986 nByteVal >>= 1;
987 pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
988 nByteVal >>= 1;
989 pAcc->SetPixelIndex( nY, --nx, nByteVal );
990 nx += 15;
992 if ( nImageWidth & 7 )
994 nx -= 7;
995 nByteVal = *pt++;
996 nShift = 7;
997 while ( nx < nImageWidth )
999 pAcc->SetPixelIndex( nY, nx++, ( nByteVal >> nShift ) & 1);
1004 break;
1006 default :
1007 return sal_False;
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) );
1024 else
1025 return sal_False;
1026 return sal_True;
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 )
1042 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;
1050 else
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 ) )
1063 sal_uLong nRX,nRY;
1064 if (nResolutionUnit==2)
1066 nRX=(sal_uLong)(fXResolution+0.5);
1067 nRY=(sal_uLong)(fYResolution+0.5);
1069 else
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;
1085 sal_uInt16 nushort;
1087 *pTIFF >> nbyte1;
1088 if ( nbyte1 == 'I' )
1089 pTIFF->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1090 else
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*/
1101 return (
1102 nDstBitsPerPixel == 24 &&
1103 nBitsPerSample == 8 &&
1104 nSamplesPerPixel >= 4 &&
1105 nPlanes == 1 &&
1106 nPhotometricInterpretation == 2
1110 // ---------------------------------------------------------------------------------
1112 sal_Bool TIFFReader::ReadTIFF(SvStream & rTIFF, Graphic & rGraphic )
1114 sal_uInt16 i, nNumTags, nTagType;
1115 sal_uLong nMaxPos;
1116 sal_uLong nPos;
1117 sal_uInt32 nFirstIfd, nDataLen;
1119 bStatus = sal_True;
1120 nLastPercent = 0;
1122 pTIFF = &rTIFF;
1123 nMaxPos = nOrigPos = pTIFF->Tell();
1124 nOrigNumberFormat = pTIFF->GetNumberFormatInt();
1126 MayCallback( 0 );
1128 // read header:
1129 ReadHeader();
1131 // read first IFD:
1132 *pTIFF >> nFirstIfd;
1134 if( !nFirstIfd || pTIFF->GetError() )
1135 bStatus = sal_False;
1137 if ( bStatus )
1139 sal_uInt32 nOffset = nFirstIfd;
1141 // calculate length of TIFF file
1144 pTIFF->Seek( nOrigPos + nOffset );
1146 if( pTIFF->GetError() )
1148 pTIFF->ResetError();
1149 break;
1151 nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1153 *pTIFF >> nNumTags;
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 );
1163 *pTIFF >> nOffset;
1164 if ( pTIFF->IsEof() )
1165 nOffset = 0;
1167 nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1168 if ( !nOffset )
1169 nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1171 while( nOffset );
1173 for ( sal_uInt32 nNextIfd = nFirstIfd; nNextIfd && bStatus; )
1175 pTIFF->Seek( nOrigPos + nNextIfd );
1177 bByteSwap = sal_False;
1179 nNewSubFile = 0;
1180 nSubFile = 0;
1181 nImageWidth = 0;
1182 nImageLength = 0;
1183 nBitsPerSample = 1; // default value according to the documentation
1184 nCompression = 1;
1185 nPhotometricInterpretation = 0;
1186 nThresholding = 1; // default value according to the documentation
1187 nCellWidth = 1;
1188 nCellLength = 1;
1189 nFillOrder = 1; // default value according to the documentation
1190 nNumStripOffsets = 0;
1191 nOrientation = 1;
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;
1197 fXResolution = 0.0;
1198 fYResolution = 0.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
1203 nPredictor = 1;
1204 nNumColors = 0;
1206 pAcc = NULL;
1207 pColorMap = NULL;
1208 pStripOffsets = NULL;
1209 pStripByteCounts = NULL;
1210 pMap[ 0 ] = pMap[ 1 ] = pMap[ 2 ] = pMap[ 3 ] = NULL;
1212 *pTIFF >> nNumTags;
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 )
1222 *pTIFF >> nOffset;
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 )
1232 break;
1234 *pTIFF >> nNextIfd;
1235 if ( pTIFF->IsEof() )
1236 nNextIfd = 0;
1238 if ( !nBitsPerSample || ( nBitsPerSample > 32 ) )
1239 bStatus = sal_False;
1240 if ( bStatus )
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)
1246 else
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;
1255 else
1256 nDstBitsPerPixel = 8;
1258 Size aTargetSize( nImageWidth, nImageLength );
1259 aBitmap = Bitmap( aTargetSize, nDstBitsPerPixel );
1260 pAcc = aBitmap.AcquireWriteAccess();
1261 if ( pAcc )
1263 if ( nPlanarConfiguration == 1 )
1264 nPlanes = 1;
1265 else
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 &)
1282 pMap[ j ] = NULL;
1283 bStatus = sal_False;
1284 break;
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 );
1297 MakePalCol();
1298 nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1300 else
1301 bStatus = sal_False;
1303 if( pAcc )
1305 aBitmap.ReleaseAccess( pAcc );
1307 if ( pMaskAcc )
1309 if ( pAlphaMask )
1310 pAlphaMask->ReleaseAccess( pMaskAcc );
1311 pMaskAcc = NULL;
1314 if ( bStatus )
1316 BitmapEx aImage;
1318 if (pAlphaMask)
1319 aImage = BitmapEx( aBitmap, *pAlphaMask );
1320 else
1321 aImage = aBitmap;
1323 AnimationBitmap aAnimationBitmap( aImage, Point( 0, 0 ), aBitmap.GetSizePixel(),
1324 ANIMATION_TIMEOUT_ON_CLICK, DISPOSE_BACK );
1326 aAnimation.Insert( aAnimationBitmap );
1329 // Aufraeumen:
1330 for ( i = 0; i < 4; i++ )
1331 delete[] pMap[ i ];
1333 delete[] pColorMap;
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();
1349 else
1350 rGraphic = aAnimation; //aBitmap;
1352 return sal_True;
1354 else
1355 return sal_False;
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
1366 #endif
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 )
1374 return sal_False;
1376 return sal_True;
1379 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */