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.cpp453
1 files changed, 287 insertions, 166 deletions
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index db19bd6ec6..5c33b675ca 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -2,30 +2,25 @@
* @file llimage.cpp
* @brief Base class for images.
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -40,10 +35,47 @@
#include "llimagebmp.h"
#include "llimagetga.h"
#include "llimagej2c.h"
-#if JPEG_SUPPORT
#include "llimagejpeg.h"
-#endif
+#include "llimagepng.h"
#include "llimagedxt.h"
+#include "llimageworker.h"
+
+//---------------------------------------------------------------------------
+// LLImage
+//---------------------------------------------------------------------------
+
+//static
+std::string LLImage::sLastErrorMessage;
+LLMutex* LLImage::sMutex = NULL;
+
+//static
+void LLImage::initClass()
+{
+ sMutex = new LLMutex(NULL);
+ LLImageJ2C::openDSO();
+}
+
+//static
+void LLImage::cleanupClass()
+{
+ LLImageJ2C::closeDSO();
+ delete sMutex;
+ sMutex = NULL;
+}
+
+//static
+const std::string& LLImage::getLastError()
+{
+ static const std::string noerr("No Error");
+ return sLastErrorMessage.empty() ? noerr : sLastErrorMessage;
+}
+
+//static
+void LLImage::setLastError(const std::string& message)
+{
+ LLMutexLock m(sMutex);
+ sLastErrorMessage = message;
+}
//---------------------------------------------------------------------------
// LLImageBase
@@ -55,6 +87,8 @@ LLImageBase::LLImageBase()
mWidth(0),
mHeight(0),
mComponents(0),
+ mBadBufferAllocation(false),
+ mAllowOverSize(false),
mMemType(LLMemType::MTYPE_IMAGEBASE)
{
}
@@ -95,21 +129,6 @@ void LLImageBase::sanityCheck()
}
}
-LLString LLImageBase::sLastErrorMessage;
-BOOL LLImageBase::sSizeOverride = FALSE;
-
-BOOL LLImageBase::setLastError(const LLString& message, const LLString& filename)
-{
- sLastErrorMessage = message;
- if (filename != "")
- {
- sLastErrorMessage += LLString(" FILE:");
- sLastErrorMessage += filename;
- }
- llwarns << sLastErrorMessage << llendl;
- return FALSE;
-}
-
// virtual
void LLImageBase::deleteData()
{
@@ -121,30 +140,42 @@ void LLImageBase::deleteData()
// virtual
U8* LLImageBase::allocateData(S32 size)
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
if (size < 0)
{
size = mWidth * mHeight * mComponents;
if (size <= 0)
{
- llerrs << llformat("LLImageBase::allocateData called with bad dimentions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl;
+ llerrs << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,(S32)mComponents) << llendl;
}
}
- else if (size <= 0 || (size > 4096*4096*16 && sSizeOverride == FALSE))
+
+ //make this function thread-safe.
+ static const U32 MAX_BUFFER_SIZE = 4096 * 4096 * 16 ; //256 MB
+ if (size < 1 || size > MAX_BUFFER_SIZE)
{
- llerrs << "LLImageBase::allocateData: bad size: " << size << llendl;
+ llinfos << "width: " << mWidth << " height: " << mHeight << " components: " << mComponents << llendl ;
+ if(mAllowOverSize)
+ {
+ llinfos << "Oversize: " << size << llendl ;
+ }
+ else
+ {
+ llerrs << "LLImageBase::allocateData: bad size: " << size << llendl;
+ }
}
-
- resetLastError();
-
if (!mData || size != mDataSize)
{
deleteData(); // virtual
+ mBadBufferAllocation = false ;
mData = new U8[size];
if (!mData)
{
- llerrs << "allocate image data: " << size << llendl;
+ llwarns << "allocate image data: " << size << llendl;
+ size = 0 ;
+ mWidth = mHeight = 0 ;
+ mBadBufferAllocation = true ;
}
mDataSize = size;
}
@@ -155,7 +186,7 @@ U8* LLImageBase::allocateData(S32 size)
// virtual
U8* LLImageBase::reallocateData(S32 size)
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
U8 *new_datap = new U8[size];
if (!new_datap)
{
@@ -173,6 +204,30 @@ U8* LLImageBase::reallocateData(S32 size)
return mData;
}
+const U8* LLImageBase::getData() const
+{
+ if(mBadBufferAllocation)
+ {
+ llerrs << "Bad memory allocation for the image buffer!" << llendl ;
+ }
+
+ return mData;
+} // read only
+
+U8* LLImageBase::getData()
+{
+ if(mBadBufferAllocation)
+ {
+ llerrs << "Bad memory allocation for the image buffer!" << llendl ;
+ }
+
+ return mData;
+}
+
+bool LLImageBase::isBufferInvalid()
+{
+ return mBadBufferAllocation || mData == NULL ;
+}
void LLImageBase::setSize(S32 width, S32 height, S32 ncomponents)
{
@@ -205,7 +260,7 @@ LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components)
: LLImageBase()
{
mMemType = LLMemType::MTYPE_IMAGERAW;
- llassert( S32(width) * S32(height) * S32(components) <= MAX_IMAGE_DATA_SIZE );
+ //llassert( S32(width) * S32(height) * S32(components) <= MAX_IMAGE_DATA_SIZE );
allocateDataSize(width, height, components);
++sRawImageCount;
}
@@ -214,12 +269,14 @@ LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
: LLImageBase()
{
mMemType = LLMemType::MTYPE_IMAGERAW;
- allocateDataSize(width, height, components);
- memcpy(getData(), data, width*height*components);
+ if(allocateDataSize(width, height, components))
+ {
+ memcpy(getData(), data, width*height*components);
+ }
++sRawImageCount;
}
-LLImageRaw::LLImageRaw(const LLString &filename, bool j2c_lowest_mip_only)
+LLImageRaw::LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only)
: LLImageBase()
{
createFromFile(filename, j2c_lowest_mip_only);
@@ -257,6 +314,21 @@ void LLImageRaw::deleteData()
LLImageBase::deleteData();
}
+void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components)
+{
+ if(data == getData())
+ {
+ return ;
+ }
+
+ deleteData();
+
+ LLImageBase::setSize(width, height, components) ;
+ LLImageBase::setDataAndSize(data, width * height * components) ;
+
+ sGlobalRawMemory += getDataSize();
+}
+
BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
{
if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components))
@@ -273,7 +345,7 @@ BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
U8 *data = new U8[width*height*getComponents()];
// Should do some simple bounds checking
@@ -356,24 +428,19 @@ void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a)
// Reverses the order of the rows in the image
void LLImageRaw::verticalFlip()
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
S32 row_bytes = getWidth() * getComponents();
- U8* line_buffer = new U8[row_bytes];
- if (!line_buffer )
- {
- llerrs << "Out of memory in LLImageRaw::verticalFlip()" << llendl;
- return;
- }
+ llassert(row_bytes > 0);
+ std::vector<U8> line_buffer(row_bytes);
S32 mid_row = getHeight() / 2;
for( S32 row = 0; row < mid_row; row++ )
{
U8* row_a_data = getData() + row * row_bytes;
U8* row_b_data = getData() + (getHeight() - 1 - row) * row_bytes;
- memcpy( line_buffer, row_a_data, row_bytes ); /* Flawfinder: ignore */
- memcpy( row_a_data, row_b_data, row_bytes ); /* Flawfinder: ignore */
- memcpy( row_b_data, line_buffer, row_bytes ); /* Flawfinder: ignore */
+ memcpy( &line_buffer[0], row_a_data, row_bytes );
+ memcpy( row_a_data, row_b_data, row_bytes );
+ memcpy( row_b_data, &line_buffer[0], row_bytes );
}
- delete[] line_buffer;
}
@@ -460,8 +527,8 @@ void LLImageRaw::composite( LLImageRaw* src )
{
LLImageRaw* dst = this; // Just for clarity.
- llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
- llassert( (3 == dst->getComponents()) || (4 == dst->getComponents()) );
+ llassert(3 == src->getComponents());
+ llassert(3 == dst->getComponents());
if( 3 == dst->getComponents() )
{
@@ -489,39 +556,33 @@ void LLImageRaw::composite( LLImageRaw* src )
}
}
}
- else
- {
- // 4 == dst->mComponents
- llassert(0); // not implemented yet.
- }
}
// Src and dst can be any size. Src has 4 components. Dst has 3 components.
void LLImageRaw::compositeScaled4onto3(LLImageRaw* src)
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
llinfos << "compositeScaled4onto3" << llendl;
LLImageRaw* dst = this; // Just for clarity.
llassert( (4 == src->getComponents()) && (3 == dst->getComponents()) );
- // Vertical: scale but no composite
S32 temp_data_size = src->getWidth() * dst->getHeight() * src->getComponents();
- U8* temp_buffer = new U8[ temp_data_size ];
+ llassert_always(temp_data_size > 0);
+ std::vector<U8> temp_buffer(temp_data_size);
+
+ // Vertical: scale but no composite
for( S32 col = 0; col < src->getWidth(); col++ )
{
- copyLineScaled( src->getData() + (src->getComponents() * col), temp_buffer + (src->getComponents() * col), src->getHeight(), dst->getHeight(), src->getWidth(), src->getWidth() );
+ copyLineScaled( src->getData() + (src->getComponents() * col), &temp_buffer[0] + (src->getComponents() * col), src->getHeight(), dst->getHeight(), src->getWidth(), src->getWidth() );
}
// Horizontal: scale and composite
for( S32 row = 0; row < dst->getHeight(); row++ )
{
- compositeRowScaled4onto3( temp_buffer + (src->getComponents() * src->getWidth() * row), dst->getData() + (dst->getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth() );
+ compositeRowScaled4onto3( &temp_buffer[0] + (src->getComponents() * src->getWidth() * row), dst->getData() + (dst->getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth() );
}
-
- // Clean up
- delete[] temp_buffer;
}
@@ -610,10 +671,13 @@ void LLImageRaw::fill( const LLColor4U& color )
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void LLImageRaw::copy(LLImageRaw* src)
{
- LLImageRaw* dst = this; // Just for clarity.
+ if (!src)
+ {
+ llwarns << "LLImageRaw::copy called with a null src pointer" << llendl;
+ return;
+ }
- llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
- llassert( (3 == dst->getComponents()) || (4 == dst->getComponents()) );
+ LLImageRaw* dst = this; // Just for clarity.
if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
{
@@ -659,7 +723,7 @@ void LLImageRaw::copyUnscaled(LLImageRaw* src)
{
LLImageRaw* dst = this; // Just for clarity.
- llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
+ llassert( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) );
llassert( src->getComponents() == dst->getComponents() );
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
@@ -739,11 +803,11 @@ void LLImageRaw::copyUnscaled3onto4( LLImageRaw* src )
// Src and dst can be any size. Src and dst have same number of components.
void LLImageRaw::copyScaled( LLImageRaw* src )
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
LLImageRaw* dst = this; // Just for clarity.
- llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
- llassert( src->getComponents() == dst->getComponents() );
+ llassert_always( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) );
+ llassert_always( src->getComponents() == dst->getComponents() );
if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
{
@@ -751,48 +815,94 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
return;
}
- // Vertical
S32 temp_data_size = src->getWidth() * dst->getHeight() * getComponents();
- U8* temp_buffer = new U8[ temp_data_size ];
+ llassert_always(temp_data_size > 0);
+ std::vector<U8> temp_buffer(temp_data_size);
+
+ // Vertical
for( S32 col = 0; col < src->getWidth(); col++ )
{
- copyLineScaled( src->getData() + (getComponents() * col), temp_buffer + (getComponents() * col), src->getHeight(), dst->getHeight(), src->getWidth(), src->getWidth() );
+ copyLineScaled( src->getData() + (getComponents() * col), &temp_buffer[0] + (getComponents() * col), src->getHeight(), dst->getHeight(), src->getWidth(), src->getWidth() );
}
// Horizontal
for( S32 row = 0; row < dst->getHeight(); row++ )
{
- copyLineScaled( temp_buffer + (getComponents() * src->getWidth() * row), dst->getData() + (getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth(), 1, 1 );
+ copyLineScaled( &temp_buffer[0] + (getComponents() * src->getWidth() * row), dst->getData() + (getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth(), 1, 1 );
}
-
- // Clean up
- delete[] temp_buffer;
}
+//scale down image by not blending a pixel with its neighbors.
+BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
+{
+ LLMemType mt1(mMemType);
+
+ S8 c = getComponents() ;
+ llassert((1 == c) || (3 == c) || (4 == c) );
+
+ S32 old_width = getWidth();
+ S32 old_height = getHeight();
+
+ S32 new_data_size = old_width * new_height * c ;
+ llassert_always(new_data_size > 0);
+
+ F32 ratio_x = (F32)old_width / new_width ;
+ F32 ratio_y = (F32)old_height / new_height ;
+ if( ratio_x < 1.0f || ratio_y < 1.0f )
+ {
+ return TRUE; // Nothing to do.
+ }
+ ratio_x -= 1.0f ;
+ ratio_y -= 1.0f ;
+
+ U8* new_data = new U8[new_data_size] ;
+ llassert_always(new_data != NULL) ;
+
+ U8* old_data = getData() ;
+ S32 i, j, k, s, t;
+ for(i = 0, s = 0, t = 0 ; i < new_height ; i++)
+ {
+ for(j = 0 ; j < new_width ; j++)
+ {
+ for(k = 0 ; k < c ; k++)
+ {
+ new_data[s++] = old_data[t++] ;
+ }
+ t += (S32)(ratio_x * c + 0.1f) ;
+ }
+ t += (S32)(ratio_y * old_width * c + 0.1f) ;
+ }
+
+ setDataAndSize(new_data, new_width, new_height, c) ;
+
+ return TRUE ;
+}
-void 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 )
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
- llassert( (3 == getComponents()) || (4 == getComponents()) );
+ LLMemType mt1(mMemType);
+ llassert((1 == getComponents()) || (3 == getComponents()) || (4 == getComponents()) );
S32 old_width = getWidth();
S32 old_height = getHeight();
if( (old_width == new_width) && (old_height == new_height) )
{
- return; // Nothing to do.
+ return TRUE; // Nothing to do.
}
// Reallocate the data buffer.
if (scale_image_data)
{
- // Vertical
S32 temp_data_size = old_width * new_height * getComponents();
- U8* temp_buffer = new U8[ temp_data_size ];
+ 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 + (getComponents() * col), old_height, new_height, old_width, old_width );
+ copyLineScaled( getData() + (getComponents() * col), &temp_buffer[0] + (getComponents() * col), old_height, new_height, old_width, old_width );
}
deleteData();
@@ -802,23 +912,15 @@ void LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
// Horizontal
for( S32 row = 0; row < new_height; row++ )
{
- copyLineScaled( temp_buffer + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 );
+ copyLineScaled( &temp_buffer[0] + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 );
}
-
- // Clean up
- delete[] temp_buffer;
}
else
{
// copy out existing image data
S32 temp_data_size = old_width * old_height * getComponents();
- U8* temp_buffer = new U8[ temp_data_size ];
- if (!temp_buffer)
- {
- llerrs << "Out of memory in LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )" << llendl;
- return;
- }
- memcpy(temp_buffer, getData(), temp_data_size); /* Flawfinder: ignore */
+ 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());
@@ -827,7 +929,7 @@ void LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
{
if (row < old_height)
{
- memcpy(new_buffer + (new_width * row * getComponents()), temp_buffer + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width)); /* Flawfinder: ignore */
+ 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
@@ -840,10 +942,9 @@ void LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
memset(new_buffer + (new_width * row * getComponents()), 0, new_width * getComponents());
}
}
-
- // Clean up
- delete[] temp_buffer;
}
+
+ 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 )
@@ -1063,7 +1164,7 @@ void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S3
static struct
{
const char* exten;
- S8 codec;
+ EImageCodec codec;
}
file_extensions[] =
{
@@ -1078,27 +1179,27 @@ file_extensions[] =
{ "dxt", IMG_CODEC_DXT },
{ "png", IMG_CODEC_PNG }
};
-#define NUM_FILE_EXTENSIONS sizeof(file_extensions)/sizeof(file_extensions[0])
+#define NUM_FILE_EXTENSIONS LL_ARRAY_SIZE(file_extensions)
-static LLString find_file(LLString &name, S8 *codec)
+static std::string find_file(std::string &name, S8 *codec)
{
- LLString tname;
+ std::string tname;
for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++)
{
- tname = name + "." + LLString(file_extensions[i].exten);
- llifstream ifs(tname.c_str(), llifstream::binary);
+ tname = name + "." + std::string(file_extensions[i].exten);
+ llifstream ifs(tname, llifstream::binary);
if (ifs.is_open())
{
ifs.close();
if (codec)
*codec = file_extensions[i].codec;
- return LLString(file_extensions[i].exten);
+ return std::string(file_extensions[i].exten);
}
}
- return LLString("");
+ return std::string("");
}
-static S8 get_codec(const LLString& exten)
+EImageCodec LLImageBase::getCodecFromExtension(const std::string& exten)
{
for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++)
{
@@ -1108,20 +1209,20 @@ static S8 get_codec(const LLString& exten)
return IMG_CODEC_INVALID;
}
-bool LLImageRaw::createFromFile(const LLString &filename, bool j2c_lowest_mip_only)
+bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip_only)
{
- LLString name = filename;
+ std::string name = filename;
size_t dotidx = name.rfind('.');
S8 codec = IMG_CODEC_INVALID;
- LLString exten;
+ std::string exten;
deleteData(); // delete any existing data
- if (dotidx != LLString::npos)
+ if (dotidx != std::string::npos)
{
exten = name.substr(dotidx+1);
- LLString::toLower(exten);
- codec = get_codec(exten);
+ LLStringUtil::toLower(exten);
+ codec = getCodecFromExtension(exten);
}
else
{
@@ -1133,7 +1234,7 @@ bool LLImageRaw::createFromFile(const LLString &filename, bool j2c_lowest_mip_on
return false; // format not recognized
}
- llifstream ifs(name.c_str(), llifstream::binary);
+ llifstream ifs(name, llifstream::binary);
if (!ifs.is_open())
{
// SJB: changed from llinfos to lldebugs to reduce spam
@@ -1165,11 +1266,9 @@ bool LLImageRaw::createFromFile(const LLString &filename, bool j2c_lowest_mip_on
case IMG_CODEC_TGA:
image = new LLImageTGA();
break;
-#if JPEG_SUPPORT
case IMG_CODEC_JPEG:
image = new LLImageJPEG();
break;
-#endif
case IMG_CODEC_J2C:
image = new LLImageJ2C();
break;
@@ -1182,28 +1281,31 @@ bool LLImageRaw::createFromFile(const LLString &filename, bool j2c_lowest_mip_on
llassert(image.notNull());
U8 *buffer = image->allocateData(length);
- ifs.read ((char*)buffer, length); /* Flawfinder: ignore */
+ ifs.read ((char*)buffer, length);
ifs.close();
- image->updateData();
-
- if (j2c_lowest_mip_only && codec == IMG_CODEC_J2C)
+ BOOL success;
+
+ success = image->updateData();
+ if (success)
{
- S32 width = image->getWidth();
- S32 height = image->getHeight();
- S32 discard_level = 0;
- while (width > 1 && height > 1 && discard_level < MAX_DISCARD_LEVEL)
+ if (j2c_lowest_mip_only && codec == IMG_CODEC_J2C)
{
- width >>= 1;
- height >>= 1;
- discard_level++;
+ S32 width = image->getWidth();
+ S32 height = image->getHeight();
+ S32 discard_level = 0;
+ while (width > 1 && height > 1 && discard_level < MAX_DISCARD_LEVEL)
+ {
+ width >>= 1;
+ height >>= 1;
+ discard_level++;
+ }
+ ((LLImageJ2C *)((LLImageFormatted*)image))->setDiscardLevel(discard_level);
}
- ((LLImageJ2C *)((LLImageFormatted*)image))->setDiscardLevel(discard_level);
+ success = image->decode(this, 100000.0f);
}
-
- BOOL success = image->decode(this, 100000.0f);
- image = NULL; // deletes image
+ image = NULL; // deletes image
if (!success)
{
deleteData();
@@ -1226,7 +1328,7 @@ LLImageFormatted::LLImageFormatted(S8 codec)
mCodec(codec),
mDecoding(0),
mDecoded(0),
- mDiscardLevel(0)
+ mDiscardLevel(-1)
{
mMemType = LLMemType::MTYPE_IMAGEFORMATTED;
}
@@ -1241,6 +1343,23 @@ LLImageFormatted::~LLImageFormatted()
//----------------------------------------------------------------------------
+//virtual
+void LLImageFormatted::resetLastError()
+{
+ LLImage::setLastError("");
+}
+
+//virtual
+void LLImageFormatted::setLastError(const std::string& message, const std::string& filename)
+{
+ std::string error = message;
+ if (!filename.empty())
+ error += std::string(" FILE: ") + filename;
+ LLImage::setLastError(error);
+}
+
+//----------------------------------------------------------------------------
+
// static
LLImageFormatted* LLImageFormatted::createFromType(S8 codec)
{
@@ -1253,11 +1372,12 @@ LLImageFormatted* LLImageFormatted::createFromType(S8 codec)
case IMG_CODEC_TGA:
image = new LLImageTGA();
break;
-#if JPEG_SUPPORT
case IMG_CODEC_JPEG:
image = new LLImageJPEG();
break;
-#endif
+ case IMG_CODEC_PNG:
+ image = new LLImagePNG();
+ break;
case IMG_CODEC_J2C:
image = new LLImageJ2C();
break;
@@ -1272,11 +1392,11 @@ LLImageFormatted* LLImageFormatted::createFromType(S8 codec)
}
// static
-LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring)
+LLImageFormatted* LLImageFormatted::createFromExtension(const std::string& instring)
{
- LLString exten;
+ std::string exten;
size_t dotidx = instring.rfind('.');
- if (dotidx != LLString::npos)
+ if (dotidx != std::string::npos)
{
exten = instring.substr(dotidx+1);
}
@@ -1284,7 +1404,7 @@ LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring
{
exten = instring;
}
- S8 codec = get_codec(exten);
+ S8 codec = getCodecFromExtension(exten);
return createFromType(codec);
}
//----------------------------------------------------------------------------
@@ -1340,7 +1460,7 @@ S32 LLImageFormatted::calcDiscardLevelBytes(S32 bytes)
//----------------------------------------------------------------------------
// Subclasses that can handle more than 4 channels should override this function.
-BOOL LLImageFormatted::decode(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.
@@ -1427,18 +1547,21 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
S32 newsize = cursize + size;
reallocateData(newsize);
memcpy(getData() + cursize, data, size);
+ delete[] data;
}
}
}
//----------------------------------------------------------------------------
-BOOL LLImageFormatted::load(const LLString &filename)
+BOOL LLImageFormatted::load(const std::string &filename)
{
resetLastError();
S32 file_size = 0;
- apr_file_t* apr_file = ll_apr_file_open(filename, LL_APR_RB, &file_size);
+ LLAPRFile infile ;
+ infile.open(filename, LL_APR_RB, NULL, &file_size);
+ apr_file_t* apr_file = infile.getFileHandle();
if (!apr_file)
{
setLastError("Unable to open file for reading", filename);
@@ -1447,7 +1570,6 @@ BOOL LLImageFormatted::load(const LLString &filename)
if (file_size == 0)
{
setLastError("File is empty",filename);
- apr_file_close(apr_file);
return FALSE;
}
@@ -1465,25 +1587,24 @@ BOOL LLImageFormatted::load(const LLString &filename)
{
res = updateData();
}
- apr_file_close(apr_file);
-
+
return res;
}
-BOOL LLImageFormatted::save(const LLString &filename)
+BOOL LLImageFormatted::save(const std::string &filename)
{
resetLastError();
- apr_file_t* apr_file = ll_apr_file_open(filename, LL_APR_WB);
- if (!apr_file)
+ LLAPRFile outfile ;
+ outfile.open(filename, LL_APR_WB);
+ if (!outfile.getFileHandle())
{
- setLastError("Unable to open file for reading", filename);
+ setLastError("Unable to open file for writing", filename);
return FALSE;
}
- ll_apr_file_write(apr_file, getData(), getDataSize());
- apr_file_close(apr_file);
-
+ outfile.write(getData(), getDataSize());
+ outfile.close() ;
return TRUE;
}