aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llimage/llimagetga.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llimage/llimagetga.cpp')
-rw-r--r--linden/indra/llimage/llimagetga.cpp1109
1 files changed, 1109 insertions, 0 deletions
diff --git a/linden/indra/llimage/llimagetga.cpp b/linden/indra/llimage/llimagetga.cpp
new file mode 100644
index 0000000..722bd1e
--- /dev/null
+++ b/linden/indra/llimage/llimagetga.cpp
@@ -0,0 +1,1109 @@
1/**
2 * @file llimagetga.cpp
3 *
4 * Copyright (c) 2001-2007, Linden Research, Inc.
5 *
6 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement
9 * ("Other License"), formally executed by you and Linden Lab. Terms of
10 * the GPL can be found in doc/GPL-license.txt in this distribution, or
11 * online at http://secondlife.com/developers/opensource/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at http://secondlife.com/developers/opensource/flossexception
17 *
18 * By copying, modifying or distributing this software, you acknowledge
19 * that you have read and understood your obligations described above,
20 * and agree to abide by those obligations.
21 *
22 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
23 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
24 * COMPLETENESS OR PERFORMANCE.
25 */
26
27#include "linden_common.h"
28
29#include "llimagetga.h"
30#include "llerror.h"
31#include "llmath.h"
32
33// For expanding 5-bit pixel values to 8-bit with best rounding
34// static
35const U8 LLImageTGA::s5to8bits[32] =
36 {
37 0, 8, 16, 25, 33, 41, 49, 58,
38 66, 74, 82, 90, 99, 107, 115, 123,
39 132, 140, 148, 156, 165, 173, 181, 189,
40 197, 206, 214, 222, 230, 239, 247, 255
41 };
42
43inline void LLImageTGA::decodeTruecolorPixel15( U8* dst, const U8* src )
44{
45 // We expand 5 bit data to 8 bit sample width.
46 // The format of the 16-bit (LSB first) input word is
47 // xRRRRRGGGGGBBBBB
48 U32 t = U32(src[0]) + (U32(src[1]) << 8);
49 dst[2] = s5to8bits[t & 0x1F]; // blue
50 t >>= 5;
51 dst[1] = s5to8bits[t & 0x1F]; // green
52 t >>= 5;
53 dst[0] = s5to8bits[t & 0x1F]; // red
54}
55
56LLImageTGA::LLImageTGA()
57 : LLImageFormatted(IMG_CODEC_TGA),
58 mColorMap( NULL ),
59 mColorMapStart( 0 ),
60 mColorMapLength( 0 ),
61 mColorMapBytesPerEntry( 0 ),
62 mIs15Bit( FALSE )
63{
64}
65
66LLImageTGA::LLImageTGA(const LLString& file_name)
67 : LLImageFormatted(IMG_CODEC_TGA),
68 mColorMap( NULL ),
69 mColorMapStart( 0 ),
70 mColorMapLength( 0 ),
71 mColorMapBytesPerEntry( 0 ),
72 mIs15Bit( FALSE )
73{
74 loadFile(file_name);
75}
76
77LLImageTGA::~LLImageTGA()
78{
79 delete mColorMap;
80}
81
82BOOL LLImageTGA::updateData()
83{
84 resetLastError();
85
86 // Check to make sure that this instance has been initialized with data
87 if (!getData() || (0 == getDataSize()))
88 {
89 setLastError("LLImageTGA uninitialized");
90 return FALSE;
91 }
92
93 // Pull image information from the header...
94 U8 flags;
95 U8 junk[256];
96
97 /****************************************************************************
98 **
99 ** For more information about the original Truevision TGA(tm) file format,
100 ** or for additional information about the new extensions to the
101 ** Truevision TGA file, refer to the "Truevision TGA File Format
102 ** Specification Version 2.0" available from Truevision or your
103 ** Truevision dealer.
104 **
105 ** FILE STRUCTURE FOR THE ORIGINAL TRUEVISION TGA FILE
106 ** FIELD 1 : NUMBER OF CHARACTERS IN ID FIELD (1 BYTES)
107 ** FIELD 2 : COLOR MAP TYPE (1 BYTES)
108 ** FIELD 3 : IMAGE TYPE CODE (1 BYTES)
109 ** = 0 NO IMAGE DATA INCLUDED
110 ** = 1 UNCOMPRESSED, COLOR-MAPPED IMAGE
111 ** = 2 UNCOMPRESSED, TRUE-COLOR IMAGE
112 ** = 3 UNCOMPRESSED, BLACK AND WHITE IMAGE
113 ** = 9 RUN-LENGTH ENCODED COLOR-MAPPED IMAGE
114 ** = 10 RUN-LENGTH ENCODED TRUE-COLOR IMAGE
115 ** = 11 RUN-LENGTH ENCODED BLACK AND WHITE IMAGE
116 ** FIELD 4 : COLOR MAP SPECIFICATION (5 BYTES)
117 ** 4.1 : COLOR MAP ORIGIN (2 BYTES)
118 ** 4.2 : COLOR MAP LENGTH (2 BYTES)
119 ** 4.3 : COLOR MAP ENTRY SIZE (2 BYTES)
120 ** FIELD 5 : IMAGE SPECIFICATION (10 BYTES)
121 ** 5.1 : X-ORIGIN OF IMAGE (2 BYTES)
122 ** 5.2 : Y-ORIGIN OF IMAGE (2 BYTES)
123 ** 5.3 : WIDTH OF IMAGE (2 BYTES)
124 ** 5.4 : HEIGHT OF IMAGE (2 BYTES)
125 ** 5.5 : IMAGE PIXEL SIZE (1 BYTE)
126 ** 5.6 : IMAGE DESCRIPTOR BYTE (1 BYTE)
127 ** FIELD 6 : IMAGE ID FIELD (LENGTH SPECIFIED BY FIELD 1)
128 ** FIELD 7 : COLOR MAP DATA (BIT WIDTH SPECIFIED BY FIELD 4.3 AND
129 ** NUMBER OF COLOR MAP ENTRIES SPECIFIED IN FIELD 4.2)
130 ** FIELD 8 : IMAGE DATA FIELD (WIDTH AND HEIGHT SPECIFIED IN
131 ** FIELD 5.3 AND 5.4)
132 ****************************************************************************/
133
134 mDataOffset = 0;
135 mIDLength = *(getData()+mDataOffset++);
136 mColorMapType = *(getData()+mDataOffset++);
137 mImageType = *(getData()+mDataOffset++);
138 mColorMapIndexLo = *(getData()+mDataOffset++);
139 mColorMapIndexHi = *(getData()+mDataOffset++);
140 mColorMapLengthLo = *(getData()+mDataOffset++);
141 mColorMapLengthHi = *(getData()+mDataOffset++);
142 mColorMapDepth = *(getData()+mDataOffset++);
143 mXOffsetLo = *(getData()+mDataOffset++);
144 mXOffsetHi = *(getData()+mDataOffset++);
145 mYOffsetLo = *(getData()+mDataOffset++);
146 mYOffsetHi = *(getData()+mDataOffset++);
147 mWidthLo = *(getData()+mDataOffset++);
148 mWidthHi = *(getData()+mDataOffset++);
149 mHeightLo = *(getData()+mDataOffset++);
150 mHeightHi = *(getData()+mDataOffset++);
151 mPixelSize = *(getData()+mDataOffset++);
152 flags = *(getData()+mDataOffset++);
153 mAttributeBits = flags & 0xf;
154 mOriginRightBit = (flags & 0x10) >> 4;
155 mOriginTopBit = (flags & 0x20) >> 5;
156 mInterleave = (flags & 0xc0) >> 6;
157
158 switch( mImageType )
159 {
160 case 0:
161 // No image data included in file
162 setLastError("Unable to load file. TGA file contains no image data.");
163 return FALSE;
164 case 1:
165 // Colormapped uncompressed
166 if( 8 != mPixelSize )
167 {
168 setLastError("Unable to load file. Colormapped images must have 8 bits per pixel.");
169 return FALSE;
170 }
171 break;
172 case 2:
173 // Truecolor uncompressed
174 break;
175 case 3:
176 // Monochrome uncompressed
177 if( 8 != mPixelSize )
178 {
179 setLastError("Unable to load file. Monochrome images must have 8 bits per pixel.");
180 return FALSE;
181 }
182 break;
183 case 9:
184 // Colormapped, RLE
185 break;
186 case 10:
187 // Truecolor, RLE
188 break;
189 case 11:
190 // Monochrome, RLE
191 if( 8 != mPixelSize )
192 {
193 setLastError("Unable to load file. Monochrome images must have 8 bits per pixel.");
194 return FALSE;
195 }
196 break;
197 default:
198 setLastError("Unable to load file. Unrecoginzed TGA image type.");
199 return FALSE;
200 }
201
202 // discard the ID field, if any
203 if (mIDLength)
204 {
205 memcpy(junk, getData()+mDataOffset, mIDLength);
206 mDataOffset += mIDLength;
207 }
208
209 // check to see if there's a colormap since even rgb files can have them
210 S32 color_map_bytes = 0;
211 if( (1 == mColorMapType) && (mColorMapDepth > 0) )
212 {
213 mColorMapStart = (S32(mColorMapIndexHi) << 8) + mColorMapIndexLo;
214 mColorMapLength = (S32(mColorMapLengthHi) << 8) + mColorMapLengthLo;
215
216 if( mColorMapDepth > 24 )
217 {
218 mColorMapBytesPerEntry = 4;
219 }
220 else
221 if( mColorMapDepth > 16 )
222 {
223 mColorMapBytesPerEntry = 3;
224 }
225 else
226 if( mColorMapDepth > 8 )
227 {
228 mColorMapBytesPerEntry = 2;
229 }
230 else
231 {
232 mColorMapBytesPerEntry = 1;
233 }
234 color_map_bytes = mColorMapLength * mColorMapBytesPerEntry;
235
236 // Note: although it's legal for TGA files to have color maps and not use them
237 // (some programs actually do this and use the color map for other ends), we'll
238 // only allocate memory for one if _we_ intend to use it.
239 if ( (1 == mImageType) || (9 == mImageType) )
240 {
241 mColorMap = new U8[ color_map_bytes ];
242 memcpy( mColorMap, getData() + mDataOffset, color_map_bytes );
243 }
244
245 mDataOffset += color_map_bytes;
246 }
247
248 // heights are read as bytes to prevent endian problems
249 S32 height = (S32(mHeightHi) << 8) + mHeightLo;
250 S32 width = (S32(mWidthHi) << 8) + mWidthLo;
251
252 // make sure that it's a pixel format that we understand
253 S32 bits_per_pixel;
254 if( mColorMap )
255 {
256 bits_per_pixel = mColorMapDepth;
257 }
258 else
259 {
260 bits_per_pixel = mPixelSize;
261 }
262
263 S32 components;
264 switch(bits_per_pixel)
265 {
266 case 24:
267 components = 3;
268 break;
269 case 32:
270 components = 4;
271// Don't enforce this. ACDSee doesn't bother to set the attributes bits correctly. Arrgh!
272// if( mAttributeBits != 8 )
273// {
274// setLastError("Unable to load file. 32 bit TGA image does not have 8 bits of alpha.");
275// return FALSE;
276// }
277 mAttributeBits = 8;
278 break;
279 case 15:
280 case 16:
281 components = 3;
282 mIs15Bit = TRUE; // 16th bit is used for Targa hardware interupts and is ignored.
283 break;
284 case 8:
285 components = 1;
286 break;
287 default:
288 setLastError("Unable to load file. Unknown pixel size.");
289 return FALSE;
290 }
291 setSize(width, height, components);
292
293 return TRUE;
294}
295
296BOOL LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
297{
298 llassert_always(raw_image);
299
300 // Check to make sure that this instance has been initialized with data
301 if (!getData() || (0 == getDataSize()))
302 {
303 setLastError("LLImageTGA trying to decode an image with no data!");
304 return FALSE;
305 }
306
307 // Copy everything after the header.
308
309 raw_image->resize(getWidth(), getHeight(), getComponents());
310
311 if( (getComponents() != 1) &&
312 (getComponents() != 3) &&
313 (getComponents() != 4) )
314 {
315 setLastError("TGA images with a number of components other than 1, 3, and 4 are not supported.");
316 return FALSE;
317 }
318
319
320 if( mOriginRightBit )
321 {
322 setLastError("TGA images with origin on right side are not supported.");
323 return FALSE;
324 }
325
326 BOOL flipped = (mOriginTopBit != 0);
327 BOOL rle_compressed = ((mImageType & 0x08) != 0);
328
329 if( mColorMap )
330 {
331 return decodeColorMap( raw_image, rle_compressed, flipped );
332 }
333 else
334 {
335 return decodeTruecolor( raw_image, rle_compressed, flipped );
336 }
337}
338
339BOOL LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
340{
341 BOOL success = FALSE;
342 BOOL alpha_opaque = FALSE;
343 if( rle )
344 {
345
346 switch( getComponents() )
347 {
348 case 1:
349 success = decodeTruecolorRle8( raw_image );
350 break;
351 case 3:
352 if( mIs15Bit )
353 {
354 success = decodeTruecolorRle15( raw_image );
355 }
356 else
357 {
358 success = decodeTruecolorRle24( raw_image );
359 }
360 break;
361 case 4:
362 success = decodeTruecolorRle32( raw_image, alpha_opaque );
363 if (alpha_opaque)
364 {
365 // alpha was entirely opaque
366 // convert to 24 bit image
367 LLPointer<LLImageRaw> compacted_image = new LLImageRaw(raw_image->getWidth(), raw_image->getHeight(), 3);
368 compacted_image->copy(raw_image);
369 raw_image->resize(raw_image->getWidth(), raw_image->getHeight(), 3);
370 raw_image->copy(compacted_image);
371 }
372 break;
373 }
374 }
375 else
376 {
377 BOOL alpha_opaque;
378 success = decodeTruecolorNonRle( raw_image, alpha_opaque );
379 if (alpha_opaque && raw_image->getComponents() == 4)
380 {
381 // alpha was entirely opaque
382 // convert to 24 bit image
383 LLPointer<LLImageRaw> compacted_image = new LLImageRaw(raw_image->getWidth(), raw_image->getHeight(), 3);
384 compacted_image->copy(raw_image);
385 raw_image->resize(raw_image->getWidth(), raw_image->getHeight(), 3);
386 raw_image->copy(compacted_image);
387 }
388 }
389
390 if( success && flipped )
391 {
392 // This works because the Targa definition requires that RLE blocks never
393 // encode pixels from more than one scanline.
394 // (On the other hand, it's not as fast as writing separate flipped versions as
395 // we did with TruecolorNonRle.)
396 raw_image->verticalFlip();
397 }
398
399 return success;
400}
401
402
403BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaque )
404{
405 alpha_opaque = TRUE;
406
407 // Origin is the bottom left
408 U8* dst = raw_image->getData();
409 U8* src = getData() + mDataOffset;
410 S32 pixels = getWidth() * getHeight();
411
412 if (getComponents() == 4)
413 {
414 while( pixels-- )
415 {
416 // Our data is stored in RGBA. TGA stores them as BGRA (little-endian ARGB)
417 dst[0] = src[2]; // Red
418 dst[1] = src[1]; // Green
419 dst[2] = src[0]; // Blue
420 dst[3] = src[3]; // Alpha
421 if (dst[3] != 255)
422 {
423 alpha_opaque = FALSE;
424 }
425 dst += 4;
426 src += 4;
427 }
428 }
429 else if (getComponents() == 3)
430 {
431 if( mIs15Bit )
432 {
433 while( pixels-- )
434 {
435 decodeTruecolorPixel15( dst, src );
436 dst += 3;
437 src += 2;
438 }
439 }
440 else
441 {
442 while( pixels-- )
443 {
444 dst[0] = src[2]; // Red
445 dst[1] = src[1]; // Green
446 dst[2] = src[0]; // Blue
447 dst += 3;
448 src += 3;
449 }
450 }
451 }
452 else if (getComponents() == 1)
453 {
454 memcpy(dst, src, pixels);
455 }
456
457 return TRUE;
458}
459
460void LLImageTGA::decodeColorMapPixel8( U8* dst, const U8* src )
461{
462 S32 index = llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 );
463 dst[0] = mColorMap[ index ];
464}
465
466void LLImageTGA::decodeColorMapPixel15( U8* dst, const U8* src )
467{
468 S32 index = llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 );
469 decodeTruecolorPixel15( dst, mColorMap + 2 * index );
470}
471
472void LLImageTGA::decodeColorMapPixel24( U8* dst, const U8* src )
473{
474 S32 index = 3 * llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 );
475 dst[0] = mColorMap[ index + 2 ]; // Red
476 dst[1] = mColorMap[ index + 1 ]; // Green
477 dst[2] = mColorMap[ index + 0 ]; // Blue
478}
479
480void LLImageTGA::decodeColorMapPixel32( U8* dst, const U8* src )
481{
482 S32 index = 4 * llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 );
483 dst[0] = mColorMap[ index + 2 ]; // Red
484 dst[1] = mColorMap[ index + 1 ]; // Green
485 dst[2] = mColorMap[ index + 0 ]; // Blue
486 dst[3] = mColorMap[ index + 3 ]; // Alpha
487}
488
489
490BOOL LLImageTGA::decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
491{
492 // If flipped, origin is the top left. Need to reverse the order of the rows.
493 // Otherwise the origin is the bottom left.
494
495 if( 8 != mPixelSize )
496 {
497 return FALSE;
498 }
499
500 U8* src = getData() + mDataOffset;
501 U8* dst = raw_image->getData(); // start from the top
502
503 void (LLImageTGA::*pixel_decoder)( U8*, const U8* );
504
505 switch( mColorMapBytesPerEntry )
506 {
507 case 1: pixel_decoder = &LLImageTGA::decodeColorMapPixel8; break;
508 case 2: pixel_decoder = &LLImageTGA::decodeColorMapPixel15; break;
509 case 3: pixel_decoder = &LLImageTGA::decodeColorMapPixel24; break;
510 case 4: pixel_decoder = &LLImageTGA::decodeColorMapPixel32; break;
511 default: llassert(0); return FALSE;
512 }
513
514 if( rle )
515 {
516 U8* last_dst = dst + getComponents() * (getHeight() * getWidth() - 1);
517 while( dst <= last_dst )
518 {
519 // Read RLE block header
520 U8 block_header_byte = *src;
521 src++;
522
523 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
524 if( block_header_byte & 0x80 )
525 {
526 // Encoded (duplicate-pixel) block
527 do
528 {
529 (this->*pixel_decoder)( dst, src );
530 dst += getComponents();
531 block_pixel_count--;
532 }
533 while( block_pixel_count > 0 );
534 src++;
535 }
536 else
537 {
538 // Unencoded block
539 do
540 {
541 (this->*pixel_decoder)( dst, src );
542 dst += getComponents();
543 src++;
544 block_pixel_count--;
545 }
546 while( block_pixel_count > 0 );
547 }
548 }
549
550 raw_image->verticalFlip();
551 }
552 else
553 {
554 S32 src_row_bytes = getWidth();
555 S32 dst_row_bytes = getWidth() * getComponents();
556
557 if( flipped )
558 {
559 U8* src_last_row_start = src + (getHeight() - 1) * src_row_bytes;
560 src = src_last_row_start; // start from the bottom
561 src_row_bytes *= -1;
562 }
563
564
565 S32 i;
566 S32 j;
567
568 for( S32 row = 0; row < getHeight(); row++ )
569 {
570 for( i = 0, j = 0; j < getWidth(); i += getComponents(), j++ )
571 {
572 (this->*pixel_decoder)( dst + i, src + j );
573 }
574
575 dst += dst_row_bytes;
576 src += src_row_bytes;
577 }
578 }
579
580 return TRUE;
581}
582
583
584
585BOOL LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
586{
587 llassert_always(raw_image);
588
589 deleteData();
590
591 setSize(raw_image->getWidth(), raw_image->getHeight(), raw_image->getComponents());
592
593 // Data from header
594 mIDLength = 0; // Length of identifier string
595 mColorMapType = 0; // 0 = No Map
596
597 // Supported: 2 = Uncompressed true color, 3 = uncompressed monochrome without colormap
598 switch( getComponents() )
599 {
600 case 1:
601 mImageType = 3;
602 break;
603 case 2: // Interpret as intensity plus alpha
604 case 3:
605 case 4:
606 mImageType = 2;
607 break;
608 default:
609 return FALSE;
610 }
611
612 // Color map stuff (unsupported)
613 mColorMapIndexLo = 0; // First color map entry (low order byte)
614 mColorMapIndexHi = 0; // First color map entry (high order byte)
615 mColorMapLengthLo = 0; // Color map length (low order byte)
616 mColorMapLengthHi = 0; // Color map length (high order byte)
617 mColorMapDepth = 0; // Size of color map entry (15, 16, 24, or 32 bits)
618
619 // Image offset relative to origin.
620 mXOffsetLo = 0; // X offset from origin (low order byte)
621 mXOffsetHi = 0; // X offset from origin (hi order byte)
622 mYOffsetLo = 0; // Y offset from origin (low order byte)
623 mYOffsetHi = 0; // Y offset from origin (hi order byte)
624
625 // Height and width
626 mWidthLo = U8(getWidth() & 0xFF); // Width (low order byte)
627 mWidthHi = U8((getWidth() >> 8) & 0xFF); // Width (hi order byte)
628 mHeightLo = U8(getHeight() & 0xFF); // Height (low order byte)
629 mHeightHi = U8((getHeight() >> 8) & 0xFF); // Height (hi order byte)
630
631 S32 bytes_per_pixel;
632 switch( getComponents() )
633 {
634 case 1:
635 bytes_per_pixel = 1;
636 break;
637 case 3:
638 bytes_per_pixel = 3;
639 break;
640 case 2: // Interpret as intensity plus alpha. Store as RGBA.
641 case 4:
642 bytes_per_pixel = 4;
643 break;
644 default:
645 return FALSE;
646 }
647 mPixelSize = U8(bytes_per_pixel * 8); // 8, 16, 24, 32 bits per pixel
648
649 mAttributeBits = (4 == bytes_per_pixel) ? 8 : 0; // 4 bits: number of attribute bits (alpha) per pixel
650 mOriginRightBit = 0; // 1 bit: origin, 0 = left, 1 = right
651 mOriginTopBit = 0; // 1 bit: origin, 0 = bottom, 1 = top
652 mInterleave = 0; // 2 bits: interleaved flag, 0 = none, 1 = interleaved 2, 2 = interleaved 4
653
654
655 const S32 TGA_HEADER_SIZE = 18;
656 const S32 COLOR_MAP_SIZE = 0;
657 mDataOffset = TGA_HEADER_SIZE + mIDLength + COLOR_MAP_SIZE; // Offset from start of data to the actual header.
658
659 S32 pixels = getWidth() * getHeight();
660 S32 datasize = mDataOffset + bytes_per_pixel * pixels;
661 U8* dst = allocateData(datasize);
662
663 // Write header
664 *(dst++) = mIDLength;
665 *(dst++) = mColorMapType;
666 *(dst++) = mImageType;
667 *(dst++) = mColorMapIndexLo;
668 *(dst++) = mColorMapIndexHi;
669 *(dst++) = mColorMapLengthLo;
670 *(dst++) = mColorMapLengthHi;
671 *(dst++) = mColorMapDepth;
672 *(dst++) = mXOffsetLo;
673 *(dst++) = mXOffsetHi;
674 *(dst++) = mYOffsetLo;
675 *(dst++) = mYOffsetHi;
676 *(dst++) = mWidthLo;
677 *(dst++) = mWidthHi;
678 *(dst++) = mHeightLo;
679 *(dst++) = mHeightHi;
680 *(dst++) = mPixelSize;
681 *(dst++) =
682 ((mInterleave & 3) << 5) |
683 ((mOriginTopBit & 1) << 4) |
684 ((mOriginRightBit & 1) << 3) |
685 ((mAttributeBits & 0xF) << 0);
686
687 // Write pixels
688 const U8* src = raw_image->getData();
689 llassert( dst == getData() + mDataOffset );
690 S32 i = 0;
691 S32 j = 0;
692 switch( getComponents() )
693 {
694 case 1:
695 memcpy( dst, src, bytes_per_pixel * pixels );
696 break;
697
698 case 2:
699 while( pixels-- )
700 {
701 dst[i + 0] = src[j + 0]; // intensity
702 dst[i + 1] = src[j + 0]; // intensity
703 dst[i + 2] = src[j + 0]; // intensity
704 dst[i + 3] = src[j + 1]; // alpha
705 i += 4;
706 j += 2;
707 }
708 break;
709
710 case 3:
711 while( pixels-- )
712 {
713 dst[i + 0] = src[i + 2]; // blue
714 dst[i + 1] = src[i + 1]; // green
715 dst[i + 2] = src[i + 0]; // red
716 i += 3;
717 }
718 break;
719
720 case 4:
721 while( pixels-- )
722 {
723 dst[i + 0] = src[i + 2]; // blue
724 dst[i + 1] = src[i + 1]; // green
725 dst[i + 2] = src[i + 0]; // red
726 dst[i + 3] = src[i + 3]; // alpha
727 i += 4;
728 }
729 break;
730 }
731
732 return TRUE;
733}
734
735BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque )
736{
737 llassert( getComponents() == 4 );
738 alpha_opaque = TRUE;
739
740 U8* dst = raw_image->getData();
741 U32* dst_pixels = (U32*) dst;
742
743 U8* src = getData() + mDataOffset;
744
745 U32 rgba;
746 U8* rgba_byte_p = (U8*) &rgba;
747
748 U32* last_dst_pixel = dst_pixels + getHeight() * getWidth() - 1;
749 while( dst_pixels <= last_dst_pixel )
750 {
751 // Read RLE block header
752 U8 block_header_byte = *src;
753 src++;
754
755 U32 block_pixel_count = (block_header_byte & 0x7F) + 1;
756 if( block_header_byte & 0x80 )
757 {
758 // Encoded (duplicate-pixel) block
759 rgba_byte_p[0] = src[2];
760 rgba_byte_p[1] = src[1];
761 rgba_byte_p[2] = src[0];
762 rgba_byte_p[3] = src[3];
763 if (rgba_byte_p[3] != 255)
764 {
765 alpha_opaque = FALSE;
766 }
767
768 src += 4;
769 register U32 value = rgba;
770 do
771 {
772 *dst_pixels = value;
773 dst_pixels++;
774 block_pixel_count--;
775 }
776 while( block_pixel_count > 0 );
777 }
778 else
779 {
780 // Unencoded block
781 do
782 {
783 ((U8*)dst_pixels)[0] = src[2];
784 ((U8*)dst_pixels)[1] = src[1];
785 ((U8*)dst_pixels)[2] = src[0];
786 ((U8*)dst_pixels)[3] = src[3];
787 if (src[3] != 255)
788 {
789 alpha_opaque = FALSE;
790 }
791 src += 4;
792 dst_pixels++;
793 block_pixel_count--;
794 }
795 while( block_pixel_count > 0 );
796 }
797 }
798
799 return TRUE;
800}
801
802BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
803{
804 llassert( getComponents() == 3 );
805 llassert( mIs15Bit );
806
807 U8* dst = raw_image->getData();
808 U8* src = getData() + mDataOffset;
809
810 U8* last_dst = dst + getComponents() * (getHeight() * getWidth() - 1);
811 while( dst <= last_dst )
812 {
813 // Read RLE block header
814 U8 block_header_byte = *src;
815 src++;
816
817 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
818 if( block_header_byte & 0x80 )
819 {
820 // Encoded (duplicate-pixel) block
821 do
822 {
823 decodeTruecolorPixel15( dst, src ); // slow
824 dst += 3;
825 block_pixel_count--;
826 }
827 while( block_pixel_count > 0 );
828 src += 2;
829 }
830 else
831 {
832 // Unencoded block
833 do
834 {
835 decodeTruecolorPixel15( dst, src );
836 dst += 3;
837 src += 2;
838 block_pixel_count--;
839 }
840 while( block_pixel_count > 0 );
841 }
842 }
843
844 return TRUE;
845}
846
847
848
849BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
850{
851 llassert( getComponents() == 3 );
852
853 U8* dst = raw_image->getData();
854 U8* src = getData() + mDataOffset;
855
856 U8* last_dst = dst + getComponents() * (getHeight() * getWidth() - 1);
857 while( dst <= last_dst )
858 {
859 // Read RLE block header
860 U8 block_header_byte = *src;
861 src++;
862
863 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
864 if( block_header_byte & 0x80 )
865 {
866 // Encoded (duplicate-pixel) block
867 do
868 {
869 dst[0] = src[2];
870 dst[1] = src[1];
871 dst[2] = src[0];
872 dst += 3;
873 block_pixel_count--;
874 }
875 while( block_pixel_count > 0 );
876 src += 3;
877 }
878 else
879 {
880 // Unencoded block
881 do
882 {
883 dst[0] = src[2];
884 dst[1] = src[1];
885 dst[2] = src[0];
886 dst += 3;
887 src += 3;
888 block_pixel_count--;
889 }
890 while( block_pixel_count > 0 );
891 }
892 }
893
894 return TRUE;
895}
896
897
898BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
899{
900 llassert( getComponents() == 1 );
901
902 U8* dst = raw_image->getData();
903 U8* src = getData() + mDataOffset;
904
905 U8* last_dst = dst + getHeight() * getWidth() - 1;
906 while( dst <= last_dst )
907 {
908 // Read RLE block header
909 U8 block_header_byte = *src;
910 src++;
911
912 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
913 if( block_header_byte & 0x80 )
914 {
915 // Encoded (duplicate-pixel) block
916 memset( dst, *src, block_pixel_count );
917 dst += block_pixel_count;
918 src++;
919 }
920 else
921 {
922 // Unencoded block
923 do
924 {
925 *dst = *src;
926 dst++;
927 src++;
928 block_pixel_count--;
929 }
930 while( block_pixel_count > 0 );
931 }
932 }
933
934 return TRUE;
935}
936
937
938// Decoded and process the image for use in avatar gradient masks.
939// Processing happens during the decode for speed.
940BOOL LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight )
941{
942 llassert_always(raw_image);
943
944 // "Domain" isn't really the right word. It refers to the width of the
945 // ramp portion of the function that relates input and output pixel values.
946 // A domain of 0 gives a step function.
947 //
948 // | /----------------
949 // O| / |
950 // u| / |
951 // t| / |
952 // p|------------------/ |
953 // u| | |
954 // t|<---------------->|<-->|
955 // | "offset" "domain"
956 // |
957 // --+---Input--------------------------------
958 // |
959
960 if (!getData() || (0 == getDataSize()))
961 {
962 setLastError("LLImageTGA trying to decode an image with no data!");
963 return FALSE;
964 }
965
966 // Only works for unflipped monochrome RLE images
967 if( (getComponents() != 1) || (mImageType != 11) || mOriginTopBit || mOriginRightBit )
968 {
969 llerrs << "LLImageTGA trying to alpha-gradient process an image that's not a standard RLE, one component image" << llendl;
970 return FALSE;
971 }
972
973 raw_image->resize(getWidth(), getHeight(), getComponents());
974
975 U8* dst = raw_image->getData();
976 U8* src = getData() + mDataOffset;
977 U8* last_dst = dst + getHeight() * getWidth() - 1;
978
979 if( domain > 0 )
980 {
981 // Process using a look-up table (lut)
982 const S32 LUT_LEN = 256;
983 U8 lut[LUT_LEN];
984 S32 i;
985
986 F32 scale = 1.f / domain;
987 F32 offset = (1.f - domain) * llclampf( 1.f - weight );
988 F32 bias = -(scale * offset);
989
990 for( i = 0; i < LUT_LEN; i++ )
991 {
992 lut[i] = (U8)llclampb( 255.f * ( i/255.f * scale + bias ) );
993 }
994
995 while( dst <= last_dst )
996 {
997 // Read RLE block header
998 U8 block_header_byte = *src;
999 src++;
1000
1001 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
1002 if( block_header_byte & 0x80 )
1003 {
1004 // Encoded (duplicate-pixel) block
1005 memset( dst, lut[ *src ], block_pixel_count );
1006 dst += block_pixel_count;
1007 src++;
1008 }
1009 else
1010 {
1011 // Unencoded block
1012 do
1013 {
1014 *dst = lut[ *src ];
1015 dst++;
1016 src++;
1017 block_pixel_count--;
1018 }
1019 while( block_pixel_count > 0 );
1020 }
1021 }
1022 }
1023 else
1024 {
1025 // Process using a simple comparison agains a threshold
1026 const U8 threshold = (U8)(0xFF * llclampf( 1.f - weight ));
1027
1028 while( dst <= last_dst )
1029 {
1030 // Read RLE block header
1031 U8 block_header_byte = *src;
1032 src++;
1033
1034 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
1035 if( block_header_byte & 0x80 )
1036 {
1037 // Encoded (duplicate-pixel) block
1038 memset( dst, ((*src >= threshold) ? 0xFF : 0), block_pixel_count );
1039 dst += block_pixel_count;
1040 src++;
1041 }
1042 else
1043 {
1044 // Unencoded block
1045 do
1046 {
1047 *dst = (*src >= threshold) ? 0xFF : 0;
1048 dst++;
1049 src++;
1050 block_pixel_count--;
1051 }
1052 while( block_pixel_count > 0 );
1053 }
1054 }
1055 }
1056 return TRUE;
1057}
1058
1059// Reads a .tga file and creates an LLImageTGA with its data.
1060bool LLImageTGA::loadFile( const LLString& path )
1061{
1062 S32 len = path.size();
1063 if( len < 5 )
1064 {
1065 return false;
1066 }
1067
1068 LLString extension = path.substr( len - 4, 4 );
1069 LLString::toLower(extension);
1070 if( ".tga" != extension )
1071 {
1072 return false;
1073 }
1074
1075 FILE *file = LLFile::fopen(path.c_str(), "rb");
1076 if( !file )
1077 {
1078 llwarns << "Couldn't open file " << path << llendl;
1079 return false;
1080 }
1081
1082 S32 file_size = 0;
1083 if (!fseek(file, 0, SEEK_END))
1084 {
1085 file_size = ftell(file);
1086 fseek(file, 0, SEEK_SET);
1087 }
1088
1089 U8* buffer = allocateData(file_size);
1090 S32 bytes_read = fread(buffer, 1, file_size, file);
1091 if( bytes_read != file_size )
1092 {
1093 deleteData();
1094 llwarns << "Couldn't read file " << path << llendl;
1095 return false;
1096 }
1097
1098 fclose( file );
1099
1100 if( !updateData() )
1101 {
1102 llwarns << "Couldn't decode file " << path << llendl;
1103 deleteData();
1104 return false;
1105 }
1106 return true;
1107}
1108
1109