00001
00031 #include "linden_common.h"
00032
00033 #include "llimagetga.h"
00034 #include "llerror.h"
00035 #include "llmath.h"
00036
00037
00038
00039 const U8 LLImageTGA::s5to8bits[32] =
00040 {
00041 0, 8, 16, 25, 33, 41, 49, 58,
00042 66, 74, 82, 90, 99, 107, 115, 123,
00043 132, 140, 148, 156, 165, 173, 181, 189,
00044 197, 206, 214, 222, 230, 239, 247, 255
00045 };
00046
00047 inline void LLImageTGA::decodeTruecolorPixel15( U8* dst, const U8* src )
00048 {
00049
00050
00051
00052 U32 t = U32(src[0]) + (U32(src[1]) << 8);
00053 dst[2] = s5to8bits[t & 0x1F];
00054 t >>= 5;
00055 dst[1] = s5to8bits[t & 0x1F];
00056 t >>= 5;
00057 dst[0] = s5to8bits[t & 0x1F];
00058 }
00059
00060 LLImageTGA::LLImageTGA()
00061 : LLImageFormatted(IMG_CODEC_TGA),
00062 mColorMap( NULL ),
00063 mColorMapStart( 0 ),
00064 mColorMapLength( 0 ),
00065 mColorMapBytesPerEntry( 0 ),
00066 mIs15Bit( FALSE )
00067 {
00068 }
00069
00070 LLImageTGA::LLImageTGA(const LLString& file_name)
00071 : LLImageFormatted(IMG_CODEC_TGA),
00072 mColorMap( NULL ),
00073 mColorMapStart( 0 ),
00074 mColorMapLength( 0 ),
00075 mColorMapBytesPerEntry( 0 ),
00076 mIs15Bit( FALSE )
00077 {
00078 loadFile(file_name);
00079 }
00080
00081 LLImageTGA::~LLImageTGA()
00082 {
00083 delete mColorMap;
00084 }
00085
00086 BOOL LLImageTGA::updateData()
00087 {
00088 resetLastError();
00089
00090
00091 if (!getData() || (0 == getDataSize()))
00092 {
00093 setLastError("LLImageTGA uninitialized");
00094 return FALSE;
00095 }
00096
00097
00098 U8 flags;
00099 U8 junk[256];
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 mDataOffset = 0;
00139 mIDLength = *(getData()+mDataOffset++);
00140 mColorMapType = *(getData()+mDataOffset++);
00141 mImageType = *(getData()+mDataOffset++);
00142 mColorMapIndexLo = *(getData()+mDataOffset++);
00143 mColorMapIndexHi = *(getData()+mDataOffset++);
00144 mColorMapLengthLo = *(getData()+mDataOffset++);
00145 mColorMapLengthHi = *(getData()+mDataOffset++);
00146 mColorMapDepth = *(getData()+mDataOffset++);
00147 mXOffsetLo = *(getData()+mDataOffset++);
00148 mXOffsetHi = *(getData()+mDataOffset++);
00149 mYOffsetLo = *(getData()+mDataOffset++);
00150 mYOffsetHi = *(getData()+mDataOffset++);
00151 mWidthLo = *(getData()+mDataOffset++);
00152 mWidthHi = *(getData()+mDataOffset++);
00153 mHeightLo = *(getData()+mDataOffset++);
00154 mHeightHi = *(getData()+mDataOffset++);
00155 mPixelSize = *(getData()+mDataOffset++);
00156 flags = *(getData()+mDataOffset++);
00157 mAttributeBits = flags & 0xf;
00158 mOriginRightBit = (flags & 0x10) >> 4;
00159 mOriginTopBit = (flags & 0x20) >> 5;
00160 mInterleave = (flags & 0xc0) >> 6;
00161
00162 switch( mImageType )
00163 {
00164 case 0:
00165
00166 setLastError("Unable to load file. TGA file contains no image data.");
00167 return FALSE;
00168 case 1:
00169
00170 if( 8 != mPixelSize )
00171 {
00172 setLastError("Unable to load file. Colormapped images must have 8 bits per pixel.");
00173 return FALSE;
00174 }
00175 break;
00176 case 2:
00177
00178 break;
00179 case 3:
00180
00181 if( 8 != mPixelSize )
00182 {
00183 setLastError("Unable to load file. Monochrome images must have 8 bits per pixel.");
00184 return FALSE;
00185 }
00186 break;
00187 case 9:
00188
00189 break;
00190 case 10:
00191
00192 break;
00193 case 11:
00194
00195 if( 8 != mPixelSize )
00196 {
00197 setLastError("Unable to load file. Monochrome images must have 8 bits per pixel.");
00198 return FALSE;
00199 }
00200 break;
00201 default:
00202 setLastError("Unable to load file. Unrecoginzed TGA image type.");
00203 return FALSE;
00204 }
00205
00206
00207 if (mIDLength)
00208 {
00209 memcpy(junk, getData()+mDataOffset, mIDLength);
00210 mDataOffset += mIDLength;
00211 }
00212
00213
00214 S32 color_map_bytes = 0;
00215 if( (1 == mColorMapType) && (mColorMapDepth > 0) )
00216 {
00217 mColorMapStart = (S32(mColorMapIndexHi) << 8) + mColorMapIndexLo;
00218 mColorMapLength = (S32(mColorMapLengthHi) << 8) + mColorMapLengthLo;
00219
00220 if( mColorMapDepth > 24 )
00221 {
00222 mColorMapBytesPerEntry = 4;
00223 }
00224 else
00225 if( mColorMapDepth > 16 )
00226 {
00227 mColorMapBytesPerEntry = 3;
00228 }
00229 else
00230 if( mColorMapDepth > 8 )
00231 {
00232 mColorMapBytesPerEntry = 2;
00233 }
00234 else
00235 {
00236 mColorMapBytesPerEntry = 1;
00237 }
00238 color_map_bytes = mColorMapLength * mColorMapBytesPerEntry;
00239
00240
00241
00242
00243 if ( (1 == mImageType) || (9 == mImageType) )
00244 {
00245 mColorMap = new U8[ color_map_bytes ];
00246 if (!mColorMap)
00247 {
00248 llerrs << "Out of Memory in BOOL LLImageTGA::updateData()" << llendl;
00249 return FALSE;
00250 }
00251 memcpy( mColorMap, getData() + mDataOffset, color_map_bytes );
00252 }
00253
00254 mDataOffset += color_map_bytes;
00255 }
00256
00257
00258 S32 height = (S32(mHeightHi) << 8) + mHeightLo;
00259 S32 width = (S32(mWidthHi) << 8) + mWidthLo;
00260
00261
00262 S32 bits_per_pixel;
00263 if( mColorMap )
00264 {
00265 bits_per_pixel = mColorMapDepth;
00266 }
00267 else
00268 {
00269 bits_per_pixel = mPixelSize;
00270 }
00271
00272 S32 components;
00273 switch(bits_per_pixel)
00274 {
00275 case 24:
00276 components = 3;
00277 break;
00278 case 32:
00279 components = 4;
00280
00281
00282
00283
00284
00285
00286 mAttributeBits = 8;
00287 break;
00288 case 15:
00289 case 16:
00290 components = 3;
00291 mIs15Bit = TRUE;
00292 break;
00293 case 8:
00294 components = 1;
00295 break;
00296 default:
00297 setLastError("Unable to load file. Unknown pixel size.");
00298 return FALSE;
00299 }
00300 setSize(width, height, components);
00301
00302 return TRUE;
00303 }
00304
00305 BOOL LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
00306 {
00307 llassert_always(raw_image);
00308
00309
00310 if (!getData() || (0 == getDataSize()))
00311 {
00312 setLastError("LLImageTGA trying to decode an image with no data!");
00313 return FALSE;
00314 }
00315
00316
00317
00318 raw_image->resize(getWidth(), getHeight(), getComponents());
00319
00320 if( (getComponents() != 1) &&
00321 (getComponents() != 3) &&
00322 (getComponents() != 4) )
00323 {
00324 setLastError("TGA images with a number of components other than 1, 3, and 4 are not supported.");
00325 return FALSE;
00326 }
00327
00328
00329 if( mOriginRightBit )
00330 {
00331 setLastError("TGA images with origin on right side are not supported.");
00332 return FALSE;
00333 }
00334
00335 BOOL flipped = (mOriginTopBit != 0);
00336 BOOL rle_compressed = ((mImageType & 0x08) != 0);
00337
00338 if( mColorMap )
00339 {
00340 return decodeColorMap( raw_image, rle_compressed, flipped );
00341 }
00342 else
00343 {
00344 return decodeTruecolor( raw_image, rle_compressed, flipped );
00345 }
00346 }
00347
00348 BOOL LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
00349 {
00350 BOOL success = FALSE;
00351 BOOL alpha_opaque = FALSE;
00352 if( rle )
00353 {
00354
00355 switch( getComponents() )
00356 {
00357 case 1:
00358 success = decodeTruecolorRle8( raw_image );
00359 break;
00360 case 3:
00361 if( mIs15Bit )
00362 {
00363 success = decodeTruecolorRle15( raw_image );
00364 }
00365 else
00366 {
00367 success = decodeTruecolorRle24( raw_image );
00368 }
00369 break;
00370 case 4:
00371 success = decodeTruecolorRle32( raw_image, alpha_opaque );
00372 if (alpha_opaque)
00373 {
00374
00375
00376 LLPointer<LLImageRaw> compacted_image = new LLImageRaw(raw_image->getWidth(), raw_image->getHeight(), 3);
00377 compacted_image->copy(raw_image);
00378 raw_image->resize(raw_image->getWidth(), raw_image->getHeight(), 3);
00379 raw_image->copy(compacted_image);
00380 }
00381 break;
00382 }
00383 }
00384 else
00385 {
00386 BOOL alpha_opaque;
00387 success = decodeTruecolorNonRle( raw_image, alpha_opaque );
00388 if (alpha_opaque && raw_image->getComponents() == 4)
00389 {
00390
00391
00392 LLPointer<LLImageRaw> compacted_image = new LLImageRaw(raw_image->getWidth(), raw_image->getHeight(), 3);
00393 compacted_image->copy(raw_image);
00394 raw_image->resize(raw_image->getWidth(), raw_image->getHeight(), 3);
00395 raw_image->copy(compacted_image);
00396 }
00397 }
00398
00399 if( success && flipped )
00400 {
00401
00402
00403
00404
00405 raw_image->verticalFlip();
00406 }
00407
00408 return success;
00409 }
00410
00411
00412 BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaque )
00413 {
00414 alpha_opaque = TRUE;
00415
00416
00417 U8* dst = raw_image->getData();
00418 U8* src = getData() + mDataOffset;
00419 S32 pixels = getWidth() * getHeight();
00420
00421 if (getComponents() == 4)
00422 {
00423 while( pixels-- )
00424 {
00425
00426 dst[0] = src[2];
00427 dst[1] = src[1];
00428 dst[2] = src[0];
00429 dst[3] = src[3];
00430 if (dst[3] != 255)
00431 {
00432 alpha_opaque = FALSE;
00433 }
00434 dst += 4;
00435 src += 4;
00436 }
00437 }
00438 else if (getComponents() == 3)
00439 {
00440 if( mIs15Bit )
00441 {
00442 while( pixels-- )
00443 {
00444 decodeTruecolorPixel15( dst, src );
00445 dst += 3;
00446 src += 2;
00447 }
00448 }
00449 else
00450 {
00451 while( pixels-- )
00452 {
00453 dst[0] = src[2];
00454 dst[1] = src[1];
00455 dst[2] = src[0];
00456 dst += 3;
00457 src += 3;
00458 }
00459 }
00460 }
00461 else if (getComponents() == 1)
00462 {
00463 memcpy(dst, src, pixels);
00464 }
00465
00466 return TRUE;
00467 }
00468
00469 void LLImageTGA::decodeColorMapPixel8( U8* dst, const U8* src )
00470 {
00471 S32 index = llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 );
00472 dst[0] = mColorMap[ index ];
00473 }
00474
00475 void LLImageTGA::decodeColorMapPixel15( U8* dst, const U8* src )
00476 {
00477 S32 index = llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 );
00478 decodeTruecolorPixel15( dst, mColorMap + 2 * index );
00479 }
00480
00481 void LLImageTGA::decodeColorMapPixel24( U8* dst, const U8* src )
00482 {
00483 S32 index = 3 * llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 );
00484 dst[0] = mColorMap[ index + 2 ];
00485 dst[1] = mColorMap[ index + 1 ];
00486 dst[2] = mColorMap[ index + 0 ];
00487 }
00488
00489 void LLImageTGA::decodeColorMapPixel32( U8* dst, const U8* src )
00490 {
00491 S32 index = 4 * llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 );
00492 dst[0] = mColorMap[ index + 2 ];
00493 dst[1] = mColorMap[ index + 1 ];
00494 dst[2] = mColorMap[ index + 0 ];
00495 dst[3] = mColorMap[ index + 3 ];
00496 }
00497
00498
00499 BOOL LLImageTGA::decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
00500 {
00501
00502
00503
00504 if( 8 != mPixelSize )
00505 {
00506 return FALSE;
00507 }
00508
00509 U8* src = getData() + mDataOffset;
00510 U8* dst = raw_image->getData();
00511
00512 void (LLImageTGA::*pixel_decoder)( U8*, const U8* );
00513
00514 switch( mColorMapBytesPerEntry )
00515 {
00516 case 1: pixel_decoder = &LLImageTGA::decodeColorMapPixel8; break;
00517 case 2: pixel_decoder = &LLImageTGA::decodeColorMapPixel15; break;
00518 case 3: pixel_decoder = &LLImageTGA::decodeColorMapPixel24; break;
00519 case 4: pixel_decoder = &LLImageTGA::decodeColorMapPixel32; break;
00520 default: llassert(0); return FALSE;
00521 }
00522
00523 if( rle )
00524 {
00525 U8* last_dst = dst + getComponents() * (getHeight() * getWidth() - 1);
00526 while( dst <= last_dst )
00527 {
00528
00529 U8 block_header_byte = *src;
00530 src++;
00531
00532 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
00533 if( block_header_byte & 0x80 )
00534 {
00535
00536 do
00537 {
00538 (this->*pixel_decoder)( dst, src );
00539 dst += getComponents();
00540 block_pixel_count--;
00541 }
00542 while( block_pixel_count > 0 );
00543 src++;
00544 }
00545 else
00546 {
00547
00548 do
00549 {
00550 (this->*pixel_decoder)( dst, src );
00551 dst += getComponents();
00552 src++;
00553 block_pixel_count--;
00554 }
00555 while( block_pixel_count > 0 );
00556 }
00557 }
00558
00559 raw_image->verticalFlip();
00560 }
00561 else
00562 {
00563 S32 src_row_bytes = getWidth();
00564 S32 dst_row_bytes = getWidth() * getComponents();
00565
00566 if( flipped )
00567 {
00568 U8* src_last_row_start = src + (getHeight() - 1) * src_row_bytes;
00569 src = src_last_row_start;
00570 src_row_bytes *= -1;
00571 }
00572
00573
00574 S32 i;
00575 S32 j;
00576
00577 for( S32 row = 0; row < getHeight(); row++ )
00578 {
00579 for( i = 0, j = 0; j < getWidth(); i += getComponents(), j++ )
00580 {
00581 (this->*pixel_decoder)( dst + i, src + j );
00582 }
00583
00584 dst += dst_row_bytes;
00585 src += src_row_bytes;
00586 }
00587 }
00588
00589 return TRUE;
00590 }
00591
00592
00593
00594 BOOL LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
00595 {
00596 llassert_always(raw_image);
00597
00598 deleteData();
00599
00600 setSize(raw_image->getWidth(), raw_image->getHeight(), raw_image->getComponents());
00601
00602
00603 mIDLength = 0;
00604 mColorMapType = 0;
00605
00606
00607 switch( getComponents() )
00608 {
00609 case 1:
00610 mImageType = 3;
00611 break;
00612 case 2:
00613 case 3:
00614 case 4:
00615 mImageType = 2;
00616 break;
00617 default:
00618 return FALSE;
00619 }
00620
00621
00622 mColorMapIndexLo = 0;
00623 mColorMapIndexHi = 0;
00624 mColorMapLengthLo = 0;
00625 mColorMapLengthHi = 0;
00626 mColorMapDepth = 0;
00627
00628
00629 mXOffsetLo = 0;
00630 mXOffsetHi = 0;
00631 mYOffsetLo = 0;
00632 mYOffsetHi = 0;
00633
00634
00635 mWidthLo = U8(getWidth() & 0xFF);
00636 mWidthHi = U8((getWidth() >> 8) & 0xFF);
00637 mHeightLo = U8(getHeight() & 0xFF);
00638 mHeightHi = U8((getHeight() >> 8) & 0xFF);
00639
00640 S32 bytes_per_pixel;
00641 switch( getComponents() )
00642 {
00643 case 1:
00644 bytes_per_pixel = 1;
00645 break;
00646 case 3:
00647 bytes_per_pixel = 3;
00648 break;
00649 case 2:
00650 case 4:
00651 bytes_per_pixel = 4;
00652 break;
00653 default:
00654 return FALSE;
00655 }
00656 mPixelSize = U8(bytes_per_pixel * 8);
00657
00658 mAttributeBits = (4 == bytes_per_pixel) ? 8 : 0;
00659 mOriginRightBit = 0;
00660 mOriginTopBit = 0;
00661 mInterleave = 0;
00662
00663
00664 const S32 TGA_HEADER_SIZE = 18;
00665 const S32 COLOR_MAP_SIZE = 0;
00666 mDataOffset = TGA_HEADER_SIZE + mIDLength + COLOR_MAP_SIZE;
00667
00668 S32 pixels = getWidth() * getHeight();
00669 S32 datasize = mDataOffset + bytes_per_pixel * pixels;
00670 U8* dst = allocateData(datasize);
00671
00672
00673 *(dst++) = mIDLength;
00674 *(dst++) = mColorMapType;
00675 *(dst++) = mImageType;
00676 *(dst++) = mColorMapIndexLo;
00677 *(dst++) = mColorMapIndexHi;
00678 *(dst++) = mColorMapLengthLo;
00679 *(dst++) = mColorMapLengthHi;
00680 *(dst++) = mColorMapDepth;
00681 *(dst++) = mXOffsetLo;
00682 *(dst++) = mXOffsetHi;
00683 *(dst++) = mYOffsetLo;
00684 *(dst++) = mYOffsetHi;
00685 *(dst++) = mWidthLo;
00686 *(dst++) = mWidthHi;
00687 *(dst++) = mHeightLo;
00688 *(dst++) = mHeightHi;
00689 *(dst++) = mPixelSize;
00690 *(dst++) =
00691 ((mInterleave & 3) << 5) |
00692 ((mOriginTopBit & 1) << 4) |
00693 ((mOriginRightBit & 1) << 3) |
00694 ((mAttributeBits & 0xF) << 0);
00695
00696
00697 const U8* src = raw_image->getData();
00698 llassert( dst == getData() + mDataOffset );
00699 S32 i = 0;
00700 S32 j = 0;
00701 switch( getComponents() )
00702 {
00703 case 1:
00704 memcpy( dst, src, bytes_per_pixel * pixels );
00705 break;
00706
00707 case 2:
00708 while( pixels-- )
00709 {
00710 dst[i + 0] = src[j + 0];
00711 dst[i + 1] = src[j + 0];
00712 dst[i + 2] = src[j + 0];
00713 dst[i + 3] = src[j + 1];
00714 i += 4;
00715 j += 2;
00716 }
00717 break;
00718
00719 case 3:
00720 while( pixels-- )
00721 {
00722 dst[i + 0] = src[i + 2];
00723 dst[i + 1] = src[i + 1];
00724 dst[i + 2] = src[i + 0];
00725 i += 3;
00726 }
00727 break;
00728
00729 case 4:
00730 while( pixels-- )
00731 {
00732 dst[i + 0] = src[i + 2];
00733 dst[i + 1] = src[i + 1];
00734 dst[i + 2] = src[i + 0];
00735 dst[i + 3] = src[i + 3];
00736 i += 4;
00737 }
00738 break;
00739 }
00740
00741 return TRUE;
00742 }
00743
00744 BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque )
00745 {
00746 llassert( getComponents() == 4 );
00747 alpha_opaque = TRUE;
00748
00749 U8* dst = raw_image->getData();
00750 U32* dst_pixels = (U32*) dst;
00751
00752 U8* src = getData() + mDataOffset;
00753 U8* last_src = src + getDataSize();
00754
00755 U32 rgba;
00756 U8* rgba_byte_p = (U8*) &rgba;
00757
00758 U32* last_dst_pixel = dst_pixels + getHeight() * getWidth() - 1;
00759 while( dst_pixels <= last_dst_pixel )
00760 {
00761
00762
00763 if (src >= last_src)
00764 return FALSE;
00765
00766 U8 block_header_byte = *src;
00767 src++;
00768
00769 U32 block_pixel_count = (block_header_byte & 0x7F) + 1;
00770 if( block_header_byte & 0x80 )
00771 {
00772
00773
00774 if (src + 3 >= last_src)
00775 return FALSE;
00776
00777 rgba_byte_p[0] = src[2];
00778 rgba_byte_p[1] = src[1];
00779 rgba_byte_p[2] = src[0];
00780 rgba_byte_p[3] = src[3];
00781 if (rgba_byte_p[3] != 255)
00782 {
00783 alpha_opaque = FALSE;
00784 }
00785
00786 src += 4;
00787 register U32 value = rgba;
00788 do
00789 {
00790 *dst_pixels = value;
00791 dst_pixels++;
00792 block_pixel_count--;
00793 }
00794 while( block_pixel_count > 0 );
00795 }
00796 else
00797 {
00798
00799 do
00800 {
00801 if (src + 3 >= last_src)
00802 return FALSE;
00803
00804 ((U8*)dst_pixels)[0] = src[2];
00805 ((U8*)dst_pixels)[1] = src[1];
00806 ((U8*)dst_pixels)[2] = src[0];
00807 ((U8*)dst_pixels)[3] = src[3];
00808 if (src[3] != 255)
00809 {
00810 alpha_opaque = FALSE;
00811 }
00812 src += 4;
00813 dst_pixels++;
00814 block_pixel_count--;
00815 }
00816 while( block_pixel_count > 0 );
00817 }
00818 }
00819
00820 return TRUE;
00821 }
00822
00823 BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
00824 {
00825 llassert( getComponents() == 3 );
00826 llassert( mIs15Bit );
00827
00828 U8* dst = raw_image->getData();
00829 U8* src = getData() + mDataOffset;
00830
00831 U8* last_src = src + getDataSize();
00832 U8* last_dst = dst + getComponents() * (getHeight() * getWidth() - 1);
00833
00834 while( dst <= last_dst )
00835 {
00836
00837
00838 if (src >= last_src)
00839 return FALSE;
00840
00841 U8 block_header_byte = *src;
00842 src++;
00843
00844 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
00845 if( block_header_byte & 0x80 )
00846 {
00847
00848 do
00849 {
00850 if (src + 2 >= last_src)
00851 return FALSE;
00852
00853 decodeTruecolorPixel15( dst, src );
00854 dst += 3;
00855 block_pixel_count--;
00856 }
00857 while( block_pixel_count > 0 );
00858 src += 2;
00859 }
00860 else
00861 {
00862
00863 do
00864 {
00865 if (src + 2 >= last_src)
00866 return FALSE;
00867
00868 decodeTruecolorPixel15( dst, src );
00869 dst += 3;
00870 src += 2;
00871 block_pixel_count--;
00872 }
00873 while( block_pixel_count > 0 );
00874 }
00875 }
00876
00877 return TRUE;
00878 }
00879
00880
00881
00882 BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
00883 {
00884 llassert( getComponents() == 3 );
00885
00886 U8* dst = raw_image->getData();
00887 U8* src = getData() + mDataOffset;
00888
00889 U8* last_src = src + getDataSize();
00890 U8* last_dst = dst + getComponents() * (getHeight() * getWidth() - 1);
00891
00892 while( dst <= last_dst )
00893 {
00894
00895
00896 if (src >= last_src)
00897 return FALSE;
00898
00899 U8 block_header_byte = *src;
00900 src++;
00901
00902 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
00903 if( block_header_byte & 0x80 )
00904 {
00905
00906 do
00907 {
00908 if (src + 2 >= last_src)
00909 return FALSE;
00910 dst[0] = src[2];
00911 dst[1] = src[1];
00912 dst[2] = src[0];
00913 dst += 3;
00914 block_pixel_count--;
00915 }
00916 while( block_pixel_count > 0 );
00917 src += 3;
00918 }
00919 else
00920 {
00921
00922 do
00923 {
00924 if (src + 2 >= last_src)
00925 return FALSE;
00926
00927 dst[0] = src[2];
00928 dst[1] = src[1];
00929 dst[2] = src[0];
00930 dst += 3;
00931 src += 3;
00932 block_pixel_count--;
00933 }
00934 while( block_pixel_count > 0 );
00935 }
00936 }
00937
00938 return TRUE;
00939 }
00940
00941
00942 BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
00943 {
00944 llassert( getComponents() == 1 );
00945
00946 U8* dst = raw_image->getData();
00947 U8* src = getData() + mDataOffset;
00948
00949 U8* last_src = src + getDataSize();
00950 U8* last_dst = dst + getHeight() * getWidth() - 1;
00951
00952 while( dst <= last_dst )
00953 {
00954
00955
00956 if (src >= last_src)
00957 return FALSE;
00958
00959 U8 block_header_byte = *src;
00960 src++;
00961
00962 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
00963 if( block_header_byte & 0x80 )
00964 {
00965 if (src >= last_src)
00966 return FALSE;
00967
00968
00969 memset( dst, *src, block_pixel_count );
00970 dst += block_pixel_count;
00971 src++;
00972 }
00973 else
00974 {
00975
00976 do
00977 {
00978 if (src >= last_src)
00979 return FALSE;
00980
00981 *dst = *src;
00982 dst++;
00983 src++;
00984 block_pixel_count--;
00985 }
00986 while( block_pixel_count > 0 );
00987 }
00988 }
00989
00990 return TRUE;
00991 }
00992
00993
00994
00995
00996 BOOL LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight )
00997 {
00998 llassert_always(raw_image);
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016 if (!getData() || (0 == getDataSize()))
01017 {
01018 setLastError("LLImageTGA trying to decode an image with no data!");
01019 return FALSE;
01020 }
01021
01022
01023 if( (getComponents() != 1) || (mImageType != 11) || mOriginTopBit || mOriginRightBit )
01024 {
01025 llerrs << "LLImageTGA trying to alpha-gradient process an image that's not a standard RLE, one component image" << llendl;
01026 return FALSE;
01027 }
01028
01029 raw_image->resize(getWidth(), getHeight(), getComponents());
01030
01031 U8* dst = raw_image->getData();
01032 U8* src = getData() + mDataOffset;
01033 U8* last_dst = dst + getHeight() * getWidth() - 1;
01034
01035 if( domain > 0 )
01036 {
01037
01038 const S32 LUT_LEN = 256;
01039 U8 lut[LUT_LEN];
01040 S32 i;
01041
01042 F32 scale = 1.f / domain;
01043 F32 offset = (1.f - domain) * llclampf( 1.f - weight );
01044 F32 bias = -(scale * offset);
01045
01046 for( i = 0; i < LUT_LEN; i++ )
01047 {
01048 lut[i] = (U8)llclampb( 255.f * ( i/255.f * scale + bias ) );
01049 }
01050
01051 while( dst <= last_dst )
01052 {
01053
01054 U8 block_header_byte = *src;
01055 src++;
01056
01057 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
01058 if( block_header_byte & 0x80 )
01059 {
01060
01061 memset( dst, lut[ *src ], block_pixel_count );
01062 dst += block_pixel_count;
01063 src++;
01064 }
01065 else
01066 {
01067
01068 do
01069 {
01070 *dst = lut[ *src ];
01071 dst++;
01072 src++;
01073 block_pixel_count--;
01074 }
01075 while( block_pixel_count > 0 );
01076 }
01077 }
01078 }
01079 else
01080 {
01081
01082 const U8 threshold = (U8)(0xFF * llclampf( 1.f - weight ));
01083
01084 while( dst <= last_dst )
01085 {
01086
01087 U8 block_header_byte = *src;
01088 src++;
01089
01090 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
01091 if( block_header_byte & 0x80 )
01092 {
01093
01094 memset( dst, ((*src >= threshold) ? 0xFF : 0), block_pixel_count );
01095 dst += block_pixel_count;
01096 src++;
01097 }
01098 else
01099 {
01100
01101 do
01102 {
01103 *dst = (*src >= threshold) ? 0xFF : 0;
01104 dst++;
01105 src++;
01106 block_pixel_count--;
01107 }
01108 while( block_pixel_count > 0 );
01109 }
01110 }
01111 }
01112 return TRUE;
01113 }
01114
01115
01116 bool LLImageTGA::loadFile( const LLString& path )
01117 {
01118 S32 len = path.size();
01119 if( len < 5 )
01120 {
01121 return false;
01122 }
01123
01124 LLString extension = path.substr( len - 4, 4 );
01125 LLString::toLower(extension);
01126 if( ".tga" != extension )
01127 {
01128 return false;
01129 }
01130
01131 FILE* file = LLFile::fopen(path.c_str(), "rb");
01132 if( !file )
01133 {
01134 llwarns << "Couldn't open file " << path << llendl;
01135 return false;
01136 }
01137
01138 S32 file_size = 0;
01139 if (!fseek(file, 0, SEEK_END))
01140 {
01141 file_size = ftell(file);
01142 fseek(file, 0, SEEK_SET);
01143 }
01144
01145 U8* buffer = allocateData(file_size);
01146 S32 bytes_read = fread(buffer, 1, file_size, file);
01147 if( bytes_read != file_size )
01148 {
01149 deleteData();
01150 llwarns << "Couldn't read file " << path << llendl;
01151 return false;
01152 }
01153
01154 fclose( file );
01155
01156 if( !updateData() )
01157 {
01158 llwarns << "Couldn't decode file " << path << llendl;
01159 deleteData();
01160 return false;
01161 }
01162 return true;
01163 }
01164
01165