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 : :
30 : : #include <vcl/graph.hxx>
31 : : #include <vcl/bmpacc.hxx>
32 : : #include <svtools/fltcall.hxx>
33 : :
34 : : //============================ TGAReader ==================================
35 : :
36 : : struct TGAFileHeader
37 : : {
38 : : sal_uInt8 nImageIDLength;
39 : : sal_uInt8 nColorMapType;
40 : : sal_uInt8 nImageType;
41 : : sal_uInt16 nColorMapFirstEntryIndex;
42 : : sal_uInt16 nColorMapLength;
43 : : sal_uInt8 nColorMapEntrySize;
44 : : sal_uInt16 nColorMapXOrigin;
45 : : sal_uInt16 nColorMapYOrigin;
46 : : sal_uInt16 nImageWidth;
47 : : sal_uInt16 nImageHeight;
48 : : sal_uInt8 nPixelDepth;
49 : : sal_uInt8 nImageDescriptor;
50 : : };
51 : :
52 : : #define SizeOfTGAFileFooter 26
53 : :
54 : : struct TGAFileFooter
55 : : {
56 : : sal_uInt32 nExtensionFileOffset;
57 : : sal_uInt32 nDeveloperDirectoryOffset;
58 : : sal_uInt32 nSignature[4];
59 : : sal_uInt8 nPadByte;
60 : : sal_uInt8 nStringTerminator;
61 : : };
62 : :
63 : : #define SizeOfTGAExtension 495
64 : :
65 : : struct TGAExtension
66 : : {
67 : : sal_uInt16 nExtensionSize;
68 : : char sAuthorName[41];
69 : : char sAuthorComment[324];
70 : : char sDateTimeStamp[12];
71 : : char sJobNameID[41];
72 : : sal_uInt16 nJobTime[3];
73 : : char sSoftwareID[41];
74 : : sal_uInt16 nSoftwareVersionNumber;
75 : : sal_uInt8 nSoftwareVersionLetter;
76 : : sal_uInt32 nKeyColor;
77 : : sal_uInt16 nPixelAspectRatioNumerator;
78 : : sal_uInt16 nPixelAspectRatioDeNumerator;
79 : : sal_uInt16 nGammaValueNumerator;
80 : : sal_uInt16 nGammaValueDeNumerator;
81 : : sal_uInt32 nColorCorrectionOffset;
82 : : sal_uInt32 nPostageStampOffset;
83 : : sal_uInt32 nScanLineOffset;
84 : : sal_uInt8 nAttributesType;
85 : : };
86 : :
87 : : class TGAReader {
88 : :
89 : : private:
90 : :
91 : : SvStream& m_rTGA;
92 : :
93 : : BitmapWriteAccess* mpAcc;
94 : : TGAFileHeader* mpFileHeader;
95 : : TGAFileFooter* mpFileFooter;
96 : : TGAExtension* mpExtension;
97 : : sal_uInt32* mpColorMap;
98 : :
99 : : sal_Bool mbStatus;
100 : :
101 : : sal_uLong mnTGAVersion; // Enhanced TGA is defined as Version 2.0
102 : : sal_uInt16 mnDestBitDepth;
103 : : sal_Bool mbIndexing; // sal_True if source contains indexing color values
104 : : sal_Bool mbEncoding; // sal_True if source is compressed
105 : :
106 : : sal_Bool ImplReadHeader();
107 : : sal_Bool ImplReadPalette();
108 : : sal_Bool ImplReadBody();
109 : :
110 : : public:
111 : : TGAReader(SvStream &rTGA);
112 : : ~TGAReader();
113 : : sal_Bool ReadTGA(Graphic &rGraphic);
114 : : };
115 : :
116 : : //=================== Methoden von TGAReader ==============================
117 : :
118 : 6 : TGAReader::TGAReader(SvStream &rTGA)
119 : : : m_rTGA(rTGA)
120 : : , mpAcc(NULL)
121 : : , mpFileHeader(NULL)
122 : : , mpFileFooter(NULL)
123 : : , mpExtension(NULL)
124 : : , mpColorMap(NULL)
125 : : , mbStatus(sal_True)
126 : : , mnTGAVersion(1)
127 : : , mbIndexing(sal_False)
128 : 6 : , mbEncoding(sal_False)
129 : : {
130 : 6 : }
131 : :
132 : 6 : TGAReader::~TGAReader()
133 : : {
134 [ - + ]: 6 : delete[] mpColorMap;
135 : 6 : delete mpFileHeader;
136 : 6 : delete mpExtension;
137 : 6 : delete mpFileFooter;
138 : 6 : }
139 : :
140 : : // -------------------------------------------------------------------------------------------
141 : :
142 : 6 : sal_Bool TGAReader::ReadTGA(Graphic & rGraphic)
143 : : {
144 [ - + ]: 6 : if ( m_rTGA.GetError() )
145 : 0 : return sal_False;
146 : :
147 : 6 : m_rTGA.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
148 : :
149 : : // Kopf einlesen:
150 : :
151 [ + - ]: 6 : if ( !m_rTGA.GetError() )
152 : : {
153 : 6 : mbStatus = ImplReadHeader();
154 [ + - ]: 6 : if ( mbStatus )
155 : : {
156 [ + - ]: 6 : Bitmap aBitmap;
157 : :
158 [ + - ][ + - ]: 6 : aBitmap = Bitmap( Size( mpFileHeader->nImageWidth, mpFileHeader->nImageHeight ), mnDestBitDepth );
[ + - ]
159 [ + - ]: 6 : mpAcc = aBitmap.AcquireWriteAccess();
160 [ + - ]: 6 : if ( mpAcc )
161 : : {
162 [ - + ]: 6 : if ( mbIndexing )
163 [ # # ]: 0 : mbStatus = ImplReadPalette();
164 [ + - ]: 6 : if ( mbStatus )
165 [ + - ]: 6 : mbStatus = ImplReadBody();
166 : : }
167 : : else
168 : 0 : mbStatus = sal_False;
169 : :
170 [ + - ]: 6 : if ( mpAcc )
171 [ + - ]: 6 : aBitmap.ReleaseAccess ( mpAcc), mpAcc = NULL;
172 : :
173 [ + - ]: 6 : if ( mbStatus )
174 [ + - ][ + - ]: 6 : rGraphic = aBitmap;
[ + - ][ + - ]
175 : : }
176 : : }
177 : 6 : return mbStatus;
178 : : }
179 : :
180 : : // -------------------------------------------------------------------------------------------
181 : :
182 : 6 : sal_Bool TGAReader::ImplReadHeader()
183 : : {
184 : 6 : mpFileHeader = new TGAFileHeader;
185 [ - + ]: 6 : if ( mpFileHeader == NULL )
186 : 0 : return sal_False;
187 : :
188 : 6 : m_rTGA >> mpFileHeader->nImageIDLength >> mpFileHeader->nColorMapType >> mpFileHeader->nImageType >>
189 : 6 : mpFileHeader->nColorMapFirstEntryIndex >> mpFileHeader->nColorMapLength >> mpFileHeader->nColorMapEntrySize >>
190 : 6 : mpFileHeader->nColorMapXOrigin >> mpFileHeader->nColorMapYOrigin >> mpFileHeader->nImageWidth >>
191 : 6 : mpFileHeader->nImageHeight >> mpFileHeader->nPixelDepth >> mpFileHeader->nImageDescriptor;
192 : :
193 [ - + ]: 6 : if ( mpFileHeader->nColorMapType > 1 )
194 : 0 : return sal_False;
195 [ - + ]: 6 : if ( mpFileHeader->nColorMapType == 1 )
196 : 0 : mbIndexing = sal_True;
197 : :
198 : : // first we want to get the version
199 : 6 : mpFileFooter = new TGAFileFooter; // read the TGA-File-Footer to determine whether
200 [ + - ]: 6 : if ( mpFileFooter ) // we got an old TGA format or the new one
201 : : {
202 : 6 : sal_uLong nCurStreamPos = m_rTGA.Tell();
203 : 6 : m_rTGA.Seek( STREAM_SEEK_TO_END );
204 : 6 : sal_uLong nTemp = m_rTGA.Tell();
205 : 6 : m_rTGA.Seek( nTemp - SizeOfTGAFileFooter );
206 : :
207 : 6 : m_rTGA >> mpFileFooter->nExtensionFileOffset >> mpFileFooter->nDeveloperDirectoryOffset >>
208 : 6 : mpFileFooter->nSignature[0] >> mpFileFooter->nSignature[1] >> mpFileFooter->nSignature[2] >>
209 : 6 : mpFileFooter->nSignature[3] >> mpFileFooter->nPadByte >> mpFileFooter->nStringTerminator;
210 : :
211 : : // check for sal_True, VISI, ON-X, FILE in the signatures
212 [ # # ][ # # ]: 6 : if ( mpFileFooter->nSignature[ 0 ] == (('T'<<24)|('R'<<16)|('U'<<8)|'E') &&
[ # # ][ - + ]
213 : 0 : mpFileFooter->nSignature[ 1 ] == (('V'<<24)|('I'<<16)|('S'<<8)|'I') &&
214 : 0 : mpFileFooter->nSignature[ 2 ] == (('O'<<24)|('N'<<16)|('-'<<8)|'X') &&
215 : 0 : mpFileFooter->nSignature[ 3 ] == (('F'<<24)|('I'<<16)|('L'<<8)|'E') )
216 : : {
217 : 0 : mpExtension = new TGAExtension;
218 [ # # ]: 0 : if ( mpExtension )
219 : : {
220 : 0 : m_rTGA.Seek( mpFileFooter->nExtensionFileOffset );
221 : 0 : m_rTGA >> mpExtension->nExtensionSize;
222 [ # # ]: 0 : if ( mpExtension->nExtensionSize >= SizeOfTGAExtension )
223 : : {
224 : 0 : mnTGAVersion = 2;
225 : :
226 : 0 : m_rTGA.Read( mpExtension->sAuthorName, 41 );
227 : 0 : m_rTGA.Read( mpExtension->sAuthorComment, 324 );
228 : 0 : m_rTGA.Read( mpExtension->sDateTimeStamp, 12 );
229 : 0 : m_rTGA.Read( mpExtension->sJobNameID, 12 );
230 : 0 : m_rTGA >> mpExtension->sJobNameID[ 0 ] >> mpExtension->sJobNameID[ 1 ] >> mpExtension->sJobNameID[ 2 ];
231 : 0 : m_rTGA.Read( mpExtension->sSoftwareID, 41 );
232 : 0 : m_rTGA >> mpExtension->nSoftwareVersionNumber >> mpExtension->nSoftwareVersionLetter
233 : 0 : >> mpExtension->nKeyColor >> mpExtension->nPixelAspectRatioNumerator
234 : 0 : >> mpExtension->nPixelAspectRatioDeNumerator >> mpExtension->nGammaValueNumerator
235 : 0 : >> mpExtension->nGammaValueDeNumerator >> mpExtension->nColorCorrectionOffset
236 : 0 : >> mpExtension->nPostageStampOffset >> mpExtension->nScanLineOffset
237 : 0 : >> mpExtension->nAttributesType;
238 : :
239 : : }
240 : : }
241 : : }
242 : 6 : m_rTGA.Seek( nCurStreamPos );
243 : : }
244 : :
245 : : // using the TGA file specification this was the correct form but adobe photoshop sets nImageDescriptor
246 : : // equal to nPixelDepth
247 : : // mnDestBitDepth = mpFileHeader->nPixelDepth - ( mpFileHeader->nImageDescriptor & 0xf );
248 : 6 : mnDestBitDepth = mpFileHeader->nPixelDepth;
249 : :
250 [ - + ]: 6 : if ( mnDestBitDepth == 8 ) // this is a patch for grayscale pictures not including a palette
251 : 0 : mbIndexing = sal_True;
252 : :
253 [ - + ]: 6 : if ( mnDestBitDepth > 32 ) // maybe the pixeldepth is invalid
254 : 0 : return sal_False;
255 [ + - ]: 6 : else if ( mnDestBitDepth > 8 )
256 : 6 : mnDestBitDepth = 24;
257 [ # # ]: 0 : else if ( mnDestBitDepth > 4 )
258 : 0 : mnDestBitDepth = 8;
259 [ # # ]: 0 : else if ( mnDestBitDepth > 2 )
260 : 0 : mnDestBitDepth = 4;
261 : :
262 [ + - ][ - + ]: 6 : if ( !mbIndexing && ( mnDestBitDepth < 15 ) )
263 : 0 : return sal_False;
264 : :
265 [ + - ]: 6 : switch ( mpFileHeader->nImageType )
266 : : {
267 : : case 9 : // encoding for colortype 9, 10, 11
268 : : case 10 :
269 : : case 11 :
270 : 6 : mbEncoding = sal_True;
271 : 6 : break;
272 : : };
273 : :
274 [ - + ]: 6 : if ( mpFileHeader->nImageIDLength ) // skip the Image ID
275 : 0 : m_rTGA.SeekRel( mpFileHeader->nImageIDLength );
276 : :
277 : 6 : return mbStatus;
278 : : }
279 : :
280 : : // -------------------------------------------------------------------------------------------
281 : :
282 : 6 : sal_Bool TGAReader::ImplReadBody()
283 : : {
284 : :
285 : : sal_uInt16 nXCount, nYCount, nRGB16;
286 : : sal_uInt8 nRed, nGreen, nBlue, nRunCount, nDummy, nDepth;
287 : :
288 : : // this four variables match the image direction
289 : : long nY, nYAdd, nX, nXAdd, nXStart;
290 : :
291 : 6 : nX = nXStart = nY = 0;
292 : 6 : nXCount = nYCount = 0;
293 : 6 : nYAdd = nXAdd = 1;
294 : :
295 [ - + ]: 6 : if ( mpFileHeader->nImageDescriptor & 0x10 )
296 : : {
297 : 0 : nX = nXStart = mpFileHeader->nImageWidth - 1;
298 : 0 : nXAdd -= 2;
299 : : }
300 : :
301 [ + - ]: 6 : if ( !(mpFileHeader->nImageDescriptor & 0x20 ) )
302 : : {
303 : 6 : nY = mpFileHeader->nImageHeight - 1;
304 : 6 : nYAdd -=2;
305 : : }
306 : :
307 : 6 : nDepth = mpFileHeader->nPixelDepth;
308 : :
309 [ + - ]: 6 : if ( mbEncoding )
310 : : {
311 [ - + ]: 6 : if ( mbIndexing )
312 : : {
313 [ # # # ]: 0 : switch( nDepth )
314 : : {
315 : : // 16 bit encoding + indexing
316 : : case 16 :
317 [ # # ]: 0 : while ( nYCount < mpFileHeader->nImageHeight )
318 : : {
319 [ # # ]: 0 : m_rTGA >> nRunCount;
320 [ # # ]: 0 : if ( nRunCount & 0x80 ) // a run length packet
321 : : {
322 [ # # ]: 0 : m_rTGA >> nRGB16;
323 [ # # ]: 0 : if ( nRGB16 >= mpFileHeader->nColorMapLength )
324 : 0 : return sal_False;
325 : 0 : nRed = (sal_uInt8)( mpColorMap[ nRGB16 ] >> 16 );
326 : 0 : nGreen = (sal_uInt8)( mpColorMap[ nRGB16 ] >> 8 );
327 : 0 : nBlue = (sal_uInt8)( mpColorMap[ nRGB16 ] );
328 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
329 : : {
330 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) );
331 : 0 : nX += nXAdd;
332 : 0 : nXCount++;
333 [ # # ]: 0 : if ( nXCount == mpFileHeader->nImageWidth )
334 : : {
335 : 0 : nX = nXStart;
336 : 0 : nXCount = 0;
337 : 0 : nY += nYAdd;
338 : 0 : nYCount++;
339 : :
340 [ # # ]: 0 : if( nYCount >= mpFileHeader->nImageHeight )
341 : 0 : break;
342 : : }
343 : : }
344 : : }
345 : : else // a raw packet
346 : : {
347 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
348 : : {
349 [ # # ]: 0 : m_rTGA >> nRGB16;
350 [ # # ]: 0 : if ( nRGB16 >= mpFileHeader->nColorMapLength )
351 : 0 : return sal_False;
352 : 0 : nRed = (sal_uInt8)( mpColorMap[ nRGB16 ] >> 16 );
353 : 0 : nGreen = (sal_uInt8)( mpColorMap[ nRGB16 ] >> 8 );
354 : 0 : nBlue = (sal_uInt8)( mpColorMap[ nRGB16 ] );
355 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) );
356 : 0 : nX += nXAdd;
357 : 0 : nXCount++;
358 [ # # ]: 0 : if ( nXCount == mpFileHeader->nImageWidth )
359 : : {
360 : 0 : nX = nXStart;
361 : 0 : nXCount = 0;
362 : 0 : nY += nYAdd;
363 : 0 : nYCount++;
364 : :
365 [ # # ]: 0 : if( nYCount >= mpFileHeader->nImageHeight )
366 : 0 : break;
367 : : }
368 : : }
369 : : }
370 : : }
371 : 0 : break;
372 : :
373 : : // 8 bit encoding + indexing
374 : : case 8 :
375 [ # # ]: 0 : while ( nYCount < mpFileHeader->nImageHeight )
376 : : {
377 [ # # ]: 0 : m_rTGA >> nRunCount;
378 [ # # ]: 0 : if ( nRunCount & 0x80 ) // a run length packet
379 : : {
380 [ # # ]: 0 : m_rTGA >> nDummy;
381 [ # # ]: 0 : if ( nDummy >= mpFileHeader->nColorMapLength )
382 : 0 : return sal_False;
383 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
384 : : {
385 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, (sal_uInt8)nDummy );
386 : 0 : nX += nXAdd;
387 : 0 : nXCount++;
388 [ # # ]: 0 : if ( nXCount == mpFileHeader->nImageWidth )
389 : : {
390 : 0 : nX = nXStart;
391 : 0 : nXCount = 0;
392 : 0 : nY += nYAdd;
393 : 0 : nYCount++;
394 : :
395 [ # # ]: 0 : if( nYCount >= mpFileHeader->nImageHeight )
396 : 0 : break;
397 : : }
398 : : }
399 : : }
400 : : else // a raw packet
401 : : {
402 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
403 : : {
404 : :
405 [ # # ]: 0 : m_rTGA >> nDummy;
406 [ # # ]: 0 : if ( nDummy >= mpFileHeader->nColorMapLength )
407 : 0 : return sal_False;
408 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, (sal_uInt8)nDummy );
409 : 0 : nX += nXAdd;
410 : 0 : nXCount++;
411 [ # # ]: 0 : if ( nXCount == mpFileHeader->nImageWidth )
412 : : {
413 : 0 : nX = nXStart;
414 : 0 : nXCount = 0;
415 : 0 : nY += nYAdd;
416 : 0 : nYCount++;
417 : :
418 [ # # ]: 0 : if( nYCount >= mpFileHeader->nImageHeight )
419 : 0 : break;
420 : : }
421 : : }
422 : : }
423 : : }
424 : 0 : break;
425 : : default:
426 : 0 : return sal_False;
427 : : }
428 : : }
429 : : else
430 : : {
431 [ + - - - ]: 6 : switch( nDepth )
432 : : {
433 : : // 32 bit transparent true color encoding
434 : : case 32 :
435 : : {
436 [ + + ]: 630 : while ( nYCount < mpFileHeader->nImageHeight )
437 : : {
438 [ + - ]: 624 : m_rTGA >> nRunCount;
439 [ + + ]: 624 : if ( nRunCount & 0x80 ) // a run length packet
440 : : {
441 [ + - ][ + - ]: 276 : m_rTGA >> nBlue >> nGreen >> nRed >> nDummy;
[ + - ][ + - ]
442 [ + + ]: 1572 : for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
443 : : {
444 [ + - ]: 1296 : mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) );
445 : 1296 : nX += nXAdd;
446 : 1296 : nXCount++;
447 [ + + ]: 1296 : if ( nXCount == mpFileHeader->nImageWidth )
448 : : {
449 : 66 : nX = nXStart;
450 : 66 : nXCount = 0;
451 : 66 : nY += nYAdd;
452 : 66 : nYCount++;
453 : :
454 [ - + ]: 66 : if( nYCount >= mpFileHeader->nImageHeight )
455 : 0 : break;
456 : : }
457 : : }
458 : : }
459 : : else // a raw packet
460 : : {
461 [ + + ]: 3726 : for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
462 : : {
463 [ + - ][ + - ]: 3384 : m_rTGA >> nBlue >> nGreen >> nRed >> nDummy;
[ + - ][ + - ]
464 [ + - ]: 3384 : mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) );
465 : 3384 : nX += nXAdd;
466 : 3384 : nXCount++;
467 [ + + ]: 3384 : if ( nXCount == mpFileHeader->nImageWidth )
468 : : {
469 : 90 : nX = nXStart;
470 : 90 : nXCount = 0;
471 : 90 : nY += nYAdd;
472 : 90 : nYCount++;
473 : :
474 [ + + ]: 90 : if( nYCount >= mpFileHeader->nImageHeight )
475 : 6 : break;
476 : : }
477 : : }
478 : : }
479 : : }
480 : : }
481 : 6 : break;
482 : :
483 : : // 24 bit true color encoding
484 : : case 24 :
485 [ # # ]: 0 : while ( nYCount < mpFileHeader->nImageHeight )
486 : : {
487 [ # # ]: 0 : m_rTGA >> nRunCount;
488 [ # # ]: 0 : if ( nRunCount & 0x80 ) // a run length packet
489 : : {
490 [ # # ][ # # ]: 0 : m_rTGA >> nBlue >> nGreen >> nRed;
[ # # ]
491 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
492 : : {
493 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) );
494 : 0 : nX += nXAdd;
495 : 0 : nXCount++;
496 [ # # ]: 0 : if ( nXCount == mpFileHeader->nImageWidth )
497 : : {
498 : 0 : nX = nXStart;
499 : 0 : nXCount = 0;
500 : 0 : nY += nYAdd;
501 : 0 : nYCount++;
502 : :
503 [ # # ]: 0 : if( nYCount >= mpFileHeader->nImageHeight )
504 : 0 : break;
505 : : }
506 : : }
507 : : }
508 : : else // a raw packet
509 : : {
510 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
511 : : {
512 [ # # ][ # # ]: 0 : m_rTGA >> nBlue >> nGreen >> nRed;
[ # # ]
513 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) );
514 : 0 : nX += nXAdd;
515 : 0 : nXCount++;
516 [ # # ]: 0 : if ( nXCount == mpFileHeader->nImageWidth )
517 : : {
518 : 0 : nX = nXStart;
519 : 0 : nXCount = 0;
520 : 0 : nY += nYAdd;
521 : 0 : nYCount++;
522 : :
523 [ # # ]: 0 : if( nYCount >= mpFileHeader->nImageHeight )
524 : 0 : break;
525 : : }
526 : : }
527 : : }
528 : : }
529 : 0 : break;
530 : :
531 : : // 16 bit true color encoding
532 : : case 16 :
533 [ # # ]: 0 : while ( nYCount < mpFileHeader->nImageHeight )
534 : : {
535 [ # # ]: 0 : m_rTGA >> nRunCount;
536 [ # # ]: 0 : if ( nRunCount & 0x80 ) // a run length packet
537 : : {
538 [ # # ]: 0 : m_rTGA >> nRGB16;
539 : 0 : nRed = (sal_uInt8)( nRGB16 >> 7 ) & 0xf8;
540 : 0 : nGreen = (sal_uInt8)( nRGB16 >> 2 ) & 0xf8;
541 : 0 : nBlue = (sal_uInt8)( nRGB16 << 3 ) & 0xf8;
542 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
543 : : {
544 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) );
545 : 0 : nX += nXAdd;
546 : 0 : nXCount++;
547 [ # # ]: 0 : if ( nXCount == mpFileHeader->nImageWidth )
548 : : {
549 : 0 : nX = nXStart;
550 : 0 : nXCount = 0;
551 : 0 : nY += nYAdd;
552 : 0 : nYCount++;
553 : :
554 [ # # ]: 0 : if( nYCount >= mpFileHeader->nImageHeight )
555 : 0 : break;
556 : : }
557 : : }
558 : : }
559 : : else // a raw packet
560 : : {
561 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
562 : : {
563 [ # # ]: 0 : m_rTGA >> nRGB16;
564 : 0 : nRed = (sal_uInt8)( nRGB16 >> 7 ) & 0xf8;
565 : 0 : nGreen = (sal_uInt8)( nRGB16 >> 2 ) & 0xf8;
566 : 0 : nBlue = (sal_uInt8)( nRGB16 << 3 ) & 0xf8;
567 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) );
568 : 0 : nX += nXAdd;
569 : 0 : nXCount++;
570 [ # # ]: 0 : if ( nXCount == mpFileHeader->nImageWidth )
571 : : {
572 : 0 : nX = nXStart;
573 : 0 : nXCount = 0;
574 : 0 : nY += nYAdd;
575 : 0 : nYCount++;
576 : :
577 [ # # ]: 0 : if( nYCount >= mpFileHeader->nImageHeight )
578 : 0 : break;
579 : : }
580 : : }
581 : : }
582 : : }
583 : 0 : break;
584 : :
585 : : default:
586 : 6 : return sal_False;
587 : : }
588 : : }
589 : : }
590 : : else
591 : : {
592 [ # # ]: 0 : for ( nYCount = 0; nYCount < mpFileHeader->nImageHeight; nYCount++, nY += nYAdd )
593 : : {
594 : 0 : nX = nXStart;
595 : 0 : nXCount = 0;
596 : :
597 [ # # ]: 0 : if ( mbIndexing )
598 : : {
599 [ # # # ]: 0 : switch( nDepth )
600 : : {
601 : : // 16 bit indexing
602 : : case 16 :
603 [ # # ]: 0 : for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
604 : : {
605 [ # # ]: 0 : m_rTGA >> nRGB16;
606 [ # # ]: 0 : if ( nRGB16 >= mpFileHeader->nColorMapLength )
607 : 0 : return sal_False;
608 : 0 : nRed = (sal_uInt8)( mpColorMap[ nRGB16 ] >> 16 );
609 : 0 : nGreen = (sal_uInt8)( mpColorMap[ nRGB16 ] >> 8 );
610 : 0 : nBlue = (sal_uInt8)( mpColorMap[ nRGB16 ] );
611 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) );
612 : : }
613 : 0 : break;
614 : :
615 : : // 8 bit indexing
616 : : case 8 :
617 [ # # ]: 0 : for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
618 : : {
619 [ # # ]: 0 : m_rTGA >> nDummy;
620 [ # # ]: 0 : if ( nDummy >= mpFileHeader->nColorMapLength )
621 : 0 : return sal_False;
622 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, (sal_uInt8)nDummy );
623 : : }
624 : 0 : break;
625 : : default:
626 : 0 : return sal_False;
627 : : }
628 : : }
629 : : else
630 : : {
631 [ # # # # ]: 0 : switch( nDepth )
632 : : {
633 : : // 32 bit true color
634 : : case 32 :
635 : : {
636 [ # # ]: 0 : for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
637 : : {
638 [ # # ][ # # ]: 0 : m_rTGA >> nBlue >> nGreen >> nRed >> nDummy;
[ # # ][ # # ]
639 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) );
640 : : }
641 : : }
642 : 0 : break;
643 : :
644 : : // 24 bit true color
645 : : case 24 :
646 [ # # ]: 0 : for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
647 : : {
648 [ # # ][ # # ]: 0 : m_rTGA >> nBlue >> nGreen >> nRed;
[ # # ]
649 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) );
650 : : }
651 : 0 : break;
652 : :
653 : : // 16 bit true color
654 : : case 16 :
655 [ # # ]: 0 : for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
656 : : {
657 [ # # ]: 0 : m_rTGA >> nRGB16;
658 : 0 : nRed = (sal_uInt8)( nRGB16 >> 7 ) & 0xf8;
659 : 0 : nGreen = (sal_uInt8)( nRGB16 >> 2 ) & 0xf8;
660 : 0 : nBlue = (sal_uInt8)( nRGB16 << 3 ) & 0xf8;
661 [ # # ]: 0 : mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) );
662 : : }
663 : 0 : break;
664 : : default:
665 : 0 : return sal_False;
666 : : }
667 : : }
668 : : }
669 : : }
670 : 6 : return mbStatus;
671 : : }
672 : :
673 : : // -------------------------------------------------------------------------------------------
674 : :
675 : 0 : sal_Bool TGAReader::ImplReadPalette()
676 : : {
677 [ # # ]: 0 : if ( mbIndexing ) // read the colormap
678 : : {
679 : 0 : sal_uInt16 nColors = mpFileHeader->nColorMapLength;
680 : :
681 [ # # ]: 0 : if ( !nColors ) // colors == 0 ? -> we will build a grayscale palette
682 : : {
683 [ # # ]: 0 : if ( mpFileHeader->nPixelDepth != 8 )
684 : 0 : return sal_False;
685 : 0 : nColors = 256;
686 : 0 : mpFileHeader->nColorMapLength = 256;
687 : 0 : mpFileHeader->nColorMapEntrySize = 0x3f; // patch for the following switch routine
688 : : }
689 : 0 : mpColorMap = new sal_uInt32[ nColors ]; // we will always index dwords
690 [ # # ]: 0 : if ( mpColorMap == sal_False )
691 : 0 : return sal_False; // out of memory %&!$&/!"�$
692 : :
693 [ # # # # : 0 : switch( mpFileHeader->nColorMapEntrySize )
# ]
694 : : {
695 : : case 0x3f :
696 : : {
697 [ # # ]: 0 : for ( sal_uLong i = 0; i < nColors; i++ )
698 : : {
699 : 0 : mpColorMap[ i ] = ( i << 16 ) + ( i << 8 ) + i;
700 : : }
701 : : }
702 : 0 : break;
703 : :
704 : : case 32 :
705 : 0 : m_rTGA.Read( mpColorMap, 4 * nColors );
706 : 0 : break;
707 : :
708 : : case 24 :
709 : : {
710 [ # # ]: 0 : for ( sal_uLong i = 0; i < nColors; i++ )
711 : : {
712 : 0 : m_rTGA.Read( &mpColorMap[ i ], 3 );
713 : : }
714 : : }
715 : 0 : break;
716 : :
717 : : case 15 :
718 : : case 16 :
719 : : {
720 [ # # ]: 0 : for ( sal_uLong i = 0; i < nColors; i++ )
721 : : {
722 : : sal_uInt16 nTemp;
723 [ # # ]: 0 : m_rTGA >> nTemp;
724 : 0 : mpColorMap[ i ] = ( ( nTemp & 0x7c00 ) << 9 ) + ( ( nTemp & 0x01e0 ) << 6 ) +
725 : 0 : ( ( nTemp & 0x1f ) << 3 );
726 : : }
727 : : }
728 : 0 : break;
729 : :
730 : : default :
731 : 0 : return sal_False;
732 : : }
733 [ # # ]: 0 : if ( mnDestBitDepth <= 8 )
734 : : {
735 : 0 : sal_uInt16 nDestColors = ( 1 << mnDestBitDepth );
736 [ # # ]: 0 : if ( nColors > nDestColors )
737 : 0 : return sal_False;
738 : :
739 : 0 : mpAcc->SetPaletteEntryCount( nColors );
740 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < nColors; i++ )
741 : : {
742 : 0 : mpAcc->SetPaletteColor( i, Color( (sal_uInt8)( mpColorMap[ i ] >> 16 ),
743 : 0 : (sal_uInt8)( mpColorMap[ i ] >> 8 ), (sal_uInt8)(mpColorMap[ i ] ) ) );
744 : : }
745 : : }
746 : : }
747 : :
748 : 0 : return mbStatus;
749 : : }
750 : :
751 : : //================== GraphicImport - die exportierte Funktion ================
752 : :
753 : : extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool __LOADONCALLAPI
754 : 6 : GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, sal_Bool)
755 : : {
756 : 6 : TGAReader aTGAReader(rStream);
757 : :
758 [ + - ]: 6 : return aTGAReader.ReadTGA(rGraphic);
759 : : }
760 : :
761 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|