diff options
Diffstat (limited to 'linden/indra/llimage/llimagetga.cpp')
-rw-r--r-- | linden/indra/llimage/llimagetga.cpp | 1109 |
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 | ||
35 | const 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 | |||
43 | inline 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 | |||
56 | LLImageTGA::LLImageTGA() | ||
57 | : LLImageFormatted(IMG_CODEC_TGA), | ||
58 | mColorMap( NULL ), | ||
59 | mColorMapStart( 0 ), | ||
60 | mColorMapLength( 0 ), | ||
61 | mColorMapBytesPerEntry( 0 ), | ||
62 | mIs15Bit( FALSE ) | ||
63 | { | ||
64 | } | ||
65 | |||
66 | LLImageTGA::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 | |||
77 | LLImageTGA::~LLImageTGA() | ||
78 | { | ||
79 | delete mColorMap; | ||
80 | } | ||
81 | |||
82 | BOOL 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 | |||
296 | BOOL 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 | |||
339 | BOOL 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 | |||
403 | BOOL 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 | |||
460 | void LLImageTGA::decodeColorMapPixel8( U8* dst, const U8* src ) | ||
461 | { | ||
462 | S32 index = llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 ); | ||
463 | dst[0] = mColorMap[ index ]; | ||
464 | } | ||
465 | |||
466 | void 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 | |||
472 | void 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 | |||
480 | void 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 | |||
490 | BOOL 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 | |||
585 | BOOL 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 | |||
735 | BOOL 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 | |||
802 | BOOL 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 | |||
849 | BOOL 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 | |||
898 | BOOL 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. | ||
940 | BOOL 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. | ||
1060 | bool 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 | |||