summaryrefslogtreecommitdiff
path: root/indra/llimage/llimage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llimage/llimage.cpp')
-rw-r--r--indra/llimage/llimage.cpp215
1 files changed, 129 insertions, 86 deletions
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 08462c7834..f71607096c 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -773,7 +773,8 @@ const U8* LLImageBase::getData() const
{
if(mBadBufferAllocation)
{
- LL_ERRS() << "Bad memory allocation for the image buffer!" << LL_ENDL ;
+ LL_WARNS() << "Bad memory allocation for the image buffer!" << LL_ENDL ;
+ return NULL;
}
return mData;
@@ -783,7 +784,8 @@ U8* LLImageBase::getData()
{
if(mBadBufferAllocation)
{
- LL_ERRS() << "Bad memory allocation for the image buffer!" << LL_ENDL ;
+ LL_WARNS() << "Bad memory allocation for the image buffer!" << LL_ENDL;
+ return NULL;
}
return mData;
@@ -895,30 +897,30 @@ void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components)
sGlobalRawMemory += getDataSize();
}
-BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
+bool LLImageRaw::resize(U16 width, U16 height, S8 components)
{
if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components))
{
- return TRUE;
+ return true;
}
// Reallocate the data buffer.
deleteData();
allocateDataSize(width,height,components);
- return TRUE;
+ return true;
}
-BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
- const U8 *data, U32 stride, BOOL reverse_y)
+bool LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
+ const U8 *data, U32 stride, bool reverse_y)
{
if (!getData())
{
- return FALSE;
+ return false;
}
if (!data)
{
- return FALSE;
+ return false;
}
// Should do some simple bounds checking
@@ -933,13 +935,19 @@ BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
data + from_offset, getComponents()*width);
}
- return TRUE;
+ return true;
}
void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a)
{
llassert( getComponents() <= 4 );
// This is fairly bogus, but it'll do for now.
+ if (isBufferInvalid())
+ {
+ LL_WARNS() << "Invalid image buffer" << LL_ENDL;
+ return;
+ }
+
U8 *pos = getData();
U32 x, y;
for (x = 0; x < getWidth(); x++)
@@ -988,7 +996,7 @@ void LLImageRaw::verticalFlip()
}
-void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
+void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image)
{
// Find new sizes
S32 new_width = expandDimToPowerOfTwo(getWidth(), max_dim);
@@ -997,7 +1005,7 @@ void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
scale( new_width, new_height, scale_image );
}
-void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image)
+void LLImageRaw::contractToPowerOfTwo(S32 max_dim, bool scale_image)
{
// Find new sizes
S32 new_width = contractDimToPowerOfTwo(getWidth(), MIN_IMAGE_SIZE);
@@ -1067,6 +1075,11 @@ void LLImageRaw::composite( LLImageRaw* src )
{
LLImageRaw* dst = this; // Just for clarity.
+ if (!validateSrcAndDst("LLImageRaw::composite", src, dst))
+ {
+ return;
+ }
+
llassert(3 == src->getComponents());
llassert(3 == dst->getComponents());
@@ -1134,7 +1147,6 @@ void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src )
llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
-
U8* src_data = src->getData();
U8* dst_data = dst->getData();
S32 pixels = getWidth() * getHeight();
@@ -1169,6 +1181,11 @@ void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill)
{
LLImageRaw* dst = this; // Just for clarity.
+ if (!validateSrcAndDst("LLImageRaw::copyUnscaledAlphaMask", src, dst))
+ {
+ return;
+ }
+
llassert( 1 == src->getComponents() );
llassert( 4 == dst->getComponents() );
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
@@ -1191,6 +1208,12 @@ void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill)
// Fill the buffer with a constant color
void LLImageRaw::fill( const LLColor4U& color )
{
+ if (isBufferInvalid())
+ {
+ LL_WARNS() << "Invalid image buffer" << LL_ENDL;
+ return;
+ }
+
S32 pixels = getWidth() * getHeight();
if( 4 == getComponents() )
{
@@ -1229,14 +1252,13 @@ LLPointer<LLImageRaw> LLImageRaw::duplicate()
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void LLImageRaw::copy(LLImageRaw* src)
{
- if (!src)
+ LLImageRaw* dst = this; // Just for clarity.
+
+ if (!validateSrcAndDst("LLImageRaw::copy", src, dst))
{
- LL_WARNS() << "LLImageRaw::copy called with a null src pointer" << LL_ENDL;
return;
}
- LLImageRaw* dst = this; // Just for clarity.
-
if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
{
// No scaling needed
@@ -1363,6 +1385,11 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
{
LLImageRaw* dst = this; // Just for clarity.
+ if (!validateSrcAndDst("LLImageRaw::copyScaled", src, dst))
+ {
+ return;
+ }
+
llassert_always( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) );
llassert_always( src->getComponents() == dst->getComponents() );
@@ -1397,86 +1424,83 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
}
-BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
+bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
{
- llassert((1 == getComponents()) || (3 == getComponents()) || (4 == getComponents()) );
+ S32 components = getComponents();
+ if (! ((1 == components) || (3 == components) || (4 == components) ))
+ {
+ LL_WARNS() << "Invalid getComponents value (" << components << ")" << LL_ENDL;
+ return false;
+ }
+
+ if (isBufferInvalid())
+ {
+ LL_WARNS() << "Invalid image buffer" << LL_ENDL;
+ return false;
+ }
S32 old_width = getWidth();
S32 old_height = getHeight();
if( (old_width == new_width) && (old_height == new_height) )
{
- return TRUE; // Nothing to do.
+ return true; // Nothing to do.
}
// Reallocate the data buffer.
if (scale_image_data)
{
- /*
- S32 temp_data_size = old_width * new_height * getComponents();
- llassert_always(temp_data_size > 0);
- std::vector<U8> temp_buffer(temp_data_size);
-
- // Vertical
- for( S32 col = 0; col < old_width; col++ )
- {
- copyLineScaled( getData() + (getComponents() * col), &temp_buffer[0] + (getComponents() * col), old_height, new_height, old_width, old_width );
- }
+ S32 new_data_size = new_width * new_height * components;
- deleteData();
+ if (new_data_size > 0)
+ {
+ U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);
+ if(NULL == new_data)
+ {
+ return false;
+ }
- U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
-
- // Horizontal
- for( S32 row = 0; row < new_height; row++ )
- {
- copyLineScaled( &temp_buffer[0] + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 );
- }
- */
-
- S32 new_data_size = new_width * new_height * getComponents();
- llassert_always(new_data_size > 0);
-
- U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);
- if(NULL == new_data)
- {
- return FALSE;
+ bilinear_scale(getData(), old_width, old_height, components, old_width*components, new_data, new_width, new_height, components, new_width*components);
+ setDataAndSize(new_data, new_width, new_height, components);
}
-
- bilinear_scale(getData(), old_width, old_height, getComponents(), old_width*getComponents(), new_data, new_width, new_height, getComponents(), new_width*getComponents());
- setDataAndSize(new_data, new_width, new_height, getComponents());
}
else
{
// copy out existing image data
- S32 temp_data_size = old_width * old_height * getComponents();
+ S32 temp_data_size = old_width * old_height * components;
std::vector<U8> temp_buffer(temp_data_size);
memcpy(&temp_buffer[0], getData(), temp_data_size);
// allocate new image data, will delete old data
- U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
-
- for( S32 row = 0; row < new_height; row++ )
- {
- if (row < old_height)
- {
- memcpy(new_buffer + (new_width * row * getComponents()), &temp_buffer[0] + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width));
- if (old_width < new_width)
- {
- // pad out rest of row with black
- memset(new_buffer + (getComponents() * ((new_width * row) + old_width)), 0, getComponents() * (new_width - old_width));
- }
- }
- else
- {
- // pad remaining rows with black
- memset(new_buffer + (new_width * row * getComponents()), 0, new_width * getComponents());
- }
- }
- }
-
- return TRUE ;
+ U8* new_buffer = allocateDataSize(new_width, new_height, components);
+
+ if (!new_buffer)
+ {
+ LL_WARNS() << "Failed to allocate new image data buffer" << LL_ENDL;
+ return false;
+ }
+
+ for( S32 row = 0; row < new_height; row++ )
+ {
+ if (row < old_height)
+ {
+ memcpy(new_buffer + (new_width * row * components), &temp_buffer[0] + (old_width * row * components), components * llmin(old_width, new_width));
+ if (old_width < new_width)
+ {
+ // pad out rest of row with black
+ memset(new_buffer + (components * ((new_width * row) + old_width)), 0, components * (new_width - old_width));
+ }
+ }
+ else
+ {
+ // pad remaining rows with black
+ memset(new_buffer + (new_width * row * components), 0, new_width * components);
+ }
+ }
+ }
+
+ return true ;
}
void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step )
@@ -1690,6 +1714,25 @@ void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S3
}
}
+bool LLImageRaw::validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst)
+{
+ if (!src || !dst || src->isBufferInvalid() || dst->isBufferInvalid())
+ {
+ LL_WARNS() << func << ": Source: ";
+ if (!src) LL_CONT << "Null pointer";
+ else if (src->isBufferInvalid()) LL_CONT << "Invalid buffer";
+ else LL_CONT << "OK";
+
+ LL_CONT << "; Destination: ";
+ if (!dst) LL_CONT << "Null pointer";
+ else if (dst->isBufferInvalid()) LL_CONT << "Invalid buffer";
+ else LL_CONT << "OK";
+ LL_CONT << "." << LL_ENDL;
+
+ return false;
+ }
+ return true;
+}
//----------------------------------------------------------------------------
@@ -1795,7 +1838,7 @@ bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip
ifs.read ((char*)buffer, length);
ifs.close();
- BOOL success;
+ bool success;
success = image->updateData();
if (success)
@@ -1971,7 +2014,7 @@ S32 LLImageFormatted::calcDiscardLevelBytes(S32 bytes)
//----------------------------------------------------------------------------
// Subclasses that can handle more than 4 channels should override this function.
-BOOL LLImageFormatted::decodeChannels(LLImageRaw* raw_image,F32 decode_time, S32 first_channel, S32 max_channel)
+bool LLImageFormatted::decodeChannels(LLImageRaw* raw_image,F32 decode_time, S32 first_channel, S32 max_channel)
{
llassert( (first_channel == 0) && (max_channel == 4) );
return decode( raw_image, decode_time ); // Loads first 4 channels by default.
@@ -2022,7 +2065,7 @@ void LLImageFormatted::sanityCheck()
//----------------------------------------------------------------------------
-BOOL LLImageFormatted::copyData(U8 *data, S32 size)
+bool LLImageFormatted::copyData(U8 *data, S32 size)
{
if ( data && ((data != getData()) || (size != getDataSize())) )
{
@@ -2030,7 +2073,7 @@ BOOL LLImageFormatted::copyData(U8 *data, S32 size)
allocateData(size);
memcpy(getData(), data, size); /* Flawfinder: ignore */
}
- return TRUE;
+ return true;
}
// LLImageFormatted becomes the owner of data
@@ -2066,7 +2109,7 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
//----------------------------------------------------------------------------
-BOOL LLImageFormatted::load(const std::string &filename, int load_size)
+bool LLImageFormatted::load(const std::string &filename, int load_size)
{
resetLastError();
@@ -2077,12 +2120,12 @@ BOOL LLImageFormatted::load(const std::string &filename, int load_size)
if (!apr_file)
{
setLastError("Unable to open file for reading", filename);
- return FALSE;
+ return false;
}
if (file_size == 0)
{
setLastError("File is empty",filename);
- return FALSE;
+ return false;
}
// Constrain the load size to acceptable values
@@ -2090,7 +2133,7 @@ BOOL LLImageFormatted::load(const std::string &filename, int load_size)
{
load_size = file_size;
}
- BOOL res;
+ bool res;
U8 *data = allocateData(load_size);
apr_size_t bytes_read = load_size;
apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
@@ -2098,7 +2141,7 @@ BOOL LLImageFormatted::load(const std::string &filename, int load_size)
{
deleteData();
setLastError("Unable to read file",filename);
- res = FALSE;
+ res = false;
}
else
{
@@ -2108,7 +2151,7 @@ BOOL LLImageFormatted::load(const std::string &filename, int load_size)
return res;
}
-BOOL LLImageFormatted::save(const std::string &filename)
+bool LLImageFormatted::save(const std::string &filename)
{
resetLastError();
@@ -2117,15 +2160,15 @@ BOOL LLImageFormatted::save(const std::string &filename)
if (!outfile.getFileHandle())
{
setLastError("Unable to open file for writing", filename);
- return FALSE;
+ return false;
}
outfile.write(getData(), getDataSize());
outfile.close() ;
- return TRUE;
+ return true;
}
-// BOOL LLImageFormatted::save(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
+// bool LLImageFormatted::save(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
// Depricated to remove VFS dependency.
// Use:
// LLVFile::writeFile(image->getData(), image->getDataSize(), vfs, uuid, type);