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