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