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