From 5205be0c65bf8dee8b51c112083a4cc8a7cebc49 Mon Sep 17 00:00:00 2001 From: pavelkproductengine Date: Wed, 31 May 2017 19:28:46 +0300 Subject: STORM-2148 Crash on trying to save texture file(s) to computer from inventory --- indra/llimage/llimagepng.cpp | 4 ++-- indra/llimage/llpngwrapper.cpp | 8 +++++++- indra/llimage/llpngwrapper.h | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'indra/llimage') 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..b2fa0ed315 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(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(); -- cgit v1.3 From 3d8dc8cd6dd4ea59ff226f91b114a3298f8f096f Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 12 Jun 2017 15:26:10 +0300 Subject: Fixed line endings for llpngwrapper.cpp --- indra/llimage/llpngwrapper.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/llimage') diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index b2fa0ed315..eb70b78a36 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -112,10 +112,10 @@ 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; + 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); -- cgit v1.3 From 6dcde6469d03b96260b1d00c22a90d76357a28ae Mon Sep 17 00:00:00 2001 From: ruslantproductengine Date: Tue, 6 Jun 2017 15:30:03 +0300 Subject: [SL-711] - Eliminate some overheads in texturecache. - Eliminate memory overhead when need duplicated scaled image. - Small improvement in LLImageBase::getCodecFromExtension() --- indra/llimage/llimage.cpp | 60 ++++++++++++++++++++++++++++++++++++--- indra/llimage/llimage.h | 3 +- indra/newview/lltexturecache.cpp | 4 +-- indra/newview/llviewertexture.cpp | 6 ++-- 4 files changed, 61 insertions(+), 12 deletions(-) (limited to 'indra/llimage') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index a07ea14621..ad765b6415 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1436,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; @@ -1512,6 +1512,55 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data ) return true ; } +LLPointer LLImageRaw::scaled(S32 new_width, S32 new_height) +{ + LLPointer 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) + { + 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) + { + 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(); @@ -1785,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 d0bd4a2aef..958c9fad3d 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -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 scaled(S32 new_width, S32 new_height); // Fill the buffer with a constant color void fill( const LLColor4U& color ); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index e8b3842ae5..f0c28041d1 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -1987,15 +1987,13 @@ bool LLTextureCache::writeToFastCache(S32 id, LLPointer raw, S32 dis if(w * h *c > 0) //valid { //make a duplicate to keep the original raw image untouched. - raw = raw->duplicate(); + raw = raw->scaled(w, h); if (raw->isBufferInvalid()) { LL_WARNS() << "Invalid image duplicate buffer" << LL_ENDL; return false; } - raw->scale(w, h) ; - discardlevel += i ; } } diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 5de7df7b91..e5a1bed48c 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1396,8 +1396,7 @@ void LLViewerFetchedTexture::addToCreateTexture() { //make a duplicate in case somebody else is using this raw image - mRawImage = mRawImage->duplicate(); - mRawImage->scale(w >> i, h >> i) ; + mRawImage = mRawImage->scaled(w >> i, h >> i); } } } @@ -2913,8 +2912,7 @@ void LLViewerFetchedTexture::setCachedRawImage() { //make a duplicate in case somebody else is using this raw image - mRawImage = mRawImage->duplicate(); - mRawImage->scale(w >> i, h >> i) ; + mRawImage = mRawImage->scaled(w >> i, h >> i); } } mCachedRawImage = mRawImage; -- cgit v1.3