Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <vcl/graph.hxx>
21 : #include <vcl/bmpacc.hxx>
22 : #include <vcl/animate.hxx>
23 : #include "lzwdecom.hxx"
24 : #include "ccidecom.hxx"
25 :
26 : class FilterConfigItem;
27 :
28 : namespace {
29 :
30 0 : template< typename T > T BYTESWAP(T nByte) {
31 : return ( nByte << 7 ) | ( ( nByte & 2 ) << 5 ) | ( ( nByte & 4 ) << 3 ) |
32 : ( ( nByte & 8 ) << 1 ) | ( ( nByte & 16 ) >> 1 ) |
33 : ( ( nByte & 32 ) >> 3 ) | ( ( nByte & 64 ) >> 5 ) |
34 0 : ( ( nByte & 128 ) >> 7 );
35 : }
36 :
37 : }
38 :
39 : //============================ TIFFReader ==================================
40 :
41 : class TIFFReader
42 : {
43 :
44 : private:
45 :
46 : sal_Bool bStatus; // Whether until now no error occurred
47 : Animation aAnimation;
48 : sal_uLong nLastPercent;
49 :
50 : SvStream* pTIFF; // the TIFF file that should be read
51 : Bitmap aBitmap;
52 : BitmapWriteAccess* pAcc;
53 : sal_uInt16 nDstBitsPerPixel;
54 : AlphaMask* pAlphaMask;
55 : BitmapWriteAccess* pMaskAcc;
56 :
57 : sal_uLong nOrigPos; // start position in pTIFF
58 : sal_uInt16 nOrigNumberFormat; // number format of pTIFF at the beginning
59 :
60 :
61 : sal_uInt16 nDataType;
62 : // Data taken from the TIFF tags:
63 : sal_Bool bByteSwap; // sal_True if bits 0..7 -> 7..0 should get converted ( FILLORDER = 2 );
64 :
65 : sal_uLong nNewSubFile;
66 : sal_uLong nSubFile;
67 : sal_uLong nImageWidth; // picture width in pixels
68 : sal_uLong nImageLength; // picture height in pixels
69 : sal_uLong nBitsPerSample; // bits per pixel per layer
70 : sal_uLong nCompression; // kind of compression
71 : sal_uLong nPhotometricInterpretation;
72 : sal_uLong nThresholding;
73 : sal_uLong nCellWidth;
74 : sal_uLong nCellLength;
75 : sal_uLong nFillOrder;
76 : sal_uLong* pStripOffsets; // field of offsets to the Bitmap-Data-"Strips"
77 : sal_uLong nNumStripOffsets; // size of the field above
78 : sal_uLong nOrientation;
79 : sal_uLong nSamplesPerPixel; // number of layers
80 : sal_uLong nRowsPerStrip; // if it's not compressed: number of rows per Strip
81 : sal_uLong* pStripByteCounts; // if compressed (in a certain way): size of the strips
82 : sal_uLong nNumStripByteCounts; // number of entries in the field above
83 : sal_uLong nMinSampleValue;
84 : sal_uLong nMaxSampleValue;
85 : double fXResolution; // X-resolution or 0.0
86 : double fYResolution; // Y-resolution or 0.0
87 : sal_uLong nPlanarConfiguration;
88 : sal_uLong nGroup3Options;
89 : sal_uLong nGroup4Options;
90 : sal_uLong nResolutionUnit; // unit of fX/YResolution: 1=unknown, 2(default)=inch, 3=cm
91 : sal_uLong nPredictor;
92 : sal_uLong* pColorMap; // color palette
93 : sal_uLong nNumColors; // number of colors within the color palette
94 :
95 : sal_uLong nPlanes; // number of layers within the Tiff file
96 : sal_uLong nStripsPerPlane; // number of Strips per layer
97 : sal_uLong nBytesPerRow; // Bytes per line per Layer in the Tiff file ( uncompressed )
98 : sal_uInt8* pMap[ 4 ]; // temporary Scanline
99 :
100 :
101 : void MayCallback( sal_uLong nPercent );
102 :
103 : sal_uLong DataTypeSize();
104 : sal_uLong ReadIntData();
105 : double ReadDoubleData();
106 :
107 : void ReadHeader();
108 : void ReadTagData( sal_uInt16 nTagType, sal_uInt32 nDataLen );
109 :
110 : sal_Bool ReadMap( sal_uLong nMinPercent, sal_uLong nMaxPercent );
111 : // reads/decompresses the bitmap data and fills pMap
112 :
113 : sal_uLong GetBits( const sal_uInt8 * pSrc, sal_uLong nBitsPos, sal_uLong nBitsCount );
114 : // fetches BitsCount bits from pSrc[..] at the position nBitsPos
115 :
116 : void MakePalCol( void );
117 : // Create the bitmap from the temporary bitmap pMap
118 : // and partly deletes pMap while doing this.
119 :
120 : sal_Bool ConvertScanline( sal_uLong nY );
121 : // converts a Scanline to the Windows-BMP format
122 :
123 : bool HasAlphaChannel() const;
124 : public:
125 :
126 0 : TIFFReader()
127 : : bStatus(false)
128 : , nLastPercent(0)
129 : , pTIFF(NULL)
130 : , pAcc(NULL)
131 : , nDstBitsPerPixel(0)
132 : , pAlphaMask(NULL)
133 : , pMaskAcc(NULL)
134 : , nOrigPos(0)
135 : , nOrigNumberFormat(0)
136 : , nDataType(0)
137 : , bByteSwap(false)
138 : , nNewSubFile(0)
139 : , nSubFile(0)
140 : , nImageWidth(0)
141 : , nImageLength(0)
142 : , nBitsPerSample(1)
143 : , nCompression(1)
144 : , nPhotometricInterpretation(0)
145 : , nThresholding(1)
146 : , nCellWidth(1)
147 : , nCellLength(1)
148 : , nFillOrder(1)
149 : , pStripOffsets(NULL)
150 : , nNumStripOffsets(0)
151 : , nOrientation(1)
152 : , nSamplesPerPixel(1)
153 : , nRowsPerStrip(0xffffffff)
154 : , pStripByteCounts(NULL)
155 : , nNumStripByteCounts(0)
156 : , nMinSampleValue(0)
157 : , nMaxSampleValue(0)
158 : , fXResolution(0.0)
159 : , fYResolution(0.0)
160 : , nPlanarConfiguration(1)
161 : , nGroup3Options(0)
162 : , nGroup4Options(0)
163 : , nResolutionUnit(2)
164 : , nPredictor(0)
165 : , pColorMap(NULL)
166 : , nNumColors(0)
167 : , nPlanes(0)
168 : , nStripsPerPlane(0)
169 0 : , nBytesPerRow(0)
170 : {
171 0 : pMap[ 0 ] = pMap[ 1 ] = pMap[ 2 ] = pMap[ 3 ] = NULL;
172 0 : }
173 :
174 0 : ~TIFFReader()
175 0 : {
176 0 : delete pAlphaMask;
177 0 : }
178 :
179 : bool ReadTIFF( SvStream & rTIFF, Graphic & rGraphic );
180 : };
181 :
182 : //=================== Methods of TIFFReader ==============================
183 :
184 0 : void TIFFReader::MayCallback( sal_uLong /*nPercent*/ )
185 : {
186 0 : }
187 :
188 :
189 :
190 0 : sal_uLong TIFFReader::DataTypeSize()
191 : {
192 : sal_uLong nSize;
193 0 : switch ( nDataType )
194 : {
195 : case 1 : // BYTE
196 : case 2 : // ASCII
197 : case 6 : // SIGNED Byte
198 : case 7 : // UNDEFINED
199 0 : nSize = 1;
200 0 : break;
201 : case 3 : // UINT16
202 : case 8 : // INT16
203 0 : nSize = 2;
204 0 : break;
205 : case 4 : // UINT32
206 : case 9 : // INT32
207 : case 11 : // FLOAT
208 0 : nSize = 4;
209 0 : break;
210 : case 5 : // RATIONAL
211 : case 10 : // SIGNED RATIONAL
212 : case 12 : // DOUBLE
213 0 : nSize = 8;
214 0 : break;
215 : default:
216 0 : pTIFF->SetError(SVSTREAM_FILEFORMAT_ERROR);
217 0 : nSize=1;
218 : }
219 0 : return nSize;
220 : }
221 :
222 :
223 :
224 0 : sal_uLong TIFFReader::ReadIntData()
225 : {
226 : double nDOUBLE;
227 : float nFLOAT;
228 : sal_uInt32 nUINT32a, nUINT32b;
229 : sal_Int32 nINT32;
230 : sal_uInt16 nUINT16;
231 : sal_Int16 nINT16;
232 : sal_uInt8 nBYTE;
233 : char nCHAR;
234 :
235 0 : switch( nDataType )
236 : {
237 : case 0 : //??
238 : case 1 :
239 : case 2 :
240 : case 7 :
241 0 : pTIFF->ReadUChar( nBYTE );
242 0 : nUINT32a = (sal_uLong)nBYTE;
243 0 : break;
244 : case 3 :
245 0 : pTIFF->ReadUInt16( nUINT16 );
246 0 : nUINT32a = (sal_uLong)nUINT16;
247 0 : break;
248 : case 9 :
249 : case 4 :
250 0 : pTIFF->ReadUInt32( nUINT32a );
251 0 : break;
252 : case 5 :
253 0 : pTIFF->ReadUInt32( nUINT32a ).ReadUInt32( nUINT32b );
254 0 : if ( nUINT32b != 0 )
255 0 : nUINT32a /= nUINT32b;
256 0 : break;
257 : case 6 :
258 0 : pTIFF->ReadChar( nCHAR );
259 0 : nUINT32a = (sal_Int32)nCHAR;
260 0 : break;
261 : case 8 :
262 0 : pTIFF->ReadInt16( nINT16 );
263 0 : nUINT32a = (sal_Int32)nINT16;
264 0 : break;
265 : case 10 :
266 0 : pTIFF->ReadUInt32( nUINT32a ).ReadInt32( nINT32 );
267 0 : if ( nINT32 != 0 )
268 0 : nUINT32a /= nINT32;
269 0 : break;
270 : case 11 :
271 0 : pTIFF->ReadFloat( nFLOAT );
272 0 : nUINT32a = (sal_Int32)nFLOAT;
273 0 : break;
274 : case 12 :
275 0 : pTIFF->ReadDouble( nDOUBLE );
276 0 : nUINT32a = (sal_Int32)nDOUBLE;
277 0 : break;
278 : default:
279 0 : pTIFF->ReadUInt32( nUINT32a );
280 0 : break;
281 : }
282 0 : return nUINT32a;
283 : }
284 :
285 :
286 :
287 0 : double TIFFReader::ReadDoubleData()
288 : {
289 : sal_uInt32 nulong;
290 : double nd;
291 :
292 0 : if ( nDataType == 5 )
293 : {
294 0 : pTIFF->ReadUInt32( nulong );
295 0 : nd = (double)nulong;
296 0 : pTIFF->ReadUInt32( nulong );
297 0 : if ( nulong != 0 )
298 0 : nd /= (double)nulong;
299 : }
300 : else
301 0 : nd = (double)ReadIntData();
302 0 : return nd;
303 : }
304 :
305 :
306 :
307 0 : void TIFFReader::ReadTagData( sal_uInt16 nTagType, sal_uInt32 nDataLen)
308 : {
309 0 : if ( bStatus == sal_False )
310 0 : return;
311 :
312 0 : switch ( nTagType )
313 : {
314 : case 0x00fe: // New Sub File
315 0 : nNewSubFile = ReadIntData();
316 : SAL_INFO("filter.tiff","NewSubFile: " << nNewSubFile);
317 0 : break;
318 :
319 : case 0x00ff: // Sub File
320 0 : nSubFile = ReadIntData();
321 : SAL_INFO("filter.tiff","SubFile: " << nSubFile);
322 0 : break;
323 :
324 : case 0x0100: // Image Width
325 0 : nImageWidth = ReadIntData();
326 : SAL_INFO("filter.tiff","ImageWidth: " << nImageWidth);
327 0 : break;
328 :
329 : case 0x0101: // Image Length
330 0 : nImageLength = ReadIntData();
331 : SAL_INFO("filter.tiff","ImageLength: " << nImageLength);
332 0 : break;
333 :
334 : case 0x0102: // Bits Per Sample
335 0 : nBitsPerSample = ReadIntData();
336 : SAL_INFO("filter.tiff","BitsPerSample: " << nBitsPerSample);
337 0 : if ( nBitsPerSample >= 32 ) // 32 bit and larger samples are not supported
338 0 : bStatus = sal_False;
339 0 : break;
340 :
341 : case 0x0103: // Compression
342 0 : nCompression = ReadIntData();
343 : SAL_INFO("filter.tiff","Compression: " << nCompression);
344 0 : break;
345 :
346 : case 0x0106: // Photometric Interpreation
347 0 : nPhotometricInterpretation = ReadIntData();
348 : SAL_INFO("filter.tiff","PhotometricInterpretation: " << nPhotometricInterpretation);
349 0 : break;
350 :
351 : case 0x0107: // Thresholding
352 0 : nThresholding = ReadIntData();
353 : SAL_INFO("filter.tiff","Thresholding: " << nThresholding);
354 0 : break;
355 :
356 : case 0x0108: // Cell Width
357 0 : nCellWidth = ReadIntData();
358 0 : break;
359 :
360 : case 0x0109: // Cell Length
361 0 : nCellLength = ReadIntData();
362 0 : break;
363 :
364 : case 0x010a: // Fill Order
365 0 : nFillOrder = ReadIntData();
366 : SAL_INFO("filter.tiff","FillOrder: " << nFillOrder);
367 0 : break;
368 :
369 : case 0x0111: { // Strip Offset(s)
370 : sal_uLong nOldNumSO, i, * pOldSO;
371 0 : pOldSO = pStripOffsets;
372 0 : if ( pOldSO == NULL )
373 0 : nNumStripOffsets = 0;
374 0 : nOldNumSO = nNumStripOffsets;
375 0 : nDataLen += nOldNumSO;
376 0 : if ( ( nDataLen > nOldNumSO ) && ( nDataLen < SAL_MAX_UINT32 / sizeof( sal_uInt32 ) ) )
377 : {
378 0 : nNumStripOffsets = nDataLen;
379 : try
380 : {
381 0 : pStripOffsets = new sal_uLong[ nNumStripOffsets ];
382 : }
383 0 : catch (const std::bad_alloc &)
384 : {
385 0 : pStripOffsets = NULL;
386 0 : nNumStripOffsets = 0;
387 : }
388 0 : if ( pStripOffsets )
389 : {
390 0 : for ( i = 0; i < nOldNumSO; i++ )
391 0 : pStripOffsets[ i ] = pOldSO[ i ] + nOrigPos;
392 0 : for ( i = nOldNumSO; i < nNumStripOffsets; i++ )
393 0 : pStripOffsets[ i ] = ReadIntData() + nOrigPos;
394 : }
395 0 : delete[] pOldSO;
396 : }
397 : SAL_INFO("filter.tiff","StripOffsets (Number:) " << nDataLen);
398 0 : break;
399 : }
400 : case 0x0112: // Orientation
401 0 : nOrientation = ReadIntData();
402 : SAL_INFO("filter.tiff","Orientation: " << nOrientation);
403 0 : break;
404 :
405 : case 0x0115: // Samples Per Pixel
406 0 : nSamplesPerPixel = ReadIntData();
407 : SAL_INFO("filter.tiff","SamplesPerPixel: " << nSamplesPerPixel);
408 0 : break;
409 :
410 : case 0x0116: // Rows Per Strip
411 0 : nRowsPerStrip = ReadIntData();
412 : SAL_INFO("filter.tiff","RowsPerStrip: " << nRowsPerStrip);
413 0 : break;
414 :
415 : case 0x0117: { // Strip Byte Counts
416 : sal_uLong nOldNumSBC, i, * pOldSBC;
417 0 : pOldSBC = pStripByteCounts;
418 0 : if ( pOldSBC == NULL )
419 0 : nNumStripByteCounts = 0; // to be on the safe side
420 0 : nOldNumSBC = nNumStripByteCounts;
421 0 : nDataLen += nOldNumSBC;
422 0 : if ( ( nDataLen > nOldNumSBC ) && ( nDataLen < SAL_MAX_UINT32 / sizeof( sal_uInt32 ) ) )
423 : {
424 0 : nNumStripByteCounts = nDataLen;
425 : try
426 : {
427 0 : pStripByteCounts = new sal_uLong[ nNumStripByteCounts ];
428 : }
429 0 : catch (const std::bad_alloc &)
430 : {
431 0 : pStripByteCounts = NULL;
432 0 : nNumStripByteCounts = 0;
433 : }
434 0 : if ( pStripByteCounts )
435 : {
436 0 : for ( i = 0; i < nOldNumSBC; i++ )
437 0 : pStripByteCounts[ i ] = pOldSBC[ i ];
438 0 : for ( i = nOldNumSBC; i < nNumStripByteCounts; i++)
439 0 : pStripByteCounts[ i ] = ReadIntData();
440 : }
441 0 : delete[] pOldSBC;
442 : }
443 : SAL_INFO("filter.tiff","StripByteCounts (Number:) " << nDataLen);
444 0 : break;
445 : }
446 : case 0x0118: // Min Sample Value
447 0 : nMinSampleValue = ReadIntData();
448 : SAL_INFO("filter.tiff","MinSampleValue: " << nMinSampleValue);
449 0 : break;
450 :
451 : case 0x0119: // Max Sample Value
452 0 : nMaxSampleValue = ReadIntData();
453 : SAL_INFO("filter.tiff","MaxSampleValue: " << nMaxSampleValue);
454 0 : break;
455 :
456 : case 0x011a: // X Resolution
457 0 : fXResolution = ReadDoubleData();
458 0 : break;
459 :
460 : case 0x011b: // Y Resolution
461 0 : fYResolution = ReadDoubleData();
462 0 : break;
463 :
464 : case 0x011c: // Planar Configuration
465 0 : nPlanarConfiguration = ReadIntData();
466 : SAL_INFO("filter.tiff","PlanarConfiguration: " << nPlanarConfiguration);
467 0 : break;
468 :
469 : case 0x0124: // Group 3 Options
470 0 : nGroup3Options = ReadIntData();
471 : SAL_INFO("filter.tiff","Group3Options: " << nGroup3Options);
472 0 : break;
473 :
474 : case 0x0125: // Group 4 Options
475 0 : nGroup4Options = ReadIntData();
476 : SAL_INFO("filter.tiff","Group4Options: " << nGroup4Options);
477 0 : break;
478 :
479 : case 0x0128: // Resolution Unit
480 0 : nResolutionUnit = ReadIntData();
481 0 : break;
482 :
483 : case 0x013d: // Predictor
484 0 : nPredictor = ReadIntData();
485 : SAL_INFO("filter.tiff","Predictor: " << nPredictor);
486 0 : break;
487 :
488 : case 0x0140: { // Color Map
489 : sal_uInt16 nVal;
490 : sal_uLong i;
491 0 : nNumColors= ( 1UL << nBitsPerSample );
492 0 : if ( nDataType == 3 && nNumColors <= 256)
493 : {
494 0 : pColorMap = new sal_uLong[ 256 ];
495 0 : for ( i = 0; i < nNumColors; i++ )
496 0 : pColorMap[ i ] = 0;
497 0 : for ( i = 0; i < nNumColors; i++ )
498 : {
499 0 : pTIFF->ReadUInt16( nVal );
500 0 : pColorMap[ i ] |= ( ( (sal_uLong)nVal ) << 8 ) & 0x00ff0000;
501 : }
502 0 : for ( i = 0; i < nNumColors; i++ )
503 : {
504 0 : pTIFF->ReadUInt16( nVal );
505 0 : pColorMap[ i ] |= ( (sal_uLong)nVal ) & 0x0000ff00;
506 : }
507 0 : for ( i = 0; i < nNumColors; i++ )
508 : {
509 0 : pTIFF->ReadUInt16( nVal );
510 0 : pColorMap[ i ] |= ( ( (sal_uLong)nVal ) >> 8 ) & 0x000000ff;
511 : }
512 : }
513 : else
514 0 : bStatus = sal_False;
515 : SAL_INFO("filter.tiff","ColorMap (number of colors): " << nNumColors);
516 0 : break;
517 : }
518 :
519 : case 0x0153: { // SampleFormat
520 0 : sal_uLong nSampleFormat = ReadIntData();
521 0 : if ( nSampleFormat == 3 ) // IEEE floating point samples are not supported yet
522 0 : bStatus = sal_False;
523 0 : break;
524 : }
525 : }
526 :
527 0 : if ( pTIFF->GetError() )
528 0 : bStatus = sal_False;
529 : }
530 :
531 :
532 :
533 0 : sal_Bool TIFFReader::ReadMap( sal_uLong nMinPercent, sal_uLong nMaxPercent )
534 : {
535 0 : if ( nCompression == 1 || nCompression == 32771 )
536 : {
537 : sal_uLong ny, np, nStrip, nStripBytesPerRow;
538 :
539 0 : if ( nCompression == 1 )
540 0 : nStripBytesPerRow = nBytesPerRow;
541 : else
542 0 : nStripBytesPerRow = ( nBytesPerRow + 1 ) & 0xfffffffe;
543 0 : for ( ny = 0; ny < nImageLength; ny++ )
544 : {
545 0 : for ( np = 0; np < nPlanes; np++ )
546 : {
547 0 : nStrip = ny / nRowsPerStrip + np * nStripsPerPlane;
548 0 : if ( nStrip >= nNumStripOffsets )
549 0 : return sal_False;
550 0 : pTIFF->Seek( pStripOffsets[ nStrip ] + ( ny % nRowsPerStrip ) * nStripBytesPerRow );
551 0 : pTIFF->Read( pMap[ np ], nBytesPerRow );
552 0 : if ( pTIFF->GetError() )
553 0 : return sal_False;
554 0 : MayCallback( nMinPercent + ( nMaxPercent - nMinPercent ) * ( np * nImageLength + ny) / ( nImageLength * nPlanes ) );
555 : }
556 0 : if ( !ConvertScanline( ny ) )
557 0 : return sal_False;
558 0 : }
559 : }
560 0 : else if ( nCompression == 2 || nCompression == 3 || nCompression == 4 )
561 : {
562 : sal_uLong ny, np, nStrip, nOptions;
563 0 : if ( nCompression == 2 )
564 : {
565 0 : nOptions = CCI_OPTION_BYTEALIGNROW;
566 : }
567 0 : else if ( nCompression == 3 )
568 : {
569 0 : nOptions = CCI_OPTION_EOL;
570 0 : if ( nGroup3Options & 0x00000001 )
571 0 : nOptions |= CCI_OPTION_2D;
572 0 : if ( nGroup3Options & 0x00000004 )
573 0 : nOptions |= CCI_OPTION_BYTEALIGNEOL;
574 0 : if ( nGroup3Options & 0xfffffffa )
575 0 : return sal_False;
576 : }
577 : else
578 : { // nCompression==4
579 0 : nOptions = CCI_OPTION_2D;
580 0 : if ( nGroup4Options & 0xffffffff )
581 0 : return sal_False;
582 : }
583 0 : if ( nFillOrder == 2 )
584 : {
585 0 : nOptions |= CCI_OPTION_INVERSEBITORDER;
586 0 : bByteSwap = sal_False;
587 : }
588 0 : nStrip = 0;
589 0 : if ( nStrip >= nNumStripOffsets )
590 0 : return sal_False;
591 0 : pTIFF->Seek(pStripOffsets[nStrip]);
592 :
593 0 : CCIDecompressor aCCIDecom( nOptions, nImageWidth );
594 :
595 0 : aCCIDecom.StartDecompression( *pTIFF );
596 :
597 0 : for ( ny = 0; ny < nImageLength; ny++ )
598 : {
599 0 : for ( np = 0; np < nPlanes; np++ )
600 : {
601 0 : if ( ny / nRowsPerStrip + np * nStripsPerPlane > nStrip )
602 : {
603 0 : nStrip=ny/nRowsPerStrip+np*nStripsPerPlane;
604 0 : if ( nStrip >= nNumStripOffsets )
605 0 : return sal_False;
606 0 : pTIFF->Seek( pStripOffsets[ nStrip ] );
607 0 : aCCIDecom.StartDecompression( *pTIFF );
608 : }
609 0 : if ( aCCIDecom.DecompressScanline( pMap[ np ], nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes, np + 1 == nPlanes ) == sal_False )
610 0 : return sal_False;
611 0 : if ( pTIFF->GetError() )
612 0 : return sal_False;
613 0 : MayCallback(nMinPercent+(nMaxPercent-nMinPercent)*(np*nImageLength+ny)/(nImageLength*nPlanes));
614 : }
615 0 : if ( !ConvertScanline( ny ) )
616 0 : return sal_False;
617 0 : }
618 : }
619 0 : else if ( nCompression == 5 )
620 : {
621 0 : LZWDecompressor aLZWDecom;
622 : sal_uLong ny, np, nStrip;
623 0 : nStrip=0;
624 0 : if ( nStrip >= nNumStripOffsets )
625 0 : return sal_False;
626 0 : pTIFF->Seek(pStripOffsets[nStrip]);
627 0 : aLZWDecom.StartDecompression(*pTIFF);
628 0 : for ( ny = 0; ny < nImageLength; ny++ )
629 : {
630 0 : for ( np = 0; np < nPlanes; np++ )
631 : {
632 0 : if ( ny / nRowsPerStrip + np * nStripsPerPlane > nStrip )
633 : {
634 0 : nStrip = ny / nRowsPerStrip + np * nStripsPerPlane;
635 0 : if ( nStrip >= nNumStripOffsets )
636 0 : return sal_False;
637 0 : pTIFF->Seek(pStripOffsets[nStrip]);
638 0 : aLZWDecom.StartDecompression(*pTIFF);
639 : }
640 0 : if ( ( aLZWDecom.Decompress( pMap[ np ], nBytesPerRow ) != nBytesPerRow ) || pTIFF->GetError() )
641 0 : return sal_False;
642 0 : MayCallback(nMinPercent+(nMaxPercent-nMinPercent)*(np*nImageLength+ny)/(nImageLength*nPlanes));
643 : }
644 0 : if ( !ConvertScanline( ny ) )
645 0 : return sal_False;
646 0 : }
647 : }
648 0 : else if ( nCompression == 32773 )
649 : {
650 : sal_uLong nStrip,nRecCount,nRowBytesLeft,ny,np,i;
651 : sal_uInt8 * pdst, nRecHeader, nRecData;
652 0 : nStrip = 0;
653 0 : if ( nStrip >= nNumStripOffsets )
654 0 : return sal_False;
655 0 : pTIFF->Seek(pStripOffsets[nStrip]);
656 0 : for ( ny = 0; ny < nImageLength; ny++ )
657 : {
658 0 : for ( np = 0; np < nPlanes; np++ )
659 : {
660 0 : if ( ny / nRowsPerStrip + np * nStripsPerPlane > nStrip )
661 : {
662 0 : nStrip=ny/nRowsPerStrip+np*nStripsPerPlane;
663 0 : if ( nStrip >= nNumStripOffsets )
664 0 : return sal_False;
665 0 : pTIFF->Seek(pStripOffsets[nStrip]);
666 : }
667 0 : nRowBytesLeft = nBytesPerRow;
668 0 : pdst=pMap[ np ];
669 0 : do
670 : {
671 0 : pTIFF->ReadUChar( nRecHeader );
672 0 : if ((nRecHeader&0x80)==0)
673 : {
674 0 : nRecCount=0x00000001+((sal_uLong)nRecHeader);
675 0 : if ( nRecCount > nRowBytesLeft )
676 0 : return sal_False;
677 0 : pTIFF->Read(pdst,nRecCount);
678 0 : pdst+=nRecCount;
679 0 : nRowBytesLeft-=nRecCount;
680 : }
681 0 : else if ( nRecHeader != 0x80 )
682 : {
683 0 : nRecCount = 0x000000101 - ( (sal_uLong)nRecHeader );
684 0 : if ( nRecCount > nRowBytesLeft )
685 : {
686 0 : nRecCount = nRowBytesLeft;
687 :
688 : // bStatus = sal_False;
689 : // return;
690 :
691 : }
692 0 : pTIFF->ReadUChar( nRecData );
693 0 : for ( i = 0; i < nRecCount; i++ )
694 0 : *(pdst++) = nRecData;
695 0 : nRowBytesLeft -= nRecCount;
696 : }
697 : } while ( nRowBytesLeft != 0 );
698 0 : if ( pTIFF->GetError() )
699 0 : return sal_False;
700 0 : MayCallback(nMinPercent+(nMaxPercent-nMinPercent)*(np*nImageLength+ny)/(nImageLength*nPlanes));
701 : }
702 0 : if ( !ConvertScanline( ny ) )
703 0 : return sal_False;
704 : }
705 : }
706 : else
707 0 : return sal_False;
708 0 : return sal_True;
709 : }
710 :
711 0 : sal_uLong TIFFReader::GetBits( const sal_uInt8 * pSrc, sal_uLong nBitsPos, sal_uLong nBitsCount )
712 : {
713 : sal_uLong nRes;
714 0 : if ( bByteSwap )
715 : {
716 0 : pSrc += ( nBitsPos >> 3 );
717 0 : nBitsPos &= 7;
718 0 : sal_uInt8 nDat = *pSrc;
719 0 : nRes = (sal_uLong)( BYTESWAP( nDat ) & ( 0xff >> nBitsPos ) );
720 :
721 0 : if ( nBitsCount <= 8 - nBitsPos )
722 : {
723 0 : nRes >>= ( 8 - nBitsPos - nBitsCount );
724 : }
725 : else
726 : {
727 0 : pSrc++;
728 0 : nBitsCount -= 8 - nBitsPos;
729 0 : while ( nBitsCount >= 8 )
730 : {
731 0 : nDat = *(pSrc++);
732 0 : nRes = ( nRes << 8 ) | ((sal_uLong)BYTESWAP( nDat ) );
733 0 : nBitsCount -= 8;
734 : }
735 0 : if ( nBitsCount > 0 )
736 : {
737 0 : nDat = *pSrc;
738 0 : nRes = ( nRes << nBitsCount ) | (((sal_uLong)BYTESWAP(nDat))>>(8-nBitsCount));
739 : }
740 : }
741 : }
742 : else
743 : {
744 0 : pSrc += ( nBitsPos >> 3 );
745 0 : nBitsPos &= 7;
746 0 : nRes = (sal_uLong)((*pSrc)&(0xff>>nBitsPos));
747 0 : if ( nBitsCount <= 8 - nBitsPos )
748 : {
749 0 : nRes >>= ( 8 - nBitsPos - nBitsCount );
750 : }
751 : else
752 : {
753 0 : pSrc++;
754 0 : nBitsCount -= 8 - nBitsPos;
755 0 : while ( nBitsCount >= 8 )
756 : {
757 0 : nRes = ( nRes << 8 ) | ((sal_uLong)*(pSrc++));
758 0 : nBitsCount -= 8;
759 : }
760 0 : if ( nBitsCount > 0 )
761 0 : nRes = ( nRes << nBitsCount ) | (((sal_uLong)*pSrc)>>(8-nBitsCount));
762 : }
763 : }
764 0 : return nRes;
765 : }
766 :
767 :
768 :
769 0 : sal_Bool TIFFReader::ConvertScanline( sal_uLong nY )
770 : {
771 : sal_uInt32 nRed, nGreen, nBlue, ns, nx, nVal, nByteCount;
772 : sal_uInt8 nByteVal;
773 :
774 0 : if ( nDstBitsPerPixel == 24 )
775 : {
776 0 : if ( nBitsPerSample == 8 && nSamplesPerPixel >= 3 &&
777 0 : nPlanes == 1 && nPhotometricInterpretation == 2 )
778 : {
779 0 : sal_uInt8* pt = pMap[ 0 ];
780 :
781 : // are the values being saved as difference?
782 0 : if ( 2 == nPredictor )
783 : {
784 0 : sal_uInt8 nLRed = 0;
785 0 : sal_uInt8 nLGreen = 0;
786 0 : sal_uInt8 nLBlue = 0;
787 0 : sal_uInt8 nLAlpha = 0;
788 0 : for ( nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel )
789 : {
790 0 : nLRed = nLRed + pt[ 0 ];
791 0 : nLGreen = nLGreen + pt[ 1 ];
792 0 : nLBlue = nLBlue + pt[ 2 ];
793 0 : pAcc->SetPixel( nY, nx, Color( nLRed, nLGreen, nLBlue ) );
794 0 : if (nSamplesPerPixel >= 4 && pMaskAcc)
795 : {
796 0 : nLAlpha = nLAlpha + pt[ 3 ];
797 0 : pMaskAcc->SetPixel( nY, nx, BitmapColor(~nLAlpha) );
798 : }
799 : }
800 : }
801 : else
802 : {
803 0 : for ( nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel )
804 : {
805 0 : pAcc->SetPixel( nY, nx, Color( pt[0], pt[1], pt[2] ) );
806 0 : if (nSamplesPerPixel >= 4 && pMaskAcc)
807 : {
808 0 : sal_uInt8 nAlpha = pt[3];
809 0 : pMaskAcc->SetPixel( nY, nx, BitmapColor(~nAlpha) );
810 : }
811 : }
812 0 : }
813 : }
814 0 : else if ( nPhotometricInterpretation == 2 && nSamplesPerPixel >= 3 )
815 : {
816 0 : if ( nMaxSampleValue > nMinSampleValue )
817 : {
818 0 : sal_uLong nMinMax = nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue );
819 0 : for ( nx = 0; nx < nImageWidth; nx++ )
820 : {
821 0 : if ( nPlanes < 3 )
822 : {
823 0 : nRed = GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + 0 ) * nBitsPerSample, nBitsPerSample );
824 0 : nGreen = GetBits( pMap[ 1 ], ( nx * nSamplesPerPixel + 1 ) * nBitsPerSample, nBitsPerSample );
825 0 : nBlue = GetBits( pMap[ 2 ], ( nx * nSamplesPerPixel + 2 ) * nBitsPerSample, nBitsPerSample );
826 : }
827 : else
828 : {
829 0 : nRed = GetBits( pMap[ 0 ], nx * nBitsPerSample, nBitsPerSample );
830 0 : nGreen = GetBits( pMap[ 1 ], nx * nBitsPerSample, nBitsPerSample );
831 0 : nBlue = GetBits( pMap[ 2 ], nx * nBitsPerSample, nBitsPerSample );
832 : }
833 0 : pAcc->SetPixel( nY, nx, Color( (sal_uInt8)( nRed - nMinMax ), (sal_uInt8)( nGreen - nMinMax ), (sal_uInt8)(nBlue - nMinMax) ) );
834 : }
835 0 : }
836 : }
837 0 : else if ( nPhotometricInterpretation == 5 && nSamplesPerPixel == 3 )
838 : {
839 0 : if ( nMaxSampleValue > nMinSampleValue )
840 : {
841 0 : sal_uLong nMinMax = nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue );
842 0 : for ( nx = 0; nx < nImageWidth; nx++ )
843 : {
844 0 : if ( nPlanes < 3 )
845 : {
846 0 : nRed = GetBits( pMap[ 0 ],( nx * nSamplesPerPixel + 0 ) * nBitsPerSample, nBitsPerSample );
847 0 : nGreen = GetBits( pMap[ 0 ],( nx * nSamplesPerPixel + 1 ) * nBitsPerSample, nBitsPerSample );
848 0 : nBlue = GetBits( pMap[ 0 ],( nx * nSamplesPerPixel + 2 ) * nBitsPerSample, nBitsPerSample );
849 : }
850 : else
851 : {
852 0 : nRed = GetBits( pMap[ 0 ], nx * nBitsPerSample, nBitsPerSample );
853 0 : nGreen = GetBits( pMap[ 1 ], nx * nBitsPerSample, nBitsPerSample );
854 0 : nBlue = GetBits( pMap[ 2 ], nx * nBitsPerSample, nBitsPerSample );
855 : }
856 0 : nRed = 255 - (sal_uInt8)( nRed - nMinMax );
857 0 : nGreen = 255 - (sal_uInt8)( nGreen - nMinMax );
858 0 : nBlue = 255 - (sal_uInt8)( nBlue - nMinMax );
859 0 : pAcc->SetPixel( nY, nx, Color( (sal_uInt8) nRed, (sal_uInt8) nGreen, (sal_uInt8) nBlue ) );
860 : }
861 0 : }
862 : }
863 0 : else if( nPhotometricInterpretation == 5 && nSamplesPerPixel == 4 )
864 : {
865 0 : if ( nMaxSampleValue > nMinSampleValue )
866 : {
867 : sal_uInt8 nSamp[ 4 ];
868 0 : sal_uInt8 nSampLast[ 4 ] = { 0, 0, 0, 0 };
869 : long nBlack;
870 :
871 0 : for( nx = 0; nx < nImageWidth; nx++ )
872 : {
873 : // are the values being saved as difference?
874 0 : if( 2 == nPredictor )
875 : {
876 0 : for( ns = 0; ns < 4; ns++ )
877 : {
878 0 : if( nPlanes < 3 )
879 0 : nSampLast[ ns ] = nSampLast[ ns ] + (sal_uInt8) GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample );
880 : else
881 0 : nSampLast[ ns ] = nSampLast[ ns ] + (sal_uInt8) GetBits( pMap[ ns ], nx * nBitsPerSample, nBitsPerSample );
882 0 : nSamp[ ns ] = nSampLast[ ns ];
883 : }
884 : }
885 : else
886 : {
887 0 : for( ns = 0; ns < 4; ns++ )
888 : {
889 0 : if( nPlanes < 3 )
890 0 : nSamp[ ns ] = (sal_uInt8) GetBits( pMap[ 0 ], ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample );
891 : else
892 0 : nSamp[ ns ]= (sal_uInt8) GetBits( pMap[ ns ], nx * nBitsPerSample, nBitsPerSample );
893 : }
894 : }
895 0 : nBlack = nSamp[ 3 ];
896 0 : nRed = (sal_uInt8) std::max( 0L, 255L - ( ( (long) nSamp[ 0 ] + nBlack - ( ( (long) nMinSampleValue ) << 1 ) ) *
897 0 : 255L/(long)(nMaxSampleValue-nMinSampleValue) ) );
898 0 : nGreen = (sal_uInt8) std::max( 0L, 255L - ( ( (long) nSamp[ 1 ] + nBlack - ( ( (long) nMinSampleValue ) << 1 ) ) *
899 0 : 255L/(long)(nMaxSampleValue-nMinSampleValue) ) );
900 0 : nBlue = (sal_uInt8) std::max( 0L, 255L - ( ( (long) nSamp[ 2 ] + nBlack - ( ( (long) nMinSampleValue ) << 1 ) ) *
901 0 : 255L/(long)(nMaxSampleValue-nMinSampleValue) ) );
902 0 : pAcc->SetPixel( nY, nx, Color ( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
903 : }
904 : }
905 : }
906 : }
907 0 : else if ( nSamplesPerPixel == 1 && ( nPhotometricInterpretation <= 1 || nPhotometricInterpretation == 3 ) )
908 : {
909 0 : if ( nMaxSampleValue > nMinSampleValue )
910 : {
911 0 : sal_uLong nMinMax = ( ( 1 << nDstBitsPerPixel ) - 1 ) / ( nMaxSampleValue - nMinSampleValue );
912 0 : sal_uInt8* pt = pMap[ 0 ];
913 : sal_uInt8 nShift;
914 :
915 0 : switch ( nDstBitsPerPixel )
916 : {
917 : case 8 :
918 : {
919 : sal_uInt8 nLast;
920 0 : if ( bByteSwap )
921 : {
922 0 : if ( nPredictor == 2 )
923 : {
924 0 : nLast = BYTESWAP( (sal_uInt8)*pt++ );
925 0 : for ( nx = 0; nx < nImageWidth; nx++ )
926 : {
927 0 : pAcc->SetPixelIndex( nY, nx, nLast );
928 0 : nLast = nLast + *pt++;
929 : }
930 : }
931 : else
932 : {
933 0 : for ( nx = 0; nx < nImageWidth; nx++ )
934 : {
935 0 : nLast = *pt++;
936 0 : pAcc->SetPixelIndex( nY, nx, static_cast<sal_uInt8>( (BYTESWAP((sal_uLong)nLast) - nMinSampleValue) * nMinMax ) );
937 : }
938 : }
939 : }
940 : else
941 : {
942 0 : if ( nPredictor == 2 )
943 : {
944 0 : nLast = *pt++;
945 0 : for ( nx = 0; nx < nImageWidth; nx++ )
946 : {
947 0 : pAcc->SetPixelIndex( nY, nx, nLast );
948 0 : nLast = nLast + *pt++;
949 : }
950 : }
951 : else
952 : {
953 0 : for ( nx = 0; nx < nImageWidth; nx++ )
954 : {
955 0 : pAcc->SetPixelIndex( nY, nx, static_cast<sal_uInt8>( ((sal_uLong)*pt++ - nMinSampleValue) * nMinMax ) );
956 :
957 : }
958 : }
959 : }
960 : }
961 0 : break;
962 :
963 : case 7 :
964 : case 6 :
965 : case 5 :
966 : case 4 :
967 : case 3 :
968 : case 2 :
969 : {
970 0 : for ( nx = 0; nx < nImageWidth; nx++ )
971 : {
972 0 : nVal = ( GetBits( pt, nx * nBitsPerSample, nBitsPerSample ) - nMinSampleValue ) * nMinMax;
973 0 : pAcc->SetPixelIndex( nY, nx, static_cast<sal_uInt8>(nVal));
974 : }
975 : }
976 0 : break;
977 :
978 : case 1 :
979 : {
980 0 : if ( bByteSwap )
981 : {
982 0 : nx = 0;
983 0 : nByteCount = ( nImageWidth >> 3 ) + 1;
984 0 : while ( --nByteCount )
985 : {
986 0 : nByteVal = *pt++;
987 0 : pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
988 0 : nByteVal >>= 1;
989 0 : pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
990 0 : nByteVal >>= 1;
991 0 : pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
992 0 : nByteVal >>= 1;
993 0 : pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
994 0 : nByteVal >>= 1;
995 0 : pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
996 0 : nByteVal >>= 1;
997 0 : pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
998 0 : nByteVal >>= 1;
999 0 : pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
1000 0 : nByteVal >>= 1;
1001 0 : pAcc->SetPixelIndex( nY, nx++, nByteVal );
1002 : }
1003 0 : if ( nImageWidth & 7 )
1004 : {
1005 0 : nByteVal = *pt++;
1006 0 : while ( nx < nImageWidth )
1007 : {
1008 0 : pAcc->SetPixelIndex( nY, nx++, nByteVal & 1 );
1009 0 : nByteVal >>= 1;
1010 : }
1011 : }
1012 : }
1013 : else
1014 : {
1015 0 : nx = 7;
1016 0 : nByteCount = ( nImageWidth >> 3 ) + 1;
1017 0 : while ( --nByteCount )
1018 : {
1019 0 : nByteVal = *pt++;
1020 0 : pAcc->SetPixelIndex( nY, nx, nByteVal & 1 );
1021 0 : nByteVal >>= 1;
1022 0 : pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
1023 0 : nByteVal >>= 1;
1024 0 : pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
1025 0 : nByteVal >>= 1;
1026 0 : pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
1027 0 : nByteVal >>= 1;
1028 0 : pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
1029 0 : nByteVal >>= 1;
1030 0 : pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
1031 0 : nByteVal >>= 1;
1032 0 : pAcc->SetPixelIndex( nY, --nx, nByteVal & 1 );
1033 0 : nByteVal >>= 1;
1034 0 : pAcc->SetPixelIndex( nY, --nx, nByteVal );
1035 0 : nx += 15;
1036 : }
1037 0 : if ( nImageWidth & 7 )
1038 : {
1039 0 : nx -= 7;
1040 0 : nByteVal = *pt++;
1041 0 : nShift = 7;
1042 0 : while ( nx < nImageWidth )
1043 : {
1044 0 : pAcc->SetPixelIndex( nY, nx++, ( nByteVal >> nShift ) & 1);
1045 : }
1046 : }
1047 : }
1048 : }
1049 0 : break;
1050 :
1051 : default :
1052 0 : return sal_False;
1053 : }
1054 0 : }
1055 : }
1056 0 : else if ( ( nSamplesPerPixel == 2 ) && ( nBitsPerSample == 8 ) &&
1057 0 : ( nPlanarConfiguration == 1 ) && ( pColorMap == 0 ) ) // grayscale
1058 : {
1059 0 : if ( nMaxSampleValue > nMinSampleValue )
1060 : {
1061 0 : sal_uLong nMinMax = ( ( 1 << 8 /*nDstBitsPerPixel*/ ) - 1 ) / ( nMaxSampleValue - nMinSampleValue );
1062 0 : sal_uInt8* pt = pMap[ 0 ];
1063 0 : for ( nx = 0; nx < nImageWidth; nx++, pt += 2 )
1064 : {
1065 0 : pAcc->SetPixelIndex( nY, nx, static_cast<sal_uInt8>( ((sal_uLong)*pt - nMinSampleValue) * nMinMax) );
1066 : }
1067 0 : }
1068 : }
1069 : else
1070 0 : return sal_False;
1071 0 : return sal_True;
1072 : }
1073 :
1074 :
1075 :
1076 0 : void TIFFReader::MakePalCol( void )
1077 : {
1078 0 : if ( nDstBitsPerPixel <= 8 )
1079 : {
1080 : sal_uLong i, nVal, n0RGB;
1081 0 : if ( pColorMap == NULL )
1082 0 : pColorMap = new sal_uLong[ 256 ];
1083 0 : if ( nPhotometricInterpretation <= 1 )
1084 : {
1085 0 : nNumColors = 1UL << nBitsPerSample;
1086 0 : if ( nNumColors > 256 )
1087 0 : nNumColors = 256;
1088 0 : pAcc->SetPaletteEntryCount( (sal_uInt16)nNumColors );
1089 0 : for ( i = 0; i < nNumColors; i++ )
1090 : {
1091 0 : nVal = ( i * 255 / ( nNumColors - 1 ) ) & 0xff;
1092 0 : n0RGB = nVal | ( nVal << 8 ) | ( nVal << 16 );
1093 0 : if ( nPhotometricInterpretation == 1 )
1094 0 : pColorMap[ i ] = n0RGB;
1095 : else
1096 0 : pColorMap[ nNumColors - i - 1 ] = n0RGB;
1097 : }
1098 : }
1099 0 : for ( i = 0; i < nNumColors; i++ )
1100 : {
1101 0 : pAcc->SetPaletteColor( (sal_uInt16)i, BitmapColor( (sal_uInt8)( pColorMap[ i ] >> 16 ),
1102 0 : (sal_uInt8)( pColorMap[ i ] >> 8 ), (sal_uInt8)pColorMap[ i ] ) );
1103 : }
1104 : }
1105 :
1106 0 : if ( fXResolution > 1.0 && fYResolution > 1.0 && ( nResolutionUnit == 2 || nResolutionUnit == 3 ) )
1107 : {
1108 : sal_uLong nRX,nRY;
1109 0 : if (nResolutionUnit==2)
1110 : {
1111 0 : nRX=(sal_uLong)(fXResolution+0.5);
1112 0 : nRY=(sal_uLong)(fYResolution+0.5);
1113 : }
1114 : else
1115 : {
1116 0 : nRX=(sal_uLong)(fXResolution*2.54+0.5);
1117 0 : nRY=(sal_uLong)(fYResolution*2.54+0.5);
1118 : }
1119 0 : MapMode aMapMode(MAP_INCH,Point(0,0),Fraction(1,nRX),Fraction(1,nRY));
1120 0 : aBitmap.SetPrefMapMode(aMapMode);
1121 0 : aBitmap.SetPrefSize(Size(nImageWidth,nImageLength));
1122 : }
1123 0 : }
1124 :
1125 :
1126 :
1127 0 : void TIFFReader::ReadHeader()
1128 : {
1129 : sal_uInt8 nbyte1, nbyte2;
1130 : sal_uInt16 nushort;
1131 :
1132 0 : pTIFF->ReadUChar( nbyte1 );
1133 0 : if ( nbyte1 == 'I' )
1134 0 : pTIFF->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1135 : else
1136 0 : pTIFF->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
1137 :
1138 0 : pTIFF->ReadUChar( nbyte2 ).ReadUInt16( nushort );
1139 0 : if ( nbyte1 != nbyte2 || ( nbyte1 != 'I' && nbyte1 != 'M' ) || nushort != 0x002a )
1140 0 : bStatus = sal_False;
1141 0 : }
1142 :
1143 0 : bool TIFFReader::HasAlphaChannel() const
1144 : {
1145 : /*There are undoubtedly more variants we could support, but keep it simple for now*/
1146 : return (
1147 0 : nDstBitsPerPixel == 24 &&
1148 0 : nBitsPerSample == 8 &&
1149 0 : nSamplesPerPixel >= 4 &&
1150 0 : nPlanes == 1 &&
1151 0 : nPhotometricInterpretation == 2
1152 0 : );
1153 : }
1154 :
1155 :
1156 :
1157 0 : bool TIFFReader::ReadTIFF(SvStream & rTIFF, Graphic & rGraphic )
1158 : {
1159 : sal_uInt16 i, nNumTags, nTagType;
1160 : sal_uInt64 nMaxPos;
1161 : sal_uLong nPos;
1162 : sal_uInt32 nFirstIfd, nDataLen;
1163 :
1164 0 : bStatus = sal_True;
1165 0 : nLastPercent = 0;
1166 :
1167 0 : pTIFF = &rTIFF;
1168 0 : nMaxPos = nOrigPos = pTIFF->Tell();
1169 0 : nOrigNumberFormat = pTIFF->GetNumberFormatInt();
1170 :
1171 0 : MayCallback( 0 );
1172 :
1173 : // read header:
1174 0 : ReadHeader();
1175 :
1176 : // read first IFD:
1177 0 : pTIFF->ReadUInt32( nFirstIfd );
1178 :
1179 0 : if( !nFirstIfd || pTIFF->GetError() )
1180 0 : bStatus = sal_False;
1181 :
1182 0 : if ( bStatus )
1183 : {
1184 0 : sal_uInt32 nOffset = nFirstIfd;
1185 :
1186 : // calculate length of TIFF file
1187 0 : do
1188 : {
1189 0 : pTIFF->Seek( nOrigPos + nOffset );
1190 :
1191 0 : if( pTIFF->GetError() )
1192 : {
1193 0 : pTIFF->ResetError();
1194 0 : break;
1195 : };
1196 0 : nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1197 :
1198 0 : pTIFF->ReadUInt16( nNumTags );
1199 :
1200 : // loop through tags:
1201 0 : for( i = 0; i < nNumTags; i++ )
1202 : {
1203 0 : pTIFF->ReadUInt16( nTagType ).ReadUInt16( nDataType ).ReadUInt32( nDataLen ).ReadUInt32( nOffset );
1204 :
1205 0 : if( DataTypeSize() * nDataLen > 4 )
1206 0 : nMaxPos = std::max( (sal_uInt64) nOrigPos + nOffset + DataTypeSize() * nDataLen, nMaxPos );
1207 : }
1208 0 : pTIFF->ReadUInt32( nOffset );
1209 0 : if ( pTIFF->IsEof() )
1210 0 : nOffset = 0;
1211 :
1212 0 : nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1213 0 : if ( !nOffset )
1214 0 : nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1215 : }
1216 : while( nOffset );
1217 :
1218 0 : for ( sal_uInt32 nNextIfd = nFirstIfd; nNextIfd && bStatus; )
1219 : {
1220 0 : pTIFF->Seek( nOrigPos + nNextIfd );
1221 : {
1222 0 : bByteSwap = sal_False;
1223 :
1224 0 : nNewSubFile = 0;
1225 0 : nSubFile = 0;
1226 0 : nImageWidth = 0;
1227 0 : nImageLength = 0;
1228 0 : nBitsPerSample = 1; // default value according to the documentation
1229 0 : nCompression = 1;
1230 0 : nPhotometricInterpretation = 0;
1231 0 : nThresholding = 1; // default value according to the documentation
1232 0 : nCellWidth = 1;
1233 0 : nCellLength = 1;
1234 0 : nFillOrder = 1; // default value according to the documentation
1235 0 : nNumStripOffsets = 0;
1236 0 : nOrientation = 1;
1237 0 : nSamplesPerPixel = 1; // default value according to the documentation
1238 0 : nRowsPerStrip = 0xffffffff; // default value according to the documentation
1239 0 : nNumStripByteCounts = 0;
1240 0 : nMinSampleValue = 0; // default value according to the documentation
1241 0 : nMaxSampleValue = 0;
1242 0 : fXResolution = 0.0;
1243 0 : fYResolution = 0.0;
1244 0 : nPlanarConfiguration = 1;
1245 0 : nGroup3Options = 0; // default value according to the documentation
1246 0 : nGroup4Options = 0; // default value according to the documentation
1247 0 : nResolutionUnit = 2; // default value according to the documentation
1248 0 : nPredictor = 1;
1249 0 : nNumColors = 0;
1250 :
1251 0 : pAcc = NULL;
1252 0 : pColorMap = NULL;
1253 0 : pStripOffsets = NULL;
1254 0 : pStripByteCounts = NULL;
1255 0 : pMap[ 0 ] = pMap[ 1 ] = pMap[ 2 ] = pMap[ 3 ] = NULL;
1256 :
1257 0 : pTIFF->ReadUInt16( nNumTags );
1258 0 : nPos = pTIFF->Tell();
1259 :
1260 : // Schleife ueber Tags:
1261 0 : for( i = 0; i < nNumTags; i++ )
1262 : {
1263 0 : pTIFF->ReadUInt16( nTagType ).ReadUInt16( nDataType ).ReadUInt32( nDataLen );
1264 :
1265 0 : if( DataTypeSize() * nDataLen > 4 )
1266 : {
1267 0 : pTIFF->ReadUInt32( nOffset );
1268 0 : pTIFF->Seek( nOrigPos + nOffset );
1269 : }
1270 0 : ReadTagData( nTagType, nDataLen );
1271 0 : nPos += 12; pTIFF->Seek( nPos );
1272 :
1273 0 : if ( pTIFF->GetError() )
1274 0 : bStatus = sal_False;
1275 :
1276 0 : if ( bStatus == sal_False )
1277 0 : break;
1278 : }
1279 0 : pTIFF->ReadUInt32( nNextIfd );
1280 0 : if ( pTIFF->IsEof() )
1281 0 : nNextIfd = 0;
1282 : }
1283 0 : if ( !nBitsPerSample || ( nBitsPerSample > 32 ) )
1284 0 : bStatus = sal_False;
1285 0 : if ( bStatus )
1286 : {
1287 0 : if ( nMaxSampleValue == 0 )
1288 : {
1289 0 : if ( nBitsPerSample == 32 ) // sj: i93300, compiler bug, 1 << 32 gives 1 one 32bit windows platforms,
1290 0 : nMaxSampleValue = 0xffffffff; // (up from 80286 only the lower 5 bits are used when shifting a 32bit register)
1291 : else
1292 0 : nMaxSampleValue = ( 1 << nBitsPerSample ) - 1;
1293 : }
1294 0 : if ( nPhotometricInterpretation == 2 || nPhotometricInterpretation == 5 || nPhotometricInterpretation == 6 )
1295 0 : nDstBitsPerPixel = 24;
1296 0 : else if ( nBitsPerSample*nSamplesPerPixel <= 1 )
1297 0 : nDstBitsPerPixel = 1;
1298 0 : else if ( nBitsPerSample*nSamplesPerPixel <= 4 )
1299 0 : nDstBitsPerPixel = 4;
1300 : else
1301 0 : nDstBitsPerPixel = 8;
1302 :
1303 0 : Size aTargetSize( nImageWidth, nImageLength );
1304 0 : aBitmap = Bitmap( aTargetSize, nDstBitsPerPixel );
1305 0 : pAcc = aBitmap.AcquireWriteAccess();
1306 0 : if ( pAcc )
1307 : {
1308 0 : if ( nPlanarConfiguration == 1 )
1309 0 : nPlanes = 1;
1310 : else
1311 0 : nPlanes = nSamplesPerPixel;
1312 :
1313 0 : if ( ( nFillOrder == 2 ) && ( nCompression != 5 ) ) // in the LZW mode bits are already being inverted
1314 0 : bByteSwap = sal_True;
1315 :
1316 0 : nStripsPerPlane = ( nImageLength - 1 ) / nRowsPerStrip + 1;
1317 0 : nBytesPerRow = ( nImageWidth * nSamplesPerPixel / nPlanes * nBitsPerSample + 7 ) >> 3;
1318 :
1319 0 : for ( sal_uLong j = 0; j < 4; j++ )
1320 : {
1321 : try
1322 : {
1323 0 : pMap[ j ] = new sal_uInt8[ nBytesPerRow ];
1324 : }
1325 0 : catch (const std::bad_alloc &)
1326 : {
1327 0 : pMap[ j ] = NULL;
1328 0 : bStatus = sal_False;
1329 0 : break;
1330 : }
1331 : }
1332 :
1333 0 : if (HasAlphaChannel())
1334 : {
1335 0 : pAlphaMask = new AlphaMask( aTargetSize );
1336 0 : pMaskAcc = pAlphaMask->AcquireWriteAccess();
1337 : }
1338 :
1339 0 : if ( bStatus && ReadMap( 10, 60 ) )
1340 : {
1341 0 : nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1342 0 : MakePalCol();
1343 0 : nMaxPos = std::max( pTIFF->Tell(), nMaxPos );
1344 : }
1345 : else
1346 0 : bStatus = sal_False;
1347 :
1348 0 : if( pAcc )
1349 : {
1350 0 : aBitmap.ReleaseAccess( pAcc );
1351 :
1352 0 : if ( pMaskAcc )
1353 : {
1354 0 : if ( pAlphaMask )
1355 0 : pAlphaMask->ReleaseAccess( pMaskAcc );
1356 0 : pMaskAcc = NULL;
1357 : }
1358 :
1359 0 : if ( bStatus )
1360 : {
1361 0 : BitmapEx aImage;
1362 :
1363 0 : if (pAlphaMask)
1364 0 : aImage = BitmapEx( aBitmap, *pAlphaMask );
1365 : else
1366 0 : aImage = aBitmap;
1367 :
1368 0 : AnimationBitmap aAnimationBitmap( aImage, Point( 0, 0 ), aBitmap.GetSizePixel(),
1369 0 : ANIMATION_TIMEOUT_ON_CLICK, DISPOSE_BACK );
1370 :
1371 0 : aAnimation.Insert( aAnimationBitmap );
1372 : }
1373 : }
1374 : // Aufraeumen:
1375 0 : for ( i = 0; i < 4; i++ )
1376 0 : delete[] pMap[ i ];
1377 :
1378 0 : delete[] pColorMap;
1379 0 : delete[] pStripOffsets;
1380 0 : delete[] pStripByteCounts;
1381 : }
1382 : }
1383 : }
1384 : }
1385 :
1386 : // seek to end of TIFF if succeeded
1387 0 : pTIFF->SetNumberFormatInt( nOrigNumberFormat );
1388 0 : pTIFF->Seek( bStatus ? nMaxPos : nOrigPos );
1389 :
1390 0 : if ( aAnimation.Count() )
1391 : {
1392 0 : if ( aAnimation.Count() == 1 )
1393 0 : rGraphic = aAnimation.GetBitmapEx();
1394 : else
1395 0 : rGraphic = aAnimation; //aBitmap;
1396 :
1397 0 : return true;
1398 : }
1399 : else
1400 0 : return false;
1401 : }
1402 :
1403 :
1404 : //================== GraphicImport - the exported function ================
1405 :
1406 : // this needs to be kept in sync with
1407 : // ImpFilterLibCacheEntry::GetImportFunction() from
1408 : // vcl/source/filter/graphicfilter.cxx
1409 : #if defined(DISABLE_DYNLOADING)
1410 : #define GraphicImport itiGraphicImport
1411 : #endif
1412 :
1413 : extern "C" SAL_DLLPUBLIC_EXPORT bool SAL_CALL
1414 0 : GraphicImport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* )
1415 : {
1416 0 : TIFFReader aTIFFReader;
1417 :
1418 0 : return aTIFFReader.ReadTIFF( rStream, rGraphic );
1419 : }
1420 :
1421 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|