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