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