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