llimagetga.cpp

Go to the documentation of this file.
00001 
00031 #include "linden_common.h"
00032 
00033 #include "llimagetga.h"
00034 #include "llerror.h"
00035 #include "llmath.h"
00036 
00037 // For expanding 5-bit pixel values to 8-bit with best rounding
00038 // static
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     // We expand 5 bit data to 8 bit sample width.
00050     // The format of the 16-bit (LSB first) input word is
00051     // xRRRRRGGGGGBBBBB
00052         U32 t = U32(src[0]) + (U32(src[1]) << 8);
00053     dst[2] = s5to8bits[t & 0x1F];  // blue
00054     t >>= 5;
00055     dst[1] = s5to8bits[t & 0x1F];  // green
00056     t >>= 5;
00057     dst[0] = s5to8bits[t & 0x1F];  // red
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         // Check to make sure that this instance has been initialized with data
00091         if (!getData() || (0 == getDataSize()))
00092         {
00093                 setLastError("LLImageTGA uninitialized");
00094                 return FALSE;
00095         }
00096         
00097         // Pull image information from the header...
00098         U8      flags;
00099         U8      junk[256];
00100 
00101         /****************************************************************************
00102         **
00103         **      For more information about the original Truevision TGA(tm) file format,
00104         **      or for additional information about the new extensions to the
00105         **      Truevision TGA file, refer to the "Truevision TGA File Format
00106         **      Specification Version 2.0" available from Truevision or your
00107         **      Truevision dealer.
00108         **
00109         **  FILE STRUCTURE FOR THE ORIGINAL TRUEVISION TGA FILE                         
00110         **        FIELD 1 :     NUMBER OF CHARACTERS IN ID FIELD (1 BYTES)      
00111         **        FIELD 2 :     COLOR MAP TYPE (1 BYTES)                        
00112         **        FIELD 3 :     IMAGE TYPE CODE (1 BYTES)                       
00113         **                                      = 0     NO IMAGE DATA INCLUDED          
00114         **                                      = 1     UNCOMPRESSED, COLOR-MAPPED IMAGE
00115         **                                      = 2     UNCOMPRESSED, TRUE-COLOR IMAGE  
00116         **                                      = 3     UNCOMPRESSED, BLACK AND WHITE IMAGE
00117         **                                      = 9     RUN-LENGTH ENCODED COLOR-MAPPED IMAGE
00118         **                                      = 10 RUN-LENGTH ENCODED TRUE-COLOR IMAGE
00119         **                                      = 11 RUN-LENGTH ENCODED BLACK AND WHITE IMAGE
00120         **        FIELD 4 :     COLOR MAP SPECIFICATION (5 BYTES)               
00121         **                              4.1 : COLOR MAP ORIGIN (2 BYTES)        
00122         **                              4.2 : COLOR MAP LENGTH (2 BYTES)        
00123         **                              4.3 : COLOR MAP ENTRY SIZE (2 BYTES)    
00124         **        FIELD 5 :     IMAGE SPECIFICATION (10 BYTES)                  
00125         **                              5.1 : X-ORIGIN OF IMAGE (2 BYTES)       
00126         **                              5.2 : Y-ORIGIN OF IMAGE (2 BYTES)       
00127         **                              5.3 : WIDTH OF IMAGE (2 BYTES)          
00128         **                              5.4 : HEIGHT OF IMAGE (2 BYTES)         
00129         **                              5.5 : IMAGE PIXEL SIZE (1 BYTE)         
00130         **                              5.6 : IMAGE DESCRIPTOR BYTE (1 BYTE)    
00131         **        FIELD 6 :     IMAGE ID FIELD (LENGTH SPECIFIED BY FIELD 1)    
00132         **        FIELD 7 :     COLOR MAP DATA (BIT WIDTH SPECIFIED BY FIELD 4.3 AND
00133         **                              NUMBER OF COLOR MAP ENTRIES SPECIFIED IN FIELD 4.2)
00134         **        FIELD 8 :     IMAGE DATA FIELD (WIDTH AND HEIGHT SPECIFIED IN
00135         **                              FIELD 5.3 AND 5.4)                              
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                 // No image data included in file
00166                 setLastError("Unable to load file.  TGA file contains no image data.");
00167                 return FALSE;
00168         case 1:
00169                 // Colormapped uncompressed
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                 // Truecolor uncompressed
00178                 break;
00179         case 3:
00180                 // Monochrome uncompressed
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                 // Colormapped, RLE
00189                 break;
00190         case 10:
00191                 // Truecolor, RLE
00192                 break;
00193         case 11:
00194                 // Monochrome, RLE
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         // discard the ID field, if any
00207         if (mIDLength)
00208         {
00209                 memcpy(junk, getData()+mDataOffset, mIDLength); /* Flawfinder: ignore */
00210                 mDataOffset += mIDLength;
00211         }
00212         
00213         // check to see if there's a colormap since even rgb files can have them
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                 // Note: although it's legal for TGA files to have color maps and not use them
00241                 // (some programs actually do this and use the color map for other ends), we'll
00242                 // only allocate memory for one if _we_ intend to use it.
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 );  /* Flawfinder: ignore */
00252                 }
00253 
00254                 mDataOffset += color_map_bytes;
00255         }
00256 
00257         // heights are read as bytes to prevent endian problems
00258         S32 height = (S32(mHeightHi) << 8) + mHeightLo;
00259         S32 width = (S32(mWidthHi) << 8) + mWidthLo;
00260 
00261         // make sure that it's a pixel format that we understand
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 //              Don't enforce this.  ACDSee doesn't bother to set the attributes bits correctly. Arrgh!
00281 //              if( mAttributeBits != 8 )
00282 //              {
00283 //                      setLastError("Unable to load file. 32 bit TGA image does not have 8 bits of alpha.");
00284 //                      return FALSE;
00285 //              }
00286                 mAttributeBits = 8;
00287                 break;
00288         case 15:
00289         case 16:
00290                 components = 3;
00291                 mIs15Bit = TRUE;  // 16th bit is used for Targa hardware interupts and is ignored.
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         // Check to make sure that this instance has been initialized with data
00310         if (!getData() || (0 == getDataSize()))
00311         {
00312                 setLastError("LLImageTGA trying to decode an image with no data!");
00313                 return FALSE;
00314         }
00315 
00316         // Copy everything after the header.
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                                 // alpha was entirely opaque
00375                                 // convert to 24 bit image
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                         // alpha was entirely opaque
00391                         // convert to 24 bit image
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                 // This works because the Targa definition requires that RLE blocks never
00402                 // encode pixels from more than one scanline.
00403                 // (On the other hand, it's not as fast as writing separate flipped versions as 
00404                 // we did with TruecolorNonRle.)
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         // Origin is the bottom left
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                         // Our data is stored in RGBA.  TGA stores them as BGRA (little-endian ARGB)
00426                         dst[0] = src[2]; // Red
00427                         dst[1] = src[1]; // Green
00428                         dst[2] = src[0]; // Blue
00429                         dst[3] = src[3]; // Alpha
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]; // Red
00454                                 dst[1] = src[1]; // Green
00455                                 dst[2] = src[0]; // Blue
00456                                 dst += 3;
00457                                 src += 3;
00458                         }
00459                 }
00460         }
00461         else if (getComponents() == 1)
00462         {
00463                 memcpy(dst, src, pixels);       /* Flawfinder: ignore */
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 ];        // Red
00485         dst[1] = mColorMap[ index + 1 ];        // Green
00486         dst[2] = mColorMap[ index + 0 ];        // Blue
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 ];        // Red
00493         dst[1] = mColorMap[ index + 1 ];        // Green
00494         dst[2] = mColorMap[ index + 0 ];        // Blue
00495         dst[3] = mColorMap[ index + 3 ];        // Alpha
00496 }
00497 
00498 
00499 BOOL LLImageTGA::decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
00500 {
00501         // If flipped, origin is the top left.  Need to reverse the order of the rows.
00502         // Otherwise the origin is the bottom left.
00503 
00504         if( 8 != mPixelSize )
00505         {
00506                 return FALSE;
00507         }
00508 
00509         U8* src = getData() + mDataOffset;
00510         U8* dst = raw_image->getData(); // start from the top
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                         // Read RLE block header
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                                 // Encoded (duplicate-pixel) block
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                                 // Unencoded block
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;               // start from the bottom
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         // Data from header
00603         mIDLength = 0;          // Length of identifier string
00604         mColorMapType = 0;      // 0 = No Map
00605 
00606         // Supported: 2 = Uncompressed true color, 3 = uncompressed monochrome without colormap
00607         switch( getComponents() )
00608         {
00609         case 1:
00610                 mImageType = 3;         
00611                 break;
00612         case 2:  // Interpret as intensity plus alpha
00613         case 3:
00614         case 4:
00615                 mImageType = 2;         
00616                 break;
00617         default:
00618                 return FALSE;
00619         }
00620 
00621         // Color map stuff (unsupported)
00622         mColorMapIndexLo = 0;           // First color map entry (low order byte)
00623         mColorMapIndexHi = 0;           // First color map entry (high order byte)
00624         mColorMapLengthLo = 0;          // Color map length (low order byte)
00625         mColorMapLengthHi = 0;          // Color map length (high order byte)
00626         mColorMapDepth = 0;     // Size of color map entry (15, 16, 24, or 32 bits)
00627 
00628         // Image offset relative to origin.
00629         mXOffsetLo = 0;         // X offset from origin (low order byte)
00630         mXOffsetHi = 0;         // X offset from origin (hi order byte)
00631         mYOffsetLo = 0;         // Y offset from origin (low order byte)
00632         mYOffsetHi = 0;         // Y offset from origin (hi order byte)
00633 
00634         // Height and width
00635         mWidthLo = U8(getWidth() & 0xFF);                       // Width (low order byte)
00636         mWidthHi = U8((getWidth() >> 8) & 0xFF);        // Width (hi order byte)
00637         mHeightLo = U8(getHeight() & 0xFF);                     // Height (low order byte)
00638         mHeightHi = U8((getHeight() >> 8) & 0xFF);      // Height (hi order byte)
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:  // Interpret as intensity plus alpha.  Store as RGBA.
00650         case 4:
00651                 bytes_per_pixel = 4;            
00652                 break;
00653         default:
00654                 return FALSE;
00655         }
00656         mPixelSize = U8(bytes_per_pixel * 8);           // 8, 16, 24, 32 bits per pixel
00657 
00658         mAttributeBits = (4 == bytes_per_pixel) ? 8 : 0;        // 4 bits: number of attribute bits (alpha) per pixel
00659         mOriginRightBit = 0;    // 1 bit: origin, 0 = left, 1 = right
00660         mOriginTopBit = 0;      // 1 bit: origin, 0 = bottom, 1 = top
00661         mInterleave = 0;        // 2 bits: interleaved flag, 0 = none, 1 = interleaved 2, 2 = interleaved 4
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; // Offset from start of data to the actual header.
00667 
00668         S32 pixels = getWidth() * getHeight();
00669         S32 datasize = mDataOffset + bytes_per_pixel * pixels;
00670         U8* dst = allocateData(datasize);
00671 
00672         // Write header
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         // Write pixels
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 );   /* Flawfinder: ignore */
00705                 break;
00706 
00707         case 2:
00708                 while( pixels-- )
00709                 {
00710                         dst[i + 0] = src[j + 0];        // intensity
00711                         dst[i + 1] = src[j + 0];        // intensity
00712                         dst[i + 2] = src[j + 0];        // intensity
00713                         dst[i + 3] = src[j + 1];        // alpha
00714                         i += 4;
00715                         j += 2;
00716                 }
00717                 break;
00718 
00719         case 3:
00720                 while( pixels-- )
00721                 {
00722                         dst[i + 0] = src[i + 2];        // blue
00723                         dst[i + 1] = src[i + 1];        // green
00724                         dst[i + 2] = src[i + 0];        // red
00725                         i += 3;
00726                 }
00727                 break;
00728 
00729         case 4:
00730                 while( pixels-- )
00731                 {
00732                         dst[i + 0] = src[i + 2];        // blue
00733                         dst[i + 1] = src[i + 1];        // green
00734                         dst[i + 2] = src[i + 0];        // red
00735                         dst[i + 3] = src[i + 3];        // alpha
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                 // Read RLE block header
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                         // Encoded (duplicate-pixel) block
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                         // Unencoded block
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                 // Read RLE block header
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                         // Encoded (duplicate-pixel) block
00848                         do
00849                         {
00850                                 if (src + 2 >= last_src)
00851                                         return FALSE;
00852                                 
00853                                 decodeTruecolorPixel15( dst, src );   // slow
00854                                 dst += 3;
00855                                 block_pixel_count--;
00856                         }
00857                         while( block_pixel_count > 0 );
00858                         src += 2;
00859                 }
00860                 else 
00861                 {
00862                         // Unencoded block
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                 // Read RLE block header
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                         // Encoded (duplicate-pixel) block
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                         // Unencoded block
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                 // Read RLE block header
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                         // Encoded (duplicate-pixel) block
00969                         memset( dst, *src, block_pixel_count );
00970                         dst += block_pixel_count;
00971                         src++;
00972                 }
00973                 else 
00974                 {
00975                         // Unencoded block
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 // Decoded and process the image for use in avatar gradient masks.
00995 // Processing happens during the decode for speed.
00996 BOOL LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight )
00997 {
00998         llassert_always(raw_image);
00999         
01000         // "Domain" isn't really the right word.  It refers to the width of the 
01001         // ramp portion of the function that relates input and output pixel values.
01002         // A domain of 0 gives a step function.
01003         // 
01004         //   |                      /----------------
01005         //  O|                     / |
01006         //  u|                    /  |
01007         //  t|                   /   |
01008         //      p|------------------/    |
01009         //  u|                  |    | 
01010         //  t|<---------------->|<-->|
01011         //       |  "offset"         "domain"
01012         //   |
01013         // --+---Input--------------------------------
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         // Only works for unflipped monochrome RLE images
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                 // Process using a look-up table (lut)
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                         // Read RLE block header
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                                 // Encoded (duplicate-pixel) block
01061                                 memset( dst, lut[ *src ], block_pixel_count );
01062                                 dst += block_pixel_count;
01063                                 src++;
01064                         }
01065                         else 
01066                         {
01067                                 // Unencoded block
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                 // Process using a simple comparison agains a threshold
01082                 const U8 threshold = (U8)(0xFF * llclampf( 1.f - weight ));
01083 
01084                 while( dst <= last_dst )
01085                 {
01086                         // Read RLE block header
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                                 // Encoded (duplicate-pixel) block
01094                                 memset( dst, ((*src >= threshold) ? 0xFF : 0), block_pixel_count );
01095                                 dst += block_pixel_count;
01096                                 src++;
01097                         }
01098                         else 
01099                         {
01100                                 // Unencoded block
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 // Reads a .tga file and creates an LLImageTGA with its data.
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         LLFILE* file = LLFile::fopen(path.c_str(), "rb");       /* Flawfinder: ignore */
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 

Generated on Fri May 16 08:32:11 2008 for SecondLife by  doxygen 1.5.5