diff options
Diffstat (limited to 'indra/llimage')
-rw-r--r-- | indra/llimage/llimage.cpp | 99 | ||||
-rw-r--r-- | indra/llimage/llimage.h | 5 | ||||
-rw-r--r-- | indra/llimage/llimagepng.cpp | 4 | ||||
-rw-r--r-- | indra/llimage/llpngwrapper.cpp | 8 | ||||
-rw-r--r-- | indra/llimage/llpngwrapper.h | 2 |
5 files changed, 93 insertions, 25 deletions
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index f71607096c..04085eb703 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -705,18 +705,21 @@ void LLImageBase::deleteData() // virtual U8* LLImageBase::allocateData(S32 size) { + //make this function thread-safe. + static const U32 MAX_BUFFER_SIZE = 4096 * 4096 * 16; //256 MB + mBadBufferAllocation = false; + if (size < 0) { size = mWidth * mHeight * mComponents; if (size <= 0) { - LL_ERRS() << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,(S32)mComponents) << LL_ENDL; + LL_WARNS() << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,(S32)mComponents) << LL_ENDL; + mBadBufferAllocation = true; } - } - - //make this function thread-safe. - static const U32 MAX_BUFFER_SIZE = 4096 * 4096 * 16 ; //256 MB - if (size < 1 || size > MAX_BUFFER_SIZE) + } + + if (!mBadBufferAllocation && (size < 1 || size > MAX_BUFFER_SIZE)) { LL_INFOS() << "width: " << mWidth << " height: " << mHeight << " components: " << mComponents << LL_ENDL ; if(mAllowOverSize) @@ -725,25 +728,31 @@ U8* LLImageBase::allocateData(S32 size) } else { - LL_ERRS() << "LLImageBase::allocateData: bad size: " << size << LL_ENDL; + LL_WARNS() << "LLImageBase::allocateData: bad size: " << size << LL_ENDL; + mBadBufferAllocation = true; } } - if (!mData || size != mDataSize) + + if (!mBadBufferAllocation && (!mData || size != mDataSize)) { deleteData(); // virtual - mBadBufferAllocation = false ; mData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size); if (!mData) { LL_WARNS() << "Failed to allocate image data size [" << size << "]" << LL_ENDL; - size = 0 ; - mWidth = mHeight = 0 ; - mBadBufferAllocation = true ; + mBadBufferAllocation = true; } - mDataSize = size; - claimMem(mDataSize); } + if (mBadBufferAllocation) + { + size = 0; + mWidth = mHeight = 0; + mData = NULL; + } + mDataSize = size; + claimMem(mDataSize); + return mData; } @@ -791,7 +800,7 @@ U8* LLImageBase::getData() return mData; } -bool LLImageBase::isBufferInvalid() +bool LLImageBase::isBufferInvalid() const { return mBadBufferAllocation || mData == NULL ; } @@ -1427,7 +1436,7 @@ void LLImageRaw::copyScaled( LLImageRaw* src ) bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data ) { S32 components = getComponents(); - if (! ((1 == components) || (3 == components) || (4 == components) )) + if (components != 1 && components != 3 && components != 4) { LL_WARNS() << "Invalid getComponents value (" << components << ")" << LL_ENDL; return false; @@ -1503,6 +1512,55 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data ) return true ; } +LLPointer<LLImageRaw> LLImageRaw::scaled(S32 new_width, S32 new_height) +{ + LLPointer<LLImageRaw> result; + + S32 components = getComponents(); + if (components != 1 && components != 3 && components != 4) + { + LL_WARNS() << "Invalid getComponents value (" << components << ")" << LL_ENDL; + return result; + } + + if (isBufferInvalid()) + { + LL_WARNS() << "Invalid image buffer" << LL_ENDL; + return result; + } + + S32 old_width = getWidth(); + S32 old_height = getHeight(); + + if ((old_width == new_width) && (old_height == new_height)) + { + result = new LLImageRaw(old_width, old_height, components); + if (!result || result->isBufferInvalid()) + { + LL_WARNS() << "Failed to allocate new image" << LL_ENDL; + return result; + } + memcpy(result->getData(), getData(), getDataSize()); + } + else + { + S32 new_data_size = new_width * new_height * components; + + if (new_data_size > 0) + { + result = new LLImageRaw(new_width, new_height, components); + if (!result || result->isBufferInvalid()) + { + LL_WARNS() << "Failed to allocate new image" << LL_ENDL; + return result; + } + bilinear_scale(getData(), old_width, old_height, components, old_width*components, result->getData(), new_width, new_height, components, new_width*components); + } + } + + return result; +} + void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step ) { const S32 components = getComponents(); @@ -1776,10 +1834,13 @@ static std::string find_file(std::string &name, S8 *codec) #endif EImageCodec LLImageBase::getCodecFromExtension(const std::string& exten) { - for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++) + if (!exten.empty()) { - if (exten == file_extensions[i].exten) - return file_extensions[i].codec; + for (int i = 0; i < (int)(NUM_FILE_EXTENSIONS); i++) + { + if (exten == file_extensions[i].exten) + return file_extensions[i].codec; + } } return IMG_CODEC_INVALID; } diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 9cc7431a9c..958c9fad3d 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -141,7 +141,7 @@ public: const U8 *getData() const ; U8 *getData() ; - bool isBufferInvalid() ; + bool isBufferInvalid() const; void setSize(S32 width, S32 height, S32 ncomponents); U8* allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 size = -1); // setSize() + allocateData() @@ -215,7 +215,8 @@ public: void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, bool scale_image = true); void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, bool scale_image = true); void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE); - bool scale( S32 new_width, S32 new_height, bool scale_image = true ); + bool scale(S32 new_width, S32 new_height, bool scale_image = true); + LLPointer<LLImageRaw> scaled(S32 new_width, S32 new_height); // Fill the buffer with a constant color void fill( const LLColor4U& color ); diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp index a299602d79..a4823ed859 100644 --- a/indra/llimage/llimagepng.cpp +++ b/indra/llimage/llimagepng.cpp @@ -124,12 +124,12 @@ bool LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time) // Temporary buffer to hold the encoded image. Note: the final image // size should be much smaller due to compression. - U32 bufferSize = getWidth() * getHeight() * getComponents() + 1024; + U32 bufferSize = getWidth() * getHeight() * getComponents() + 8192; U8* tmpWriteBuffer = new U8[ bufferSize ]; // Delegate actual encoding work to wrapper LLPngWrapper pngWrapper; - if (! pngWrapper.writePng(raw_image, tmpWriteBuffer)) + if (!pngWrapper.writePng(raw_image, tmpWriteBuffer, bufferSize)) { setLastError(pngWrapper.getErrorMessage()); delete[] tmpWriteBuffer; diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index da289ea889..eb70b78a36 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -112,6 +112,11 @@ void LLPngWrapper::readDataCallback(png_structp png_ptr, png_bytep dest, png_siz void LLPngWrapper::writeDataCallback(png_structp png_ptr, png_bytep src, png_size_t length) { PngDataInfo *dataInfo = (PngDataInfo *) png_get_io_ptr(png_ptr); + if (dataInfo->mOffset + length > dataInfo->mDataSize) + { + png_error(png_ptr, "Data write error. Requested data size exceeds available data size."); + return; + } U8 *dest = &dataInfo->mData[dataInfo->mOffset]; memcpy(dest, src, length); dataInfo->mOffset += static_cast<U32>(length); @@ -272,7 +277,7 @@ void LLPngWrapper::updateMetaData() // Method to write raw image into PNG at dest. The raw scanline begins // at the bottom of the image per SecondLife conventions. -BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest) +BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest, size_t destSize) { try { @@ -313,6 +318,7 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest) PngDataInfo dataPtr; dataPtr.mData = dest; dataPtr.mOffset = 0; + dataPtr.mDataSize = destSize; png_set_write_fn(mWritePngPtr, &dataPtr, &writeDataCallback, &writeFlush); // Setup image params diff --git a/indra/llimage/llpngwrapper.h b/indra/llimage/llpngwrapper.h index 27d7df3bef..8d42317b0f 100644 --- a/indra/llimage/llpngwrapper.h +++ b/indra/llimage/llpngwrapper.h @@ -45,7 +45,7 @@ public: BOOL isValidPng(U8* src); BOOL readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInfo *infop = NULL); - BOOL writePng(const LLImageRaw* rawImage, U8* dst); + BOOL writePng(const LLImageRaw* rawImage, U8* dst, size_t destSize); U32 getFinalSize(); const std::string& getErrorMessage(); |