llimage.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include "llimage.h"
00035 
00036 #include "llmath.h"
00037 #include "v4coloru.h"
00038 #include "llmemtype.h"
00039 
00040 #include "llimagebmp.h"
00041 #include "llimagetga.h"
00042 #include "llimagej2c.h"
00043 #if JPEG_SUPPORT
00044 #include "llimagejpeg.h"
00045 #endif
00046 #include "llimagedxt.h"
00047 
00048 //---------------------------------------------------------------------------
00049 // LLImageBase
00050 //---------------------------------------------------------------------------
00051 
00052 LLImageBase::LLImageBase()
00053         : mData(NULL),
00054           mDataSize(0),
00055           mWidth(0),
00056           mHeight(0),
00057           mComponents(0),
00058           mMemType(LLMemType::MTYPE_IMAGEBASE)
00059 {
00060 }
00061 
00062 // virtual
00063 LLImageBase::~LLImageBase()
00064 {
00065         deleteData(); // virtual
00066 }
00067 
00068 // virtual
00069 void LLImageBase::dump()
00070 {
00071         llinfos << "LLImageBase mComponents " << mComponents
00072                 << " mData " << mData
00073                 << " mDataSize " << mDataSize
00074                 << " mWidth " << mWidth
00075                 << " mHeight " << mHeight
00076                 << llendl;
00077 }
00078 
00079 // virtual
00080 void LLImageBase::sanityCheck()
00081 {
00082         if (mWidth > MAX_IMAGE_SIZE
00083                 || mHeight > MAX_IMAGE_SIZE
00084                 || mDataSize > (S32)MAX_IMAGE_DATA_SIZE
00085                 || mComponents > (S8)MAX_IMAGE_COMPONENTS
00086                 )
00087         {
00088                 llerrs << "Failed LLImageBase::sanityCheck "
00089                            << "width " << mWidth
00090                            << "height " << mHeight
00091                            << "datasize " << mDataSize
00092                            << "components " << mComponents
00093                            << "data " << mData
00094                            << llendl;
00095         }
00096 }
00097 
00098 LLString LLImageBase::sLastErrorMessage;
00099 BOOL LLImageBase::sSizeOverride = FALSE;
00100 
00101 BOOL LLImageBase::setLastError(const LLString& message, const LLString& filename) 
00102 {
00103         sLastErrorMessage = message;
00104         if (filename != "")
00105         {
00106                 sLastErrorMessage += LLString(" FILE:");
00107                 sLastErrorMessage += filename;
00108         }
00109         llwarns << sLastErrorMessage << llendl;
00110         return FALSE;
00111 }
00112 
00113 // virtual
00114 void LLImageBase::deleteData()
00115 {
00116         delete[] mData;
00117         mData = NULL;
00118         mDataSize = 0;
00119 }
00120 
00121 // virtual
00122 U8* LLImageBase::allocateData(S32 size)
00123 {
00124         LLMemType mt1((LLMemType::EMemType)mMemType);
00125         
00126         if (size < 0)
00127         {
00128                 size = mWidth * mHeight * mComponents;
00129                 if (size <= 0)
00130                 {
00131                         llerrs << llformat("LLImageBase::allocateData called with bad dimentions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl;
00132                 }
00133         }
00134         else if (size <= 0 || (size > 4096*4096*16 && sSizeOverride == FALSE))
00135         {
00136                 llerrs << "LLImageBase::allocateData: bad size: " << size << llendl;
00137         }
00138         
00139         resetLastError();
00140 
00141         if (!mData || size != mDataSize)
00142         {
00143                 deleteData(); // virtual
00144                 mData = new U8[size];
00145                 if (!mData)
00146                 {
00147                         llerrs << "allocate image data: " << size << llendl;
00148                 }
00149                 mDataSize = size;
00150         }
00151 
00152         return mData;
00153 }
00154 
00155 // virtual
00156 U8* LLImageBase::reallocateData(S32 size)
00157 {
00158         LLMemType mt1((LLMemType::EMemType)mMemType);
00159         U8 *new_datap = new U8[size];
00160         if (!new_datap)
00161         {
00162                 llwarns << "Out of memory in LLImageBase::reallocateData" << llendl;
00163                 return 0;
00164         }
00165         if (mData)
00166         {
00167                 S32 bytes = llmin(mDataSize, size);
00168                 memcpy(new_datap, mData, bytes);        /* Flawfinder: ignore */
00169                 delete[] mData;
00170         }
00171         mData = new_datap;
00172         mDataSize = size;
00173         return mData;
00174 }
00175 
00176 
00177 void LLImageBase::setSize(S32 width, S32 height, S32 ncomponents)
00178 {
00179         mWidth = width;
00180         mHeight = height;
00181         mComponents = ncomponents;
00182 }
00183 
00184 U8* LLImageBase::allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 size)
00185 {
00186         setSize(width, height, ncomponents);
00187         return allocateData(size); // virtual
00188 }
00189 
00190 //---------------------------------------------------------------------------
00191 // LLImageRaw
00192 //---------------------------------------------------------------------------
00193 
00194 S32 LLImageRaw::sGlobalRawMemory = 0;
00195 S32 LLImageRaw::sRawImageCount = 0;
00196 
00197 LLImageRaw::LLImageRaw()
00198         : LLImageBase()
00199 {
00200         mMemType = LLMemType::MTYPE_IMAGERAW;
00201         ++sRawImageCount;
00202 }
00203 
00204 LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components)
00205         : LLImageBase()
00206 {
00207         mMemType = LLMemType::MTYPE_IMAGERAW;
00208         llassert( S32(width) * S32(height) * S32(components) <= MAX_IMAGE_DATA_SIZE );
00209         allocateDataSize(width, height, components);
00210         ++sRawImageCount;
00211 }
00212 
00213 LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
00214         : LLImageBase()
00215 {
00216         mMemType = LLMemType::MTYPE_IMAGERAW;
00217         allocateDataSize(width, height, components);
00218         memcpy(getData(), data, width*height*components);
00219         ++sRawImageCount;
00220 }
00221 
00222 LLImageRaw::LLImageRaw(const LLString &filename, bool j2c_lowest_mip_only)
00223         : LLImageBase()
00224 {
00225         createFromFile(filename, j2c_lowest_mip_only);
00226 }
00227 
00228 LLImageRaw::~LLImageRaw()
00229 {
00230         // NOTE: ~LLimageBase() call to deleteData() calls LLImageBase::deleteData()
00231         //        NOT LLImageRaw::deleteData()
00232         deleteData();
00233         --sRawImageCount;
00234 }
00235 
00236 // virtual
00237 U8* LLImageRaw::allocateData(S32 size)
00238 {
00239         U8* res = LLImageBase::allocateData(size);
00240         sGlobalRawMemory += getDataSize();
00241         return res;
00242 }
00243 
00244 // virtual
00245 U8* LLImageRaw::reallocateData(S32 size)
00246 {
00247         sGlobalRawMemory -= getDataSize();
00248         U8* res = LLImageBase::reallocateData(size);
00249         sGlobalRawMemory += getDataSize();
00250         return res;
00251 }
00252 
00253 // virtual
00254 void LLImageRaw::deleteData()
00255 {
00256         sGlobalRawMemory -= getDataSize();
00257         LLImageBase::deleteData();
00258 }
00259 
00260 BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
00261 {
00262         if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components))
00263         {
00264                 return TRUE;
00265         }
00266         // Reallocate the data buffer.
00267         deleteData();
00268 
00269         allocateDataSize(width,height,components);
00270 
00271         return TRUE;
00272 }
00273 
00274 U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const
00275 {
00276         LLMemType mt1((LLMemType::EMemType)mMemType);
00277         U8 *data = new U8[width*height*getComponents()];
00278 
00279         // Should do some simple bounds checking
00280         if (!data)
00281         {
00282                 llerrs << "Out of memory in LLImageRaw::getSubImage" << llendl;
00283                 return NULL;
00284         }
00285 
00286         U32 i;
00287         for (i = y_pos; i < y_pos+height; i++)
00288         {
00289                 memcpy(data + i*width*getComponents(),          /* Flawfinder: ignore */
00290                                 getData() + ((y_pos + i)*getWidth() + x_pos)*getComponents(), getComponents()*width);
00291         }
00292         return data;
00293 }
00294 
00295 BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
00296                                                          const U8 *data, U32 stride, BOOL reverse_y)
00297 {
00298         if (!getData())
00299         {
00300                 return FALSE;
00301         }
00302         if (!data)
00303         {
00304                 return FALSE;
00305         }
00306 
00307         // Should do some simple bounds checking
00308 
00309         U32 i;
00310         for (i = 0; i < height; i++)
00311         {
00312                 const U32 row = reverse_y ? height - 1 - i : i;
00313                 const U32 from_offset = row * ((stride == 0) ? width*getComponents() : stride);
00314                 const U32 to_offset = (y_pos + i)*getWidth() + x_pos;
00315                 memcpy(getData() + to_offset*getComponents(),           /* Flawfinder: ignore */
00316                                 data + from_offset, getComponents()*width);
00317         }
00318 
00319         return TRUE;
00320 }
00321 
00322 void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a)
00323 {
00324         llassert( getComponents() <= 4 );
00325         // This is fairly bogus, but it'll do for now.
00326         U8 *pos = getData();
00327         U32 x, y;
00328         for (x = 0; x < getWidth(); x++)
00329         {
00330                 for (y = 0; y < getHeight(); y++)
00331                 {
00332                         *pos = r;
00333                         pos++;
00334                         if (getComponents() == 1)
00335                         {
00336                                 continue;
00337                         }
00338                         *pos = g;
00339                         pos++;
00340                         if (getComponents() == 2)
00341                         {
00342                                 continue;
00343                         }
00344                         *pos = b;
00345                         pos++;
00346                         if (getComponents() == 3)
00347                         {
00348                                 continue;
00349                         }
00350                         *pos = a;
00351                         pos++;
00352                 }
00353         }
00354 }
00355 
00356 // Reverses the order of the rows in the image
00357 void LLImageRaw::verticalFlip()
00358 {
00359         LLMemType mt1((LLMemType::EMemType)mMemType);
00360         S32 row_bytes = getWidth() * getComponents();
00361         U8* line_buffer = new U8[row_bytes];
00362         if (!line_buffer )
00363         {
00364                 llerrs << "Out of memory in LLImageRaw::verticalFlip()" << llendl;
00365                 return;
00366         }
00367         S32 mid_row = getHeight() / 2;
00368         for( S32 row = 0; row < mid_row; row++ )
00369         {
00370                 U8* row_a_data = getData() + row * row_bytes;
00371                 U8* row_b_data = getData() + (getHeight() - 1 - row) * row_bytes;
00372                 memcpy( line_buffer, row_a_data,  row_bytes );  /* Flawfinder: ignore */
00373                 memcpy( row_a_data,  row_b_data,  row_bytes );  /* Flawfinder: ignore */
00374                 memcpy( row_b_data,  line_buffer, row_bytes );  /* Flawfinder: ignore */
00375         }
00376         delete[] line_buffer;
00377 }
00378 
00379 
00380 void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
00381 {
00382         // Find new sizes
00383         S32 new_width = MIN_IMAGE_SIZE;
00384         S32 new_height = MIN_IMAGE_SIZE;
00385 
00386         while( (new_width < getWidth()) && (new_width < max_dim) )
00387         {
00388                 new_width <<= 1;
00389         }
00390 
00391         while( (new_height < getHeight()) && (new_height < max_dim) )
00392         {
00393                 new_height <<= 1;
00394         }
00395 
00396         scale( new_width, new_height, scale_image );
00397 }
00398 
00399 void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image)
00400 {
00401         // Find new sizes
00402         S32 new_width = max_dim;
00403         S32 new_height = max_dim;
00404 
00405         while( (new_width > getWidth()) && (new_width > MIN_IMAGE_SIZE) )
00406         {
00407                 new_width >>= 1;
00408         }
00409 
00410         while( (new_height > getHeight()) && (new_height > MIN_IMAGE_SIZE) )
00411         {
00412                 new_height >>= 1;
00413         }
00414 
00415         scale( new_width, new_height, scale_image );
00416 }
00417 
00418 void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
00419 {
00420         // Strong bias towards rounding down (to save bandwidth)
00421         // No bias would mean THRESHOLD == 1.5f;
00422         const F32 THRESHOLD = 1.75f; 
00423 
00424         // Find new sizes
00425         S32 larger_w = max_dim; // 2^n >= mWidth
00426         S32 smaller_w = max_dim;        // 2^(n-1) <= mWidth
00427         while( (smaller_w > getWidth()) && (smaller_w > MIN_IMAGE_SIZE) )
00428         {
00429                 larger_w = smaller_w;
00430                 smaller_w >>= 1;
00431         }
00432         S32 new_width = ( (F32)getWidth() / smaller_w > THRESHOLD ) ? larger_w : smaller_w;
00433 
00434 
00435         S32 larger_h = max_dim; // 2^m >= mHeight
00436         S32 smaller_h = max_dim;        // 2^(m-1) <= mHeight
00437         while( (smaller_h > getHeight()) && (smaller_h > MIN_IMAGE_SIZE) )
00438         {
00439                 larger_h = smaller_h;
00440                 smaller_h >>= 1;
00441         }
00442         S32 new_height = ( (F32)getHeight() / smaller_h > THRESHOLD ) ? larger_h : smaller_h;
00443 
00444 
00445         scale( new_width, new_height );
00446 }
00447 
00448 
00449 
00450 
00451 // Calculates (U8)(255*(a/255.f)*(b/255.f) + 0.5f).  Thanks, Jim Blinn!
00452 inline U8 LLImageRaw::fastFractionalMult( U8 a, U8 b )
00453 {
00454         U32 i = a * b + 128;
00455         return U8((i + (i>>8)) >> 8);
00456 }
00457 
00458 
00459 void LLImageRaw::composite( LLImageRaw* src )
00460 {
00461         LLImageRaw* dst = this;  // Just for clarity.
00462 
00463         llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
00464         llassert( (3 == dst->getComponents()) || (4 == dst->getComponents()) );
00465 
00466         if( 3 == dst->getComponents() )
00467         {
00468                 if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
00469                 {
00470                         // No scaling needed
00471                         if( 3 == src->getComponents() )
00472                         {
00473                                 copyUnscaled( src );  // alpha is one so just copy the data.
00474                         }
00475                         else
00476                         {
00477                                 compositeUnscaled4onto3( src );
00478                         }
00479                 }
00480                 else
00481                 {
00482                         if( 3 == src->getComponents() )
00483                         {
00484                                 copyScaled( src );  // alpha is one so just copy the data.
00485                         }
00486                         else
00487                         {
00488                                 compositeScaled4onto3( src );
00489                         }
00490                 }
00491         }
00492         else
00493         {
00494                 // 4 == dst->mComponents
00495                 llassert(0); // not implemented yet.
00496         }
00497 }
00498 
00499 // Src and dst can be any size.  Src has 4 components.  Dst has 3 components.
00500 void LLImageRaw::compositeScaled4onto3(LLImageRaw* src)
00501 {
00502         LLMemType mt1((LLMemType::EMemType)mMemType);
00503         llinfos << "compositeScaled4onto3" << llendl;
00504 
00505         LLImageRaw* dst = this;  // Just for clarity.
00506 
00507         llassert( (4 == src->getComponents()) && (3 == dst->getComponents()) );
00508 
00509         // Vertical: scale but no composite
00510         S32 temp_data_size = src->getWidth() * dst->getHeight() * src->getComponents();
00511         U8* temp_buffer = new U8[ temp_data_size ];
00512         for( S32 col = 0; col < src->getWidth(); col++ )
00513         {
00514                 copyLineScaled( src->getData() + (src->getComponents() * col), temp_buffer + (src->getComponents() * col), src->getHeight(), dst->getHeight(), src->getWidth(), src->getWidth() );
00515         }
00516 
00517         // Horizontal: scale and composite
00518         for( S32 row = 0; row < dst->getHeight(); row++ )
00519         {
00520                 compositeRowScaled4onto3( temp_buffer + (src->getComponents() * src->getWidth() * row), dst->getData() + (dst->getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth() );
00521         }
00522 
00523         // Clean up
00524         delete[] temp_buffer;
00525 }
00526 
00527 
00528 // Src and dst are same size.  Src has 4 components.  Dst has 3 components.
00529 void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src )
00530 {
00531         /*
00532         //test fastFractionalMult()
00533         {
00534                 U8 i = 255;
00535                 U8 j = 255;
00536                 do
00537                 {
00538                         do
00539                         {
00540                                 llassert( fastFractionalMult(i, j) == (U8)(255*(i/255.f)*(j/255.f) + 0.5f) );
00541                         } while( j-- );
00542                 } while( i-- );
00543         }
00544         */
00545 
00546         LLImageRaw* dst = this;  // Just for clarity.
00547 
00548         llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
00549         llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
00550 
00551 
00552         U8* src_data = src->getData();
00553         U8* dst_data = dst->getData();
00554         S32 pixels = getWidth() * getHeight();
00555         while( pixels-- )
00556         {
00557                 U8 alpha = src_data[3];
00558                 if( alpha )
00559                 {
00560                         if( 255 == alpha )
00561                         {
00562                                 dst_data[0] = src_data[0];
00563                                 dst_data[1] = src_data[1];
00564                                 dst_data[2] = src_data[2];
00565                         }
00566                         else
00567                         {
00568 
00569                                 U8 transparency = 255 - alpha;
00570                                 dst_data[0] = fastFractionalMult( dst_data[0], transparency ) + fastFractionalMult( src_data[0], alpha );
00571                                 dst_data[1] = fastFractionalMult( dst_data[1], transparency ) + fastFractionalMult( src_data[1], alpha );
00572                                 dst_data[2] = fastFractionalMult( dst_data[2], transparency ) + fastFractionalMult( src_data[2], alpha );
00573                         }
00574                 }
00575 
00576                 src_data += 4;
00577                 dst_data += 3;
00578         }
00579 }
00580 
00581 // Fill the buffer with a constant color
00582 void LLImageRaw::fill( const LLColor4U& color )
00583 {
00584         S32 pixels = getWidth() * getHeight();
00585         if( 4 == getComponents() )
00586         {
00587                 U32* data = (U32*) getData();
00588                 for( S32 i = 0; i < pixels; i++ )
00589                 {
00590                         data[i] = color.mAll;
00591                 }
00592         }
00593         else
00594         if( 3 == getComponents() )
00595         {
00596                 U8* data = getData();
00597                 for( S32 i = 0; i < pixels; i++ )
00598                 {
00599                         data[0] = color.mV[0];
00600                         data[1] = color.mV[1];
00601                         data[2] = color.mV[2];
00602                         data += 3;
00603                 }
00604         }
00605 }
00606 
00607 
00608 
00609 
00610 // Src and dst can be any size.  Src and dst can each have 3 or 4 components.
00611 void LLImageRaw::copy(LLImageRaw* src)
00612 {
00613         LLImageRaw* dst = this;  // Just for clarity.
00614 
00615         llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
00616         llassert( (3 == dst->getComponents()) || (4 == dst->getComponents()) );
00617 
00618         if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
00619         {
00620                 // No scaling needed
00621                 if( src->getComponents() == dst->getComponents() )
00622                 {
00623                         copyUnscaled( src );
00624                 }
00625                 else
00626                 if( 3 == src->getComponents() )
00627                 {
00628                         copyUnscaled3onto4( src );
00629                 }
00630                 else
00631                 {
00632                         // 4 == src->getComponents()
00633                         copyUnscaled4onto3( src );
00634                 }
00635         }
00636         else
00637         {
00638                 // Scaling needed
00639                 // No scaling needed
00640                 if( src->getComponents() == dst->getComponents() )
00641                 {
00642                         copyScaled( src );
00643                 }
00644                 else
00645                 if( 3 == src->getComponents() )
00646                 {
00647                         copyScaled3onto4( src );
00648                 }
00649                 else
00650                 {
00651                         // 4 == src->getComponents()
00652                         copyScaled4onto3( src );
00653                 }
00654         }
00655 }
00656 
00657 // Src and dst are same size.  Src and dst have same number of components.
00658 void LLImageRaw::copyUnscaled(LLImageRaw* src)
00659 {
00660         LLImageRaw* dst = this;  // Just for clarity.
00661 
00662         llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
00663         llassert( src->getComponents() == dst->getComponents() );
00664         llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
00665 
00666         memcpy( dst->getData(), src->getData(), getWidth() * getHeight() * getComponents() );   /* Flawfinder: ignore */
00667 }
00668 
00669 
00670 // Src and dst can be any size.  Src has 3 components.  Dst has 4 components.
00671 void LLImageRaw::copyScaled3onto4(LLImageRaw* src)
00672 {
00673         llassert( (3 == src->getComponents()) && (4 == getComponents()) );
00674 
00675         // Slow, but simple.  Optimize later if needed.
00676         LLImageRaw temp( src->getWidth(), src->getHeight(), 4);
00677         temp.copyUnscaled3onto4( src );
00678         copyScaled( &temp );
00679 }
00680 
00681 
00682 // Src and dst can be any size.  Src has 4 components.  Dst has 3 components.
00683 void LLImageRaw::copyScaled4onto3(LLImageRaw* src)
00684 {
00685         llassert( (4 == src->getComponents()) && (3 == getComponents()) );
00686 
00687         // Slow, but simple.  Optimize later if needed.
00688         LLImageRaw temp( src->getWidth(), src->getHeight(), 3);
00689         temp.copyUnscaled4onto3( src );
00690         copyScaled( &temp );
00691 }
00692 
00693 
00694 // Src and dst are same size.  Src has 4 components.  Dst has 3 components.
00695 void LLImageRaw::copyUnscaled4onto3( LLImageRaw* src )
00696 {
00697         LLImageRaw* dst = this;  // Just for clarity.
00698 
00699         llassert( (3 == dst->getComponents()) && (4 == src->getComponents()) );
00700         llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
00701 
00702         S32 pixels = getWidth() * getHeight();
00703         U8* src_data = src->getData();
00704         U8* dst_data = dst->getData();
00705         for( S32 i=0; i<pixels; i++ )
00706         {
00707                 dst_data[0] = src_data[0];
00708                 dst_data[1] = src_data[1];
00709                 dst_data[2] = src_data[2];
00710                 src_data += 4;
00711                 dst_data += 3;
00712         }
00713 }
00714 
00715 
00716 // Src and dst are same size.  Src has 3 components.  Dst has 4 components.
00717 void LLImageRaw::copyUnscaled3onto4( LLImageRaw* src )
00718 {
00719         LLImageRaw* dst = this;  // Just for clarity.
00720         llassert( 3 == src->getComponents() );
00721         llassert( 4 == dst->getComponents() );
00722         llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
00723 
00724         S32 pixels = getWidth() * getHeight();
00725         U8* src_data = src->getData();
00726         U8* dst_data = dst->getData();
00727         for( S32 i=0; i<pixels; i++ )
00728         {
00729                 dst_data[0] = src_data[0];
00730                 dst_data[1] = src_data[1];
00731                 dst_data[2] = src_data[2];
00732                 dst_data[3] = 255;
00733                 src_data += 3;
00734                 dst_data += 4;
00735         }
00736 }
00737 
00738 
00739 // Src and dst can be any size.  Src and dst have same number of components.
00740 void LLImageRaw::copyScaled( LLImageRaw* src )
00741 {
00742         LLMemType mt1((LLMemType::EMemType)mMemType);
00743         LLImageRaw* dst = this;  // Just for clarity.
00744 
00745         llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
00746         llassert( src->getComponents() == dst->getComponents() );
00747 
00748         if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
00749         {
00750                 memcpy( dst->getData(), src->getData(), getWidth() * getHeight() * getComponents() );   /* Flawfinder: ignore */
00751                 return;
00752         }
00753 
00754         // Vertical
00755         S32 temp_data_size = src->getWidth() * dst->getHeight() * getComponents();
00756         U8* temp_buffer = new U8[ temp_data_size ];
00757         for( S32 col = 0; col < src->getWidth(); col++ )
00758         {
00759                 copyLineScaled( src->getData() + (getComponents() * col), temp_buffer + (getComponents() * col), src->getHeight(), dst->getHeight(), src->getWidth(), src->getWidth() );
00760         }
00761 
00762         // Horizontal
00763         for( S32 row = 0; row < dst->getHeight(); row++ )
00764         {
00765                 copyLineScaled( temp_buffer + (getComponents() * src->getWidth() * row), dst->getData() + (getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth(), 1, 1 );
00766         }
00767 
00768         // Clean up
00769         delete[] temp_buffer;
00770 }
00771 
00772 
00773 void LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
00774 {
00775         LLMemType mt1((LLMemType::EMemType)mMemType);
00776         llassert( (3 == getComponents()) || (4 == getComponents()) );
00777 
00778         S32 old_width = getWidth();
00779         S32 old_height = getHeight();
00780         
00781         if( (old_width == new_width) && (old_height == new_height) )
00782         {
00783                 return;  // Nothing to do.
00784         }
00785 
00786         // Reallocate the data buffer.
00787 
00788         if (scale_image_data)
00789         {
00790                 // Vertical
00791                 S32 temp_data_size = old_width * new_height * getComponents();
00792                 U8* temp_buffer = new U8[ temp_data_size ];
00793                 for( S32 col = 0; col < old_width; col++ )
00794                 {
00795                         copyLineScaled( getData() + (getComponents() * col), temp_buffer + (getComponents() * col), old_height, new_height, old_width, old_width );
00796                 }
00797 
00798                 deleteData();
00799 
00800                 U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
00801 
00802                 // Horizontal
00803                 for( S32 row = 0; row < new_height; row++ )
00804                 {
00805                         copyLineScaled( temp_buffer + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 );
00806                 }
00807 
00808                 // Clean up
00809                 delete[] temp_buffer;
00810         }
00811         else
00812         {
00813                 // copy out     existing image data
00814                 S32     temp_data_size = old_width * old_height * getComponents();
00815                 U8*     temp_buffer     = new U8[ temp_data_size ];
00816                 if (!temp_buffer)
00817                 {
00818                         llerrs << "Out of memory in LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )" << llendl;
00819                         return;
00820                 }
00821                 memcpy(temp_buffer,     getData(), temp_data_size);     /* Flawfinder: ignore */
00822 
00823                 // allocate     new     image data,     will delete     old     data
00824                 U8*     new_buffer = allocateDataSize(new_width, new_height, getComponents());
00825 
00826                 for( S32 row = 0; row < new_height;     row++ )
00827                 {
00828                         if (row < old_height)
00829                         {
00830                                 memcpy(new_buffer +     (new_width * row * getComponents()), temp_buffer + (old_width * row     * getComponents()),     getComponents() * llmin(old_width, new_width)); /* Flawfinder: ignore */
00831                                 if (old_width < new_width)
00832                                 {
00833                                         // pad out rest of row with     black
00834                                         memset(new_buffer +     (getComponents() * ((new_width * row) + old_width)), 0, getComponents() * (new_width - old_width));
00835                                 }
00836                         }
00837                         else
00838                         {
00839                                 // pad remaining rows with black
00840                                 memset(new_buffer +     (new_width * row * getComponents()), 0, new_width *     getComponents());
00841                         }
00842                 }
00843 
00844                 // Clean up
00845                 delete[] temp_buffer;
00846         }
00847 }
00848 
00849 void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step )
00850 {
00851         const S32 components = getComponents();
00852         llassert( components >= 1 && components <= 4 );
00853 
00854         const F32 ratio = F32(in_pixel_len) / out_pixel_len; // ratio of old to new
00855         const F32 norm_factor = 1.f / ratio;
00856 
00857         S32 goff = components >= 2 ? 1 : 0;
00858         S32 boff = components >= 3 ? 2 : 0;
00859         for( S32 x = 0; x < out_pixel_len; x++ )
00860         {
00861                 // Sample input pixels in range from sample0 to sample1.
00862                 // Avoid floating point accumulation error... don't just add ratio each time.  JC
00863                 const F32 sample0 = x * ratio;
00864                 const F32 sample1 = (x+1) * ratio;
00865                 const S32 index0 = llfloor(sample0);                    // left integer (floor)
00866                 const S32 index1 = llfloor(sample1);                    // right integer (floor)
00867                 const F32 fract0 = 1.f - (sample0 - F32(index0));       // spill over on left
00868                 const F32 fract1 = sample1 - F32(index1);                       // spill-over on right
00869 
00870                 if( index0 == index1 )
00871                 {
00872                         // Interval is embedded in one input pixel
00873                         S32 t0 = x * out_pixel_step * components;
00874                         S32 t1 = index0 * in_pixel_step * components;
00875                         U8* outp = out + t0;
00876                         U8* inp = in + t1;
00877                         for (S32 i = 0; i < components; ++i)
00878                         {
00879                                 *outp = *inp;
00880                                 ++outp;
00881                                 ++inp;
00882                         }
00883                 }
00884                 else
00885                 {
00886                         // Left straddle
00887                         S32 t1 = index0 * in_pixel_step * components;
00888                         F32 r = in[t1 + 0] * fract0;
00889                         F32 g = in[t1 + goff] * fract0;
00890                         F32 b = in[t1 + boff] * fract0;
00891                         F32 a = 0;
00892                         if( components == 4)
00893                         {
00894                                 a = in[t1 + 3] * fract0;
00895                         }
00896                 
00897                         // Central interval
00898                         if (components < 4)
00899                         {
00900                                 for( S32 u = index0 + 1; u < index1; u++ )
00901                                 {
00902                                         S32 t2 = u * in_pixel_step * components;
00903                                         r += in[t2 + 0];
00904                                         g += in[t2 + goff];
00905                                         b += in[t2 + boff];
00906                                 }
00907                         }
00908                         else
00909                         {
00910                                 for( S32 u = index0 + 1; u < index1; u++ )
00911                                 {
00912                                         S32 t2 = u * in_pixel_step * components;
00913                                         r += in[t2 + 0];
00914                                         g += in[t2 + 1];
00915                                         b += in[t2 + 2];
00916                                         a += in[t2 + 3];
00917                                 }
00918                         }
00919 
00920                         // right straddle
00921                         // Watch out for reading off of end of input array.
00922                         if( fract1 && index1 < in_pixel_len )
00923                         {
00924                                 S32 t3 = index1 * in_pixel_step * components;
00925                                 if (components < 4)
00926                                 {
00927                                         U8 in0 = in[t3 + 0];
00928                                         U8 in1 = in[t3 + goff];
00929                                         U8 in2 = in[t3 + boff];
00930                                         r += in0 * fract1;
00931                                         g += in1 * fract1;
00932                                         b += in2 * fract1;
00933                                 }
00934                                 else
00935                                 {
00936                                         U8 in0 = in[t3 + 0];
00937                                         U8 in1 = in[t3 + 1];
00938                                         U8 in2 = in[t3 + 2];
00939                                         U8 in3 = in[t3 + 3];
00940                                         r += in0 * fract1;
00941                                         g += in1 * fract1;
00942                                         b += in2 * fract1;
00943                                         a += in3 * fract1;
00944                                 }
00945                         }
00946 
00947                         r *= norm_factor;
00948                         g *= norm_factor;
00949                         b *= norm_factor;
00950                         a *= norm_factor;  // skip conditional
00951 
00952                         S32 t4 = x * out_pixel_step * components;
00953                         out[t4 + 0] = U8(llround(r));
00954                         if (components >= 2)
00955                                 out[t4 + 1] = U8(llround(g));
00956                         if (components >= 3)
00957                                 out[t4 + 2] = U8(llround(b));
00958                         if( components == 4)
00959                                 out[t4 + 3] = U8(llround(a));
00960                 }
00961         }
00962 }
00963 
00964 void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len )
00965 {
00966         llassert( getComponents() == 3 );
00967 
00968         const S32 IN_COMPONENTS = 4;
00969         const S32 OUT_COMPONENTS = 3;
00970 
00971         const F32 ratio = F32(in_pixel_len) / out_pixel_len; // ratio of old to new
00972         const F32 norm_factor = 1.f / ratio;
00973 
00974         for( S32 x = 0; x < out_pixel_len; x++ )
00975         {
00976                 // Sample input pixels in range from sample0 to sample1.
00977                 // Avoid floating point accumulation error... don't just add ratio each time.  JC
00978                 const F32 sample0 = x * ratio;
00979                 const F32 sample1 = (x+1) * ratio;
00980                 const S32 index0 = S32(sample0);                        // left integer (floor)
00981                 const S32 index1 = S32(sample1);                        // right integer (floor)
00982                 const F32 fract0 = 1.f - (sample0 - F32(index0));       // spill over on left
00983                 const F32 fract1 = sample1 - F32(index1);                       // spill-over on right
00984 
00985                 U8 in_scaled_r;
00986                 U8 in_scaled_g;
00987                 U8 in_scaled_b;
00988                 U8 in_scaled_a;
00989 
00990                 if( index0 == index1 )
00991                 {
00992                         // Interval is embedded in one input pixel
00993                         S32 t1 = index0 * IN_COMPONENTS;
00994                         in_scaled_r = in[t1 + 0];
00995                         in_scaled_g = in[t1 + 0];
00996                         in_scaled_b = in[t1 + 0];
00997                         in_scaled_a = in[t1 + 0];
00998                 }
00999                 else
01000                 {
01001                         // Left straddle
01002                         S32 t1 = index0 * IN_COMPONENTS;
01003                         F32 r = in[t1 + 0] * fract0;
01004                         F32 g = in[t1 + 1] * fract0;
01005                         F32 b = in[t1 + 2] * fract0;
01006                         F32 a = in[t1 + 3] * fract0;
01007                 
01008                         // Central interval
01009                         for( S32 u = index0 + 1; u < index1; u++ )
01010                         {
01011                                 S32 t2 = u * IN_COMPONENTS;
01012                                 r += in[t2 + 0];
01013                                 g += in[t2 + 1];
01014                                 b += in[t2 + 2];
01015                                 a += in[t2 + 3];
01016                         }
01017 
01018                         // right straddle
01019                         // Watch out for reading off of end of input array.
01020                         if( fract1 && index1 < in_pixel_len )
01021                         {
01022                                 S32 t3 = index1 * IN_COMPONENTS;
01023                                 r += in[t3 + 0] * fract1;
01024                                 g += in[t3 + 1] * fract1;
01025                                 b += in[t3 + 2] * fract1;
01026                                 a += in[t3 + 3] * fract1;
01027                         }
01028 
01029                         r *= norm_factor;
01030                         g *= norm_factor;
01031                         b *= norm_factor;
01032                         a *= norm_factor;
01033 
01034                         in_scaled_r = U8(llround(r));
01035                         in_scaled_g = U8(llround(g));
01036                         in_scaled_b = U8(llround(b));
01037                         in_scaled_a = U8(llround(a));
01038                 }
01039 
01040                 if( in_scaled_a )
01041                 {
01042                         if( 255 == in_scaled_a )
01043                         {
01044                                 out[0] = in_scaled_r;
01045                                 out[1] = in_scaled_g;
01046                                 out[2] = in_scaled_b;
01047                         }
01048                         else
01049                         {
01050                                 U8 transparency = 255 - in_scaled_a;
01051                                 out[0] = fastFractionalMult( out[0], transparency ) + fastFractionalMult( in_scaled_r, in_scaled_a );
01052                                 out[1] = fastFractionalMult( out[1], transparency ) + fastFractionalMult( in_scaled_g, in_scaled_a );
01053                                 out[2] = fastFractionalMult( out[2], transparency ) + fastFractionalMult( in_scaled_b, in_scaled_a );
01054                         }
01055                 }
01056                 out += OUT_COMPONENTS;
01057         }
01058 }
01059 
01060 
01061 //----------------------------------------------------------------------------
01062 
01063 static struct
01064 {
01065         const char* exten;
01066         S8 codec;
01067 }
01068 file_extensions[] =
01069 {
01070         { "bmp", IMG_CODEC_BMP },
01071         { "tga", IMG_CODEC_TGA },
01072         { "j2c", IMG_CODEC_J2C },
01073         { "jp2", IMG_CODEC_J2C },
01074         { "texture", IMG_CODEC_J2C },
01075         { "jpg", IMG_CODEC_JPEG },
01076         { "jpeg", IMG_CODEC_JPEG },
01077         { "mip", IMG_CODEC_DXT },
01078         { "dxt", IMG_CODEC_DXT },
01079         { "png", IMG_CODEC_PNG }
01080 };
01081 #define NUM_FILE_EXTENSIONS sizeof(file_extensions)/sizeof(file_extensions[0])
01082 
01083 static LLString find_file(LLString &name, S8 *codec)
01084 {
01085         LLString tname;
01086         for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++)
01087         {
01088                 tname = name + "." + LLString(file_extensions[i].exten);
01089                 llifstream ifs(tname.c_str(), llifstream::binary);
01090                 if (ifs.is_open())
01091                 {
01092                         ifs.close();
01093                         if (codec)
01094                                 *codec = file_extensions[i].codec;
01095                         return LLString(file_extensions[i].exten);
01096                 }
01097         }
01098         return LLString("");
01099 }
01100 
01101 static S8 get_codec(const LLString& exten)
01102 {
01103         for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++)
01104         {
01105                 if (exten == file_extensions[i].exten)
01106                         return file_extensions[i].codec;
01107         }
01108         return IMG_CODEC_INVALID;
01109 }
01110 
01111 bool LLImageRaw::createFromFile(const LLString &filename, bool j2c_lowest_mip_only)
01112 {
01113         LLString name = filename;
01114         size_t dotidx = name.rfind('.');
01115         S8 codec = IMG_CODEC_INVALID;
01116         LLString exten;
01117         
01118         deleteData(); // delete any existing data
01119 
01120         if (dotidx != LLString::npos)
01121         {
01122                 exten = name.substr(dotidx+1);
01123                 LLString::toLower(exten);
01124                 codec = get_codec(exten);
01125         }
01126         else
01127         {
01128                 exten = find_file(name, &codec);
01129                 name = name + "." + exten;
01130         }
01131         if (codec == IMG_CODEC_INVALID)
01132         {
01133                 return false; // format not recognized
01134         }
01135 
01136         llifstream ifs(name.c_str(), llifstream::binary);
01137         if (!ifs.is_open())
01138         {
01139                 // SJB: changed from llinfos to lldebugs to reduce spam
01140                 lldebugs << "Unable to open image file: " << name << llendl;
01141                 return false;
01142         }
01143         
01144         ifs.seekg (0, std::ios::end);
01145         int length = ifs.tellg();
01146         if (j2c_lowest_mip_only && length > 2048)
01147         {
01148                 length = 2048;
01149         }
01150         ifs.seekg (0, std::ios::beg);
01151 
01152         if (!length)
01153         {
01154                 llinfos << "Zero length file file: " << name << llendl;
01155                 return false;
01156         }
01157         
01158         LLPointer<LLImageFormatted> image;
01159         switch(codec)
01160         {
01161           //case IMG_CODEC_RGB:
01162           case IMG_CODEC_BMP:
01163                 image = new LLImageBMP();
01164                 break;
01165           case IMG_CODEC_TGA:
01166                 image = new LLImageTGA();
01167                 break;
01168 #if JPEG_SUPPORT
01169           case IMG_CODEC_JPEG:
01170                 image = new LLImageJPEG();
01171                 break;
01172 #endif
01173           case IMG_CODEC_J2C:
01174                 image = new LLImageJ2C();
01175                 break;
01176           case IMG_CODEC_DXT:
01177                 image = new LLImageDXT();
01178                 break;
01179           default:
01180                 return false;
01181         }
01182         llassert(image.notNull());
01183 
01184         U8 *buffer = image->allocateData(length);
01185         ifs.read ((char*)buffer, length);       /* Flawfinder: ignore */
01186         ifs.close();
01187         
01188         image->updateData();
01189         
01190         if (j2c_lowest_mip_only && codec == IMG_CODEC_J2C)
01191         {
01192                 S32 width = image->getWidth();
01193                 S32 height = image->getHeight();
01194                 S32 discard_level = 0;
01195                 while (width > 1 && height > 1 && discard_level < MAX_DISCARD_LEVEL)
01196                 {
01197                         width >>= 1;
01198                         height >>= 1;
01199                         discard_level++;
01200                 }
01201                 ((LLImageJ2C *)((LLImageFormatted*)image))->setDiscardLevel(discard_level);
01202         }
01203         
01204         BOOL success = image->decode(this, 100000.0f);
01205         image = NULL; // deletes image
01206 
01207         if (!success)
01208         {
01209                 deleteData();
01210                 llwarns << "Unable to decode image" << name << llendl;
01211                 return false;
01212         }
01213 
01214         return true;
01215 }
01216 
01217 //---------------------------------------------------------------------------
01218 // LLImageFormatted
01219 //---------------------------------------------------------------------------
01220 
01221 //static
01222 S32 LLImageFormatted::sGlobalFormattedMemory = 0;
01223 
01224 LLImageFormatted::LLImageFormatted(S8 codec)
01225         : LLImageBase(),
01226           mCodec(codec),
01227           mDecoding(0),
01228           mDecoded(0),
01229           mDiscardLevel(0)
01230 {
01231         mMemType = LLMemType::MTYPE_IMAGEFORMATTED;
01232 }
01233 
01234 // virtual
01235 LLImageFormatted::~LLImageFormatted()
01236 {
01237         // NOTE: ~LLimageBase() call to deleteData() calls LLImageBase::deleteData()
01238         //        NOT LLImageFormatted::deleteData()
01239         deleteData();
01240 }
01241 
01242 //----------------------------------------------------------------------------
01243 
01244 // static
01245 LLImageFormatted* LLImageFormatted::createFromType(S8 codec)
01246 {
01247         LLImageFormatted* image;
01248         switch(codec)
01249         {
01250           case IMG_CODEC_BMP:
01251                 image = new LLImageBMP();
01252                 break;
01253           case IMG_CODEC_TGA:
01254                 image = new LLImageTGA();
01255                 break;
01256 #if JPEG_SUPPORT
01257           case IMG_CODEC_JPEG:
01258                 image = new LLImageJPEG();
01259                 break;
01260 #endif
01261           case IMG_CODEC_J2C:
01262                 image = new LLImageJ2C();
01263                 break;
01264           case IMG_CODEC_DXT:
01265                 image = new LLImageDXT();
01266                 break;
01267           default:
01268                 image = NULL;
01269                 break;
01270         }
01271         return image;
01272 }
01273 
01274 // static
01275 LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring)
01276 {
01277         LLString exten;
01278         size_t dotidx = instring.rfind('.');
01279         if (dotidx != LLString::npos)
01280         {
01281                 exten = instring.substr(dotidx+1);
01282         }
01283         else
01284         {
01285                 exten = instring;
01286         }
01287         S8 codec = get_codec(exten);
01288         return createFromType(codec);
01289 }
01290 //----------------------------------------------------------------------------
01291 
01292 // virtual
01293 void LLImageFormatted::dump()
01294 {
01295         LLImageBase::dump();
01296 
01297         llinfos << "LLImageFormatted"
01298                         << " mDecoding " << mDecoding
01299                         << " mCodec " << S32(mCodec)
01300                         << " mDecoded " << mDecoded
01301                         << llendl;
01302 }
01303 
01304 //----------------------------------------------------------------------------
01305 
01306 S32 LLImageFormatted::calcDataSize(S32 discard_level)
01307 {
01308         if (discard_level < 0)
01309         {
01310                 discard_level = mDiscardLevel;
01311         }
01312         S32 w = getWidth() >> discard_level;
01313         S32 h = getHeight() >> discard_level;
01314         w = llmax(w, 1);
01315         h = llmax(h, 1);
01316         return w * h * getComponents();
01317 }
01318 
01319 S32 LLImageFormatted::calcDiscardLevelBytes(S32 bytes)
01320 {
01321         llassert(bytes >= 0);
01322         S32 discard_level = 0;
01323         while (1)
01324         {
01325                 S32 bytes_needed = calcDataSize(discard_level); // virtual
01326                 if (bytes_needed <= bytes)
01327                 {
01328                         break;
01329                 }
01330                 discard_level++;
01331                 if (discard_level > MAX_IMAGE_MIP)
01332                 {
01333                         return -1;
01334                 }
01335         }
01336         return discard_level;
01337 }
01338 
01339 
01340 //----------------------------------------------------------------------------
01341 
01342 // Subclasses that can handle more than 4 channels should override this function.
01343 BOOL LLImageFormatted::decode(LLImageRaw* raw_image,F32  decode_time, S32 first_channel, S32 max_channel)
01344 {
01345         llassert( (first_channel == 0) && (max_channel == 4) );
01346         return decode( raw_image, decode_time );  // Loads first 4 channels by default.
01347 } 
01348 
01349 //----------------------------------------------------------------------------
01350 
01351 // virtual
01352 U8* LLImageFormatted::allocateData(S32 size)
01353 {
01354         U8* res = LLImageBase::allocateData(size); // calls deleteData()
01355         sGlobalFormattedMemory += getDataSize();
01356         return res;
01357 }
01358 
01359 // virtual
01360 U8* LLImageFormatted::reallocateData(S32 size)
01361 {
01362         sGlobalFormattedMemory -= getDataSize();
01363         U8* res = LLImageBase::reallocateData(size);
01364         sGlobalFormattedMemory += getDataSize();
01365         return res;
01366 }
01367 
01368 // virtual
01369 void LLImageFormatted::deleteData()
01370 {
01371         sGlobalFormattedMemory -= getDataSize();
01372         LLImageBase::deleteData();
01373 }
01374 
01375 //----------------------------------------------------------------------------
01376 
01377 // virtual
01378 void LLImageFormatted::sanityCheck()
01379 {
01380         LLImageBase::sanityCheck();
01381 
01382         if (mCodec >= IMG_CODEC_EOF)
01383         {
01384                 llerrs << "Failed LLImageFormatted::sanityCheck "
01385                            << "decoding " << S32(mDecoding)
01386                            << "decoded " << S32(mDecoded)
01387                            << "codec " << S32(mCodec)
01388                            << llendl;
01389         }
01390 }
01391 
01392 //----------------------------------------------------------------------------
01393 
01394 BOOL LLImageFormatted::copyData(U8 *data, S32 size)
01395 {
01396         if ( data && ((data != getData()) || (size != getDataSize())) )
01397         {
01398                 deleteData();
01399                 allocateData(size);
01400                 memcpy(getData(), data, size);  /* Flawfinder: ignore */
01401         }
01402         return TRUE;
01403 }
01404 
01405 // LLImageFormatted becomes the owner of data
01406 void LLImageFormatted::setData(U8 *data, S32 size)
01407 {
01408         if (data && data != getData())
01409         {
01410                 deleteData();
01411                 setDataAndSize(data, size); // Access private LLImageBase members
01412                 sGlobalFormattedMemory += getDataSize();
01413         }
01414 }
01415 
01416 void LLImageFormatted::appendData(U8 *data, S32 size)
01417 {
01418         if (data)
01419         {
01420                 if (!getData())
01421                 {
01422                         setData(data, size);
01423                 }
01424                 else 
01425                 {
01426                         S32 cursize = getDataSize();
01427                         S32 newsize = cursize + size;
01428                         reallocateData(newsize);
01429                         memcpy(getData() + cursize, data, size);
01430                 }
01431         }
01432 }
01433 
01434 //----------------------------------------------------------------------------
01435 
01436 BOOL LLImageFormatted::load(const LLString &filename)
01437 {
01438         resetLastError();
01439 
01440         S32 file_size = 0;
01441         apr_file_t* apr_file = ll_apr_file_open(filename, LL_APR_RB, &file_size);
01442         if (!apr_file)
01443         {
01444                 setLastError("Unable to open file for reading", filename);
01445                 return FALSE;
01446         }
01447         if (file_size == 0)
01448         {
01449                 setLastError("File is empty",filename);
01450                 apr_file_close(apr_file);
01451                 return FALSE;
01452         }
01453 
01454         BOOL res;
01455         U8 *data = allocateData(file_size);
01456         apr_size_t bytes_read = file_size;
01457         apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
01458         if (s != APR_SUCCESS || (S32) bytes_read != file_size)
01459         {
01460                 deleteData();
01461                 setLastError("Unable to read entire file",filename);
01462                 res = FALSE;
01463         }
01464         else
01465         {
01466                 res = updateData();
01467         }
01468         apr_file_close(apr_file);
01469 
01470         return res;
01471 }
01472 
01473 BOOL LLImageFormatted::save(const LLString &filename)
01474 {
01475         resetLastError();
01476 
01477         apr_file_t* apr_file = ll_apr_file_open(filename, LL_APR_WB);
01478         if (!apr_file)
01479         {
01480                 setLastError("Unable to open file for reading", filename);
01481                 return FALSE;
01482         }
01483         
01484         ll_apr_file_write(apr_file, getData(),  getDataSize());
01485         apr_file_close(apr_file);
01486 
01487         return TRUE;
01488 }
01489 
01490 // BOOL LLImageFormatted::save(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
01491 // Depricated to remove VFS dependency.
01492 // Use:
01493 // LLVFile::writeFile(image->getData(), image->getDataSize(), vfs, uuid, type);
01494 
01495 //----------------------------------------------------------------------------
01496 
01497 S8 LLImageFormatted::getCodec() const
01498 {
01499         return mCodec;
01500 }
01501 
01502 //============================================================================
01503 
01504 static void avg4_colors4(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst)
01505 {
01506         dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2);
01507         dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2);
01508         dst[2] = (U8)(((U32)(a[2]) + b[2] + c[2] + d[2])>>2);
01509         dst[3] = (U8)(((U32)(a[3]) + b[3] + c[3] + d[3])>>2);
01510 }
01511 
01512 static void avg4_colors3(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst)
01513 {
01514         dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2);
01515         dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2);
01516         dst[2] = (U8)(((U32)(a[2]) + b[2] + c[2] + d[2])>>2);
01517 }
01518 
01519 static void avg4_colors2(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst)
01520 {
01521         dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2);
01522         dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2);
01523 }
01524 
01525 //static
01526 void LLImageBase::generateMip(const U8* indata, U8* mipdata, S32 width, S32 height, S32 nchannels)
01527 {
01528         llassert(width > 0 && height > 0);
01529         U8* data = mipdata;
01530         S32 in_width = width*2;
01531         for (S32 h=0; h<height; h++)
01532         {
01533                 for (S32 w=0; w<width; w++)
01534                 {
01535                         switch(nchannels)
01536                         {
01537                           case 4:
01538                                 avg4_colors4(indata, indata+4, indata+4*in_width, indata+4*in_width+4, data);
01539                                 break;
01540                           case 3:
01541                                 avg4_colors3(indata, indata+3, indata+3*in_width, indata+3*in_width+3, data);
01542                                 break;
01543                           case 2:
01544                                 avg4_colors2(indata, indata+2, indata+2*in_width, indata+2*in_width+2, data);
01545                                 break;
01546                           case 1:
01547                                 *(U8*)data = (U8)(((U32)(indata[0]) + indata[1] + indata[in_width] + indata[in_width+1])>>2);
01548                                 break;
01549                           default:
01550                                 llerrs << "generateMmip called with bad num channels" << llendl;
01551                         }
01552                         indata += nchannels*2;
01553                         data += nchannels;
01554                 }
01555                 indata += nchannels*in_width; // skip odd lines
01556         }
01557 }
01558 
01559 
01560 //============================================================================
01561 
01562 //static
01563 F32 LLImageBase::calc_download_priority(F32 virtual_size, F32 visible_pixels, S32 bytes_sent)
01564 {
01565         F32 w_priority;
01566 
01567         F32 bytes_weight = 1.f;
01568         if (!bytes_sent)
01569         {
01570                 bytes_weight = 20.f;
01571         }
01572         else if (bytes_sent < 1000)
01573         {
01574                 bytes_weight = 1.f;
01575         }
01576         else if (bytes_sent < 2000)
01577         {
01578                 bytes_weight = 1.f/1.5f;
01579         }
01580         else if (bytes_sent < 4000)
01581         {
01582                 bytes_weight = 1.f/3.f;
01583         }
01584         else if (bytes_sent < 8000)
01585         {
01586                 bytes_weight = 1.f/6.f;
01587         }
01588         else if (bytes_sent < 16000)
01589         {
01590                 bytes_weight = 1.f/12.f;
01591         }
01592         else if (bytes_sent < 32000)
01593         {
01594                 bytes_weight = 1.f/20.f;
01595         }
01596         else if (bytes_sent < 64000)
01597         {
01598                 bytes_weight = 1.f/32.f;
01599         }
01600         else
01601         {
01602                 bytes_weight = 1.f/64.f;
01603         }
01604         bytes_weight *= bytes_weight;
01605 
01606 
01607         //llinfos << "VS: " << virtual_size << llendl;
01608         F32 virtual_size_factor = virtual_size / (10.f*10.f);
01609 
01610         // The goal is for weighted priority to be <= 0 when we've reached a point where
01611         // we've sent enough data.
01612         //llinfos << "BytesSent: " << bytes_sent << llendl;
01613         //llinfos << "BytesWeight: " << bytes_weight << llendl;
01614         //llinfos << "PreLog: " << bytes_weight * virtual_size_factor << llendl;
01615         w_priority = (F32)log10(bytes_weight * virtual_size_factor);
01616 
01617         //llinfos << "PreScale: " << w_priority << llendl;
01618 
01619         // We don't want to affect how MANY bytes we send based on the visible pixels, but the order
01620         // in which they're sent.  We post-multiply so we don't change the zero point.
01621         if (w_priority > 0.f)
01622         {
01623                 F32 pixel_weight = (F32)log10(visible_pixels + 1)*3.0f;
01624                 w_priority *= pixel_weight;
01625         }
01626 
01627         return w_priority;
01628 }
01629 
01630 //============================================================================

Generated on Thu Jul 1 06:08:43 2010 for Second Life Viewer by  doxygen 1.4.7