viewer-private#226 Unhandled PngError throws application into a loop
png_read_info triggered a PngError, LLAppViewer::frame() handled it instead of LLPngWrapper::readPng, and since status didn't change viewer tried to decode image again and again and again.master
parent
00e09ddcad
commit
f5a7fba76a
|
|
@ -27,6 +27,7 @@
|
|||
#include "linden_common.h"
|
||||
#include "stdtypes.h"
|
||||
#include "llerror.h"
|
||||
#include "llexception.h"
|
||||
|
||||
#include "llimage.h"
|
||||
#include "llpngwrapper.h"
|
||||
|
|
@ -51,29 +52,44 @@ bool LLImagePNG::updateData()
|
|||
{
|
||||
resetLastError();
|
||||
|
||||
// Check to make sure that this instance has been initialized with data
|
||||
if (!getData() || (0 == getDataSize()))
|
||||
try
|
||||
{
|
||||
setLastError("Uninitialized instance of LLImagePNG");
|
||||
// Check to make sure that this instance has been initialized with data
|
||||
if (!getData() || (0 == getDataSize()))
|
||||
{
|
||||
setLastError("Uninitialized instance of LLImagePNG");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decode the PNG data and extract sizing information
|
||||
LLPngWrapper pngWrapper;
|
||||
if (!pngWrapper.isValidPng(getData()))
|
||||
{
|
||||
setLastError("LLImagePNG data does not have a valid PNG header!");
|
||||
return false;
|
||||
}
|
||||
|
||||
LLPngWrapper::ImageInfo infop;
|
||||
if (!pngWrapper.readPng(getData(), getDataSize(), NULL, &infop))
|
||||
{
|
||||
setLastError(pngWrapper.getErrorMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
setSize(infop.mWidth, infop.mHeight, infop.mComponents);
|
||||
}
|
||||
catch (const LLContinueError& msg)
|
||||
{
|
||||
setLastError(msg.what());
|
||||
LOG_UNHANDLED_EXCEPTION("");
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
setLastError("LLImagePNG");
|
||||
LOG_UNHANDLED_EXCEPTION("");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decode the PNG data and extract sizing information
|
||||
LLPngWrapper pngWrapper;
|
||||
if (!pngWrapper.isValidPng(getData()))
|
||||
{
|
||||
setLastError("LLImagePNG data does not have a valid PNG header!");
|
||||
return false;
|
||||
}
|
||||
|
||||
LLPngWrapper::ImageInfo infop;
|
||||
if (! pngWrapper.readPng(getData(), getDataSize(), NULL, &infop))
|
||||
{
|
||||
setLastError(pngWrapper.getErrorMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
setSize(infop.mWidth, infop.mHeight, infop.mComponents);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,6 +216,13 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
|
|||
releaseResources();
|
||||
return (FALSE);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
mErrorMessage = "LLPngWrapper";
|
||||
releaseResources();
|
||||
LOG_UNHANDLED_EXCEPTION("");
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
// Clean up and return
|
||||
releaseResources();
|
||||
|
|
|
|||
|
|
@ -332,54 +332,62 @@ void LLFloaterImagePreview::draw()
|
|||
//-----------------------------------------------------------------------------
|
||||
bool LLFloaterImagePreview::loadImage(const std::string& src_filename)
|
||||
{
|
||||
std::string exten = gDirUtilp->getExtension(src_filename);
|
||||
U32 codec = LLImageBase::getCodecFromExtension(exten);
|
||||
try
|
||||
{
|
||||
std::string exten = gDirUtilp->getExtension(src_filename);
|
||||
U32 codec = LLImageBase::getCodecFromExtension(exten);
|
||||
|
||||
LLImageDimensionsInfo image_info;
|
||||
if (!image_info.load(src_filename,codec))
|
||||
{
|
||||
mImageLoadError = image_info.getLastError();
|
||||
return false;
|
||||
}
|
||||
LLImageDimensionsInfo image_info;
|
||||
if (!image_info.load(src_filename, codec))
|
||||
{
|
||||
mImageLoadError = image_info.getLastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
S32 max_width = gSavedSettings.getS32("max_texture_dimension_X");
|
||||
S32 max_height = gSavedSettings.getS32("max_texture_dimension_Y");
|
||||
S32 max_width = gSavedSettings.getS32("max_texture_dimension_X");
|
||||
S32 max_height = gSavedSettings.getS32("max_texture_dimension_Y");
|
||||
|
||||
if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height))
|
||||
{
|
||||
LLStringUtil::format_map_t args;
|
||||
args["WIDTH"] = llformat("%d", max_width);
|
||||
args["HEIGHT"] = llformat("%d", max_height);
|
||||
if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height))
|
||||
{
|
||||
LLStringUtil::format_map_t args;
|
||||
args["WIDTH"] = llformat("%d", max_width);
|
||||
args["HEIGHT"] = llformat("%d", max_height);
|
||||
|
||||
mImageLoadError = LLTrans::getString("texture_load_dimensions_error", args);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the image
|
||||
LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec);
|
||||
if (image.isNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!image->load(src_filename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Decompress or expand it in a raw image structure
|
||||
LLPointer<LLImageRaw> raw_image = new LLImageRaw;
|
||||
if (!image->decode(raw_image, 0.0f))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Check the image constraints
|
||||
if ((image->getComponents() != 3) && (image->getComponents() != 4))
|
||||
{
|
||||
image->setLastError("Image files with less than 3 or more than 4 components are not supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
raw_image->biasedScaleToPowerOfTwo(1024);
|
||||
mRawImagep = raw_image;
|
||||
mImageLoadError = LLTrans::getString("texture_load_dimensions_error", args);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the image
|
||||
LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec);
|
||||
if (image.isNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!image->load(src_filename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Decompress or expand it in a raw image structure
|
||||
LLPointer<LLImageRaw> raw_image = new LLImageRaw;
|
||||
if (!image->decode(raw_image, 0.0f))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Check the image constraints
|
||||
if ((image->getComponents() != 3) && (image->getComponents() != 4))
|
||||
{
|
||||
image->setLastError("Image files with less than 3 or more than 4 components are not supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
raw_image->biasedScaleToPowerOfTwo(1024);
|
||||
mRawImagep = raw_image;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_UNHANDLED_EXCEPTION("");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1297,7 +1297,7 @@ bool LLViewerTextureList::createUploadFile(LLPointer<LLImageRaw> raw_image,
|
|||
return true;
|
||||
}
|
||||
|
||||
BOOL LLViewerTextureList::createUploadFile(const std::string& filename,
|
||||
bool LLViewerTextureList::createUploadFile(const std::string& filename,
|
||||
const std::string& out_filename,
|
||||
const U8 codec,
|
||||
const S32 max_image_dimentions,
|
||||
|
|
@ -1305,64 +1305,72 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename,
|
|||
bool force_square)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
// Load the image
|
||||
LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec);
|
||||
if (image.isNull())
|
||||
{
|
||||
LL_WARNS() << "Couldn't open the image to be uploaded." << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
if (!image->load(filename))
|
||||
{
|
||||
image->setLastError("Couldn't load the image to be uploaded.");
|
||||
return FALSE;
|
||||
}
|
||||
// Decompress or expand it in a raw image structure
|
||||
LLPointer<LLImageRaw> raw_image = new LLImageRaw;
|
||||
if (!image->decode(raw_image, 0.0f))
|
||||
{
|
||||
image->setLastError("Couldn't decode the image to be uploaded.");
|
||||
return FALSE;
|
||||
}
|
||||
// Check the image constraints
|
||||
if ((image->getComponents() != 3) && (image->getComponents() != 4))
|
||||
{
|
||||
image->setLastError("Image files with less than 3 or more than 4 components are not supported.");
|
||||
return FALSE;
|
||||
}
|
||||
if (image->getWidth() < min_image_dimentions || image->getHeight() < min_image_dimentions)
|
||||
try
|
||||
{
|
||||
std::string reason = llformat("Images below %d x %d pixels are not allowed. Actual size: %d x %dpx",
|
||||
min_image_dimentions,
|
||||
min_image_dimentions,
|
||||
image->getWidth(),
|
||||
image->getHeight());
|
||||
image->setLastError(reason);
|
||||
return FALSE;
|
||||
// Load the image
|
||||
LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec);
|
||||
if (image.isNull())
|
||||
{
|
||||
LL_WARNS() << "Couldn't open the image to be uploaded." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
if (!image->load(filename))
|
||||
{
|
||||
image->setLastError("Couldn't load the image to be uploaded.");
|
||||
return false;
|
||||
}
|
||||
// Decompress or expand it in a raw image structure
|
||||
LLPointer<LLImageRaw> raw_image = new LLImageRaw;
|
||||
if (!image->decode(raw_image, 0.0f))
|
||||
{
|
||||
image->setLastError("Couldn't decode the image to be uploaded.");
|
||||
return false;
|
||||
}
|
||||
// Check the image constraints
|
||||
if ((image->getComponents() != 3) && (image->getComponents() != 4))
|
||||
{
|
||||
image->setLastError("Image files with less than 3 or more than 4 components are not supported.");
|
||||
return false;
|
||||
}
|
||||
if (image->getWidth() < min_image_dimentions || image->getHeight() < min_image_dimentions)
|
||||
{
|
||||
std::string reason = llformat("Images below %d x %d pixels are not allowed. Actual size: %d x %dpx",
|
||||
min_image_dimentions,
|
||||
min_image_dimentions,
|
||||
image->getWidth(),
|
||||
image->getHeight());
|
||||
image->setLastError(reason);
|
||||
return false;
|
||||
}
|
||||
// Convert to j2c (JPEG2000) and save the file locally
|
||||
LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image, max_image_dimentions, force_square);
|
||||
if (compressedImage.isNull())
|
||||
{
|
||||
image->setLastError("Couldn't convert the image to jpeg2000.");
|
||||
LL_INFOS() << "Couldn't convert to j2c, file : " << filename << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
if (!compressedImage->save(out_filename))
|
||||
{
|
||||
image->setLastError("Couldn't create the jpeg2000 image for upload.");
|
||||
LL_INFOS() << "Couldn't create output file : " << out_filename << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
// Test to see if the encode and save worked
|
||||
LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C;
|
||||
if (!integrity_test->loadAndValidate(out_filename))
|
||||
{
|
||||
image->setLastError("The created jpeg2000 image is corrupt.");
|
||||
LL_INFOS() << "Image file : " << out_filename << " is corrupt" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Convert to j2c (JPEG2000) and save the file locally
|
||||
LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image, max_image_dimentions, force_square);
|
||||
if (compressedImage.isNull())
|
||||
{
|
||||
image->setLastError("Couldn't convert the image to jpeg2000.");
|
||||
LL_INFOS() << "Couldn't convert to j2c, file : " << filename << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
if (!compressedImage->save(out_filename))
|
||||
{
|
||||
image->setLastError("Couldn't create the jpeg2000 image for upload.");
|
||||
LL_INFOS() << "Couldn't create output file : " << out_filename << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
// Test to see if the encode and save worked
|
||||
LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C;
|
||||
if (!integrity_test->loadAndValidate( out_filename ))
|
||||
{
|
||||
image->setLastError("The created jpeg2000 image is corrupt.");
|
||||
LL_INFOS() << "Image file : " << out_filename << " is corrupt" << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
catch (...)
|
||||
{
|
||||
LOG_UNHANDLED_EXCEPTION("");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// note: modifies the argument raw_image!!!!
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ public:
|
|||
const std::string& out_filename,
|
||||
const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT,
|
||||
const S32 min_image_dimentions = 0);
|
||||
static BOOL createUploadFile(const std::string& filename,
|
||||
static bool createUploadFile(const std::string& filename,
|
||||
const std::string& out_filename,
|
||||
const U8 codec,
|
||||
const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT,
|
||||
|
|
|
|||
Loading…
Reference in New Issue