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