aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llimage
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llimage/files.lst3
-rw-r--r--linden/indra/llimage/llimage.cpp283
-rw-r--r--linden/indra/llimage/llimage.h41
-rw-r--r--linden/indra/llimage/llimage.vcproj6
-rw-r--r--linden/indra/llimage/llimage_vc8.vcproj306
-rw-r--r--linden/indra/llimage/llimagebmp.cpp20
-rw-r--r--linden/indra/llimage/llimagedxt.cpp24
-rw-r--r--linden/indra/llimage/llimagedxt.h5
-rw-r--r--linden/indra/llimage/llimagej2c.cpp28
-rw-r--r--linden/indra/llimage/llimagej2c.h12
-rw-r--r--linden/indra/llimage/llimagejpeg.cpp11
-rw-r--r--linden/indra/llimage/llimagetga.cpp15
-rw-r--r--linden/indra/llimage/llimageworker.cpp184
-rw-r--r--linden/indra/llimage/llimageworker.h76
-rw-r--r--linden/indra/llimagej2coj/llimagej2coj.cpp80
-rw-r--r--linden/indra/llimagej2coj/llimagej2coj.h5
16 files changed, 790 insertions, 309 deletions
diff --git a/linden/indra/llimage/files.lst b/linden/indra/llimage/files.lst
index 83f53bc..9e14118 100644
--- a/linden/indra/llimage/files.lst
+++ b/linden/indra/llimage/files.lst
@@ -3,4 +3,5 @@ llimage/llimage.cpp
3llimage/llimagedxt.cpp 3llimage/llimagedxt.cpp
4llimage/llimagej2c.cpp 4llimage/llimagej2c.cpp
5llimage/llimagejpeg.cpp 5llimage/llimagejpeg.cpp
6llimage/llimagetga.cpp \ No newline at end of file 6llimage/llimagetga.cpp
7llimage/llimageworker.cpp
diff --git a/linden/indra/llimage/llimage.cpp b/linden/indra/llimage/llimage.cpp
index acd6aef..eb4ff46 100644
--- a/linden/indra/llimage/llimage.cpp
+++ b/linden/indra/llimage/llimage.cpp
@@ -36,7 +36,7 @@
36#include "llmath.h" 36#include "llmath.h"
37#include "stdtypes.h" 37#include "stdtypes.h"
38#include "v4coloru.h" 38#include "v4coloru.h"
39#include "llmemory.h" 39#include "llmemtype.h"
40 40
41#include "llimage.h" 41#include "llimage.h"
42#include "llimagebmp.h" 42#include "llimagebmp.h"
@@ -133,7 +133,7 @@ U8* LLImageBase::allocateData(S32 size)
133 llerrs << llformat("LLImageBase::allocateData called with bad dimentions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl; 133 llerrs << llformat("LLImageBase::allocateData called with bad dimentions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl;
134 } 134 }
135 } 135 }
136 else if ((size <= 0 || size > 4096*4096*16) && sSizeOverride == FALSE) 136 else if (size <= 0 || (size > 4096*4096*16 && sSizeOverride == FALSE))
137 { 137 {
138 llerrs << "LLImageBase::allocateData: bad size: " << size << llendl; 138 llerrs << "LLImageBase::allocateData: bad size: " << size << llendl;
139 } 139 }
@@ -167,7 +167,7 @@ U8* LLImageBase::reallocateData(S32 size)
167 if (mData) 167 if (mData)
168 { 168 {
169 S32 bytes = llmin(mDataSize, size); 169 S32 bytes = llmin(mDataSize, size);
170 memcpy(new_datap, mData, bytes); 170 memcpy(new_datap, mData, bytes); /* Flawfinder: ignore */
171 delete[] mData; 171 delete[] mData;
172 } 172 }
173 mData = new_datap; 173 mData = new_datap;
@@ -216,7 +216,8 @@ LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
216 : LLImageBase() 216 : LLImageBase()
217{ 217{
218 mMemType = LLMemType::MTYPE_IMAGERAW; 218 mMemType = LLMemType::MTYPE_IMAGERAW;
219 copyData(data, width, height, components); 219 allocateDataSize(width, height, components);
220 memcpy(getData(), data, width*height*components);
220 ++sRawImageCount; 221 ++sRawImageCount;
221} 222}
222 223
@@ -258,16 +259,6 @@ void LLImageRaw::deleteData()
258 LLImageBase::deleteData(); 259 LLImageBase::deleteData();
259} 260}
260 261
261BOOL LLImageRaw::copyData(U8 *data, U16 width, U16 height, S8 components)
262{
263 if (!resize(width, height, components))
264 {
265 return FALSE;
266 }
267 memcpy(getData(), data, width*height*components);
268 return TRUE;
269}
270
271BOOL LLImageRaw::resize(U16 width, U16 height, S8 components) 262BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
272{ 263{
273 if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components)) 264 if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components))
@@ -288,11 +279,16 @@ U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const
288 U8 *data = new U8[width*height*getComponents()]; 279 U8 *data = new U8[width*height*getComponents()];
289 280
290 // Should do some simple bounds checking 281 // Should do some simple bounds checking
282 if (!data)
283 {
284 llerrs << "Out of memory in LLImageRaw::getSubImage" << llendl;
285 return NULL;
286 }
291 287
292 U32 i; 288 U32 i;
293 for (i = y_pos; i < y_pos+height; i++) 289 for (i = y_pos; i < y_pos+height; i++)
294 { 290 {
295 memcpy(data + i*width*getComponents(), 291 memcpy(data + i*width*getComponents(), /* Flawfinder: ignore */
296 getData() + ((y_pos + i)*getWidth() + x_pos)*getComponents(), getComponents()*width); 292 getData() + ((y_pos + i)*getWidth() + x_pos)*getComponents(), getComponents()*width);
297 } 293 }
298 return data; 294 return data;
@@ -328,7 +324,7 @@ BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
328 { 324 {
329 from_offset = i*width*getComponents(); 325 from_offset = i*width*getComponents();
330 } 326 }
331 memcpy(getData() + to_offset*getComponents(), 327 memcpy(getData() + to_offset*getComponents(), /* Flawfinder: ignore */
332 data + from_offset, getComponents()*width); 328 data + from_offset, getComponents()*width);
333 } 329 }
334 } 330 }
@@ -345,7 +341,7 @@ BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
345 { 341 {
346 from_offset = (height - 1 - i)*width*getComponents(); 342 from_offset = (height - 1 - i)*width*getComponents();
347 } 343 }
348 memcpy(getData() + to_offset*getComponents(), 344 memcpy(getData() + to_offset*getComponents(), /* Flawfinder: ignore */
349 data + from_offset, getComponents()*width); 345 data + from_offset, getComponents()*width);
350 } 346 }
351 } 347 }
@@ -392,14 +388,19 @@ void LLImageRaw::verticalFlip()
392 LLMemType mt1((LLMemType::EMemType)mMemType); 388 LLMemType mt1((LLMemType::EMemType)mMemType);
393 S32 row_bytes = getWidth() * getComponents(); 389 S32 row_bytes = getWidth() * getComponents();
394 U8* line_buffer = new U8[row_bytes]; 390 U8* line_buffer = new U8[row_bytes];
391 if (!line_buffer )
392 {
393 llerrs << "Out of memory in LLImageRaw::verticalFlip()" << llendl;
394 return;
395 }
395 S32 mid_row = getHeight() / 2; 396 S32 mid_row = getHeight() / 2;
396 for( S32 row = 0; row < mid_row; row++ ) 397 for( S32 row = 0; row < mid_row; row++ )
397 { 398 {
398 U8* row_a_data = getData() + row * row_bytes; 399 U8* row_a_data = getData() + row * row_bytes;
399 U8* row_b_data = getData() + (getHeight() - 1 - row) * row_bytes; 400 U8* row_b_data = getData() + (getHeight() - 1 - row) * row_bytes;
400 memcpy( line_buffer, row_a_data, row_bytes ); 401 memcpy( line_buffer, row_a_data, row_bytes ); /* Flawfinder: ignore */
401 memcpy( row_a_data, row_b_data, row_bytes ); 402 memcpy( row_a_data, row_b_data, row_bytes ); /* Flawfinder: ignore */
402 memcpy( row_b_data, line_buffer, row_bytes ); 403 memcpy( row_b_data, line_buffer, row_bytes ); /* Flawfinder: ignore */
403 } 404 }
404 delete[] line_buffer; 405 delete[] line_buffer;
405} 406}
@@ -691,7 +692,7 @@ void LLImageRaw::copyUnscaled(LLImageRaw* src)
691 llassert( src->getComponents() == dst->getComponents() ); 692 llassert( src->getComponents() == dst->getComponents() );
692 llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); 693 llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
693 694
694 memcpy( dst->getData(), src->getData(), getWidth() * getHeight() * getComponents() ); 695 memcpy( dst->getData(), src->getData(), getWidth() * getHeight() * getComponents() ); /* Flawfinder: ignore */
695} 696}
696 697
697 698
@@ -775,7 +776,7 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
775 776
776 if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ) 777 if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
777 { 778 {
778 memcpy( dst->getData(), src->getData(), getWidth() * getHeight() * getComponents() ); 779 memcpy( dst->getData(), src->getData(), getWidth() * getHeight() * getComponents() ); /* Flawfinder: ignore */
779 return; 780 return;
780 } 781 }
781 782
@@ -841,7 +842,12 @@ void LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
841 // copy out existing image data 842 // copy out existing image data
842 S32 temp_data_size = old_width * old_height * getComponents(); 843 S32 temp_data_size = old_width * old_height * getComponents();
843 U8* temp_buffer = new U8[ temp_data_size ]; 844 U8* temp_buffer = new U8[ temp_data_size ];
844 memcpy(temp_buffer, getData(), temp_data_size); 845 if (!temp_buffer)
846 {
847 llerrs << "Out of memory in LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )" << llendl;
848 return;
849 }
850 memcpy(temp_buffer, getData(), temp_data_size); /* Flawfinder: ignore */
845 851
846 // allocate new image data, will delete old data 852 // allocate new image data, will delete old data
847 U8* new_buffer = allocateDataSize(new_width, new_height, getComponents()); 853 U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
@@ -850,7 +856,7 @@ void LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
850 { 856 {
851 if (row < old_height) 857 if (row < old_height)
852 { 858 {
853 memcpy(new_buffer + (new_width * row * getComponents()), temp_buffer + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width)); 859 memcpy(new_buffer + (new_width * row * getComponents()), temp_buffer + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width)); /* Flawfinder: ignore */
854 if (old_width < new_width) 860 if (old_width < new_width)
855 { 861 {
856 // pad out rest of row with black 862 // pad out rest of row with black
@@ -1204,7 +1210,7 @@ bool LLImageRaw::createFromFile(const LLString &filename, bool j2c_lowest_mip_on
1204 llassert(image.notNull()); 1210 llassert(image.notNull());
1205 1211
1206 U8 *buffer = image->allocateData(length); 1212 U8 *buffer = image->allocateData(length);
1207 ifs.read ((char*)buffer, length); 1213 ifs.read ((char*)buffer, length); /* Flawfinder: ignore */
1208 ifs.close(); 1214 ifs.close();
1209 1215
1210 image->updateData(); 1216 image->updateData();
@@ -1243,25 +1249,8 @@ bool LLImageRaw::createFromFile(const LLString &filename, bool j2c_lowest_mip_on
1243//static 1249//static
1244S32 LLImageFormatted::sGlobalFormattedMemory = 0; 1250S32 LLImageFormatted::sGlobalFormattedMemory = 0;
1245 1251
1246//static
1247LLWorkerThread* LLImageFormatted::sWorkerThread = NULL;
1248
1249//static
1250void LLImageFormatted::initClass(bool threaded, bool run_always)
1251{
1252 sWorkerThread = new LLWorkerThread(threaded, run_always);
1253}
1254
1255//static
1256void LLImageFormatted::cleanupClass()
1257{
1258 delete sWorkerThread;
1259 sWorkerThread = NULL;
1260}
1261
1262
1263LLImageFormatted::LLImageFormatted(S8 codec) 1252LLImageFormatted::LLImageFormatted(S8 codec)
1264 : LLImageBase(), LLWorkerClass(sWorkerThread, "ImageFormatted"), 1253 : LLImageBase(),
1265 mCodec(codec), 1254 mCodec(codec),
1266 mDecoding(0), 1255 mDecoding(0),
1267 mDecoded(0), 1256 mDecoded(0),
@@ -1276,64 +1265,14 @@ LLImageFormatted::~LLImageFormatted()
1276 // NOTE: ~LLimageBase() call to deleteData() calls LLImageBase::deleteData() 1265 // NOTE: ~LLimageBase() call to deleteData() calls LLImageBase::deleteData()
1277 // NOT LLImageFormatted::deleteData() 1266 // NOT LLImageFormatted::deleteData()
1278 deleteData(); 1267 deleteData();
1279 releaseDecodedData();
1280}
1281
1282//----------------------------------------------------------------------------
1283
1284//virtual
1285void LLImageFormatted::startWork(S32 param)
1286{
1287 if (mDecoding) llerrs << "WTF?" << llendl;
1288}
1289
1290bool LLImageFormatted::doWork(S32 param)
1291{
1292 if (!(isWorking())) llerrs << "WTF?" << llendl;
1293 llassert(mDecodedImage.notNull());
1294 if (param == 0)
1295 {
1296 // Decode primary channels
1297 mDecoded = decode(mDecodedImage, .001f); // 1ms
1298 }
1299 else
1300 {
1301 // Decode aux channel
1302 mDecoded = decode(mDecodedImage, .001f, param, param); // 1ms
1303 }
1304 if (mDecoded)
1305 {
1306 return true;
1307 }
1308 else
1309 {
1310 return false;
1311 }
1312}
1313
1314void LLImageFormatted::endWork(S32 param, bool aborted)
1315{
1316 if (mDecoding) llerrs << "WTF?" << llendl;
1317 if (!mDecoded) llerrs << "WTF?" << llendl;
1318} 1268}
1319 1269
1320//---------------------------------------------------------------------------- 1270//----------------------------------------------------------------------------
1321 1271
1322// static 1272// static
1323LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring) 1273LLImageFormatted* LLImageFormatted::createFromType(S8 codec)
1324{ 1274{
1325 LLString exten; 1275 LLImageFormatted* image;
1326 size_t dotidx = instring.rfind('.');
1327 if (dotidx != LLString::npos)
1328 {
1329 exten = instring.substr(dotidx+1);
1330 }
1331 else
1332 {
1333 exten = instring;
1334 }
1335 S8 codec = get_codec(exten);
1336 LLPointer<LLImageFormatted> image;
1337 switch(codec) 1276 switch(codec)
1338 { 1277 {
1339 case IMG_CODEC_BMP: 1278 case IMG_CODEC_BMP:
@@ -1354,10 +1293,28 @@ LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring
1354 image = new LLImageDXT(); 1293 image = new LLImageDXT();
1355 break; 1294 break;
1356 default: 1295 default:
1296 image = NULL;
1357 break; 1297 break;
1358 } 1298 }
1359 return image; 1299 return image;
1360} 1300}
1301
1302// static
1303LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring)
1304{
1305 LLString exten;
1306 size_t dotidx = instring.rfind('.');
1307 if (dotidx != LLString::npos)
1308 {
1309 exten = instring.substr(dotidx+1);
1310 }
1311 else
1312 {
1313 exten = instring;
1314 }
1315 S8 codec = get_codec(exten);
1316 return createFromType(codec);
1317}
1361//---------------------------------------------------------------------------- 1318//----------------------------------------------------------------------------
1362 1319
1363// virtual 1320// virtual
@@ -1374,15 +1331,6 @@ void LLImageFormatted::dump()
1374 1331
1375//---------------------------------------------------------------------------- 1332//----------------------------------------------------------------------------
1376 1333
1377void LLImageFormatted::readHeader(U8* data, S32 size)
1378{
1379 if (size <= 0)
1380 {
1381 size = calcHeaderSize();
1382 }
1383 copyData(data, size); // calls updateData()
1384}
1385
1386S32 LLImageFormatted::calcDataSize(S32 discard_level) 1334S32 LLImageFormatted::calcDataSize(S32 discard_level)
1387{ 1335{
1388 if (discard_level < 0) 1336 if (discard_level < 0)
@@ -1426,82 +1374,6 @@ BOOL LLImageFormatted::decode(LLImageRaw* raw_image,F32 decode_time, S32 first_
1426 return decode( raw_image, decode_time ); // Loads first 4 channels by default. 1374 return decode( raw_image, decode_time ); // Loads first 4 channels by default.
1427} 1375}
1428 1376
1429// virtual
1430BOOL LLImageFormatted::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard, F32 decode_time)
1431{
1432 llassert(getData() && getDataSize());
1433 // For most codecs, only mDiscardLevel data is available. (see LLImageDXT for exception)
1434 if (discard >= 0 && discard != mDiscardLevel)
1435 {
1436 llerrs << "Request for invalid discard level" << llendl;
1437 }
1438 if (haveWork())
1439 {
1440 checkWork();
1441 }
1442 if (!mDecoded)
1443 {
1444 if (!haveWork())
1445 {
1446 llassert(!mDecoding);
1447 mDecodedImage = new LLImageRaw(getWidth(), getHeight(), getComponents());
1448 addWork(0);
1449 }
1450 return FALSE;
1451 }
1452 else
1453 {
1454 llassert(mDecodedImage.notNull());
1455 llassert(!mDecoding);
1456 raw = mDecodedImage;
1457 return TRUE;
1458 }
1459}
1460
1461BOOL LLImageFormatted::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel,
1462 S32 discard, F32 decode_time)
1463{
1464 llassert(getData() && getDataSize());
1465 // For most codecs, only mDiscardLevel data is available. (see LLImageDXT for exception)
1466 if (discard >= 0 && discard != mDiscardLevel)
1467 {
1468 llerrs << "Request for invalid discard level" << llendl;
1469 }
1470 if (haveWork())
1471 {
1472 checkWork();
1473 }
1474 if (!mDecoded)
1475 {
1476 if (!haveWork())
1477 {
1478 llassert(!mDecoding);
1479 mDecodedImage = new LLImageRaw(getWidth(), getHeight(), 1);
1480 addWork(channel);
1481 }
1482 return FALSE;
1483 }
1484 else
1485 {
1486 llassert(mDecodedImage.notNull());
1487 llassert(!mDecoding);
1488 raw = mDecodedImage;
1489 return TRUE;
1490 }
1491}
1492
1493
1494// virtual
1495void LLImageFormatted::releaseDecodedData()
1496{
1497 if (mDecoded || mDecoding)
1498 {
1499 mDecodedImage = NULL; // deletes image
1500 mDecoded = FALSE;
1501 mDecoding = FALSE;
1502 }
1503}
1504
1505//---------------------------------------------------------------------------- 1377//----------------------------------------------------------------------------
1506 1378
1507// virtual 1379// virtual
@@ -1549,47 +1421,42 @@ void LLImageFormatted::sanityCheck()
1549 1421
1550BOOL LLImageFormatted::copyData(U8 *data, S32 size) 1422BOOL LLImageFormatted::copyData(U8 *data, S32 size)
1551{ 1423{
1552 if (data && data != getData()) 1424 if ( (data && data != getData()) || (size != getDataSize()) )
1553 { 1425 {
1554 deleteData(); 1426 deleteData();
1555 allocateData(size); 1427 allocateData(size);
1556 memcpy(getData(), data, size); 1428 memcpy(getData(), data, size); /* Flawfinder: ignore */
1557 } 1429 }
1558 updateData(); // virtual
1559
1560 return TRUE; 1430 return TRUE;
1561} 1431}
1562 1432
1563BOOL LLImageFormatted::appendData(U8 *data, S32 size) 1433// LLImageFormatted becomes the owner of data
1434void LLImageFormatted::setData(U8 *data, S32 size)
1564{ 1435{
1565 LLMemType mt1((LLMemType::EMemType)mMemType); 1436 if (data && data != getData())
1566 S32 old_size = getDataSize();
1567 U8* old_data = getData();
1568 S32 new_size = old_size + size;
1569 U8* new_data = new U8[new_size];
1570 // resize the image
1571 setDataAndSize(new_data, new_size);
1572 // copy the old data and delete it
1573 memcpy(new_data, old_data, old_size);
1574 delete old_data;
1575 // if we have new data, copy it and call updateData()
1576 if (data)
1577 { 1437 {
1578 memcpy(new_data + old_size, data, size); 1438 deleteData();
1579 updateData(); // virtual 1439 setDataAndSize(data, size); // Access private LLImageBase members
1440 sGlobalFormattedMemory += getDataSize();
1580 } 1441 }
1581 return TRUE;
1582} 1442}
1583 1443
1584BOOL LLImageFormatted::setData(U8 *data, S32 size) 1444void LLImageFormatted::appendData(U8 *data, S32 size)
1585{ 1445{
1586 if (data && data != getData()) 1446 if (data)
1587 { 1447 {
1588 deleteData(); 1448 if (!getData())
1589 setDataAndSize(data, size); // Access private LLImageBase members 1449 {
1590 sGlobalFormattedMemory += getDataSize(); 1450 setData(data, size);
1451 }
1452 else
1453 {
1454 S32 cursize = getDataSize();
1455 S32 newsize = cursize + size;
1456 reallocateData(newsize);
1457 memcpy(getData() + cursize, data, size);
1458 }
1591 } 1459 }
1592 return updateData(); // virtual
1593} 1460}
1594 1461
1595//---------------------------------------------------------------------------- 1462//----------------------------------------------------------------------------
@@ -1662,8 +1529,6 @@ S8 LLImageFormatted::getCodec() const
1662 1529
1663//============================================================================ 1530//============================================================================
1664 1531
1665//----------------------------------------------------------------------------
1666
1667static void avg4_colors4(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst) 1532static void avg4_colors4(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst)
1668{ 1533{
1669 dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2); 1534 dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2);
@@ -1789,3 +1654,5 @@ F32 LLImageBase::calc_download_priority(F32 virtual_size, F32 visible_pixels, S3
1789 1654
1790 return w_priority; 1655 return w_priority;
1791} 1656}
1657
1658//============================================================================
diff --git a/linden/indra/llimage/llimage.h b/linden/indra/llimage/llimage.h
index eb1805a..ef5496e 100644
--- a/linden/indra/llimage/llimage.h
+++ b/linden/indra/llimage/llimage.h
@@ -32,7 +32,7 @@
32#include "lluuid.h" 32#include "lluuid.h"
33#include "llstring.h" 33#include "llstring.h"
34#include "llmemory.h" 34#include "llmemory.h"
35#include "llworkerthread.h" 35#include "llthread.h"
36 36
37const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 37const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2
38const S32 MAX_IMAGE_MIP = 11; // 2048x2048 38const S32 MAX_IMAGE_MIP = 11; // 2048x2048
@@ -154,8 +154,6 @@ public:
154 /*virtual*/ U8* allocateData(S32 size = -1); 154 /*virtual*/ U8* allocateData(S32 size = -1);
155 /*virtual*/ U8* reallocateData(S32 size); 155 /*virtual*/ U8* reallocateData(S32 size);
156 156
157 BOOL copyData(U8 *data, U16 width, U16 height, S8 components);
158
159 BOOL resize(U16 width, U16 height, S8 components); 157 BOOL resize(U16 width, U16 height, S8 components);
160 158
161 U8 * getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const; 159 U8 * getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const;
@@ -225,11 +223,10 @@ public:
225 223
226// Compressed representation of image. 224// Compressed representation of image.
227// Subclass from this class for the different representations (J2C, bmp) 225// Subclass from this class for the different representations (J2C, bmp)
228class LLImageFormatted : public LLImageBase, public LLWorkerClass 226class LLImageFormatted : public LLImageBase
229{ 227{
230public: 228public:
231 static void initClass(bool threaded = true, bool run_always = true); 229 static LLImageFormatted* createFromType(S8 codec);
232 static void cleanupClass();
233 static LLImageFormatted* createFromExtension(const LLString& instring); 230 static LLImageFormatted* createFromExtension(const LLString& instring);
234 231
235protected: 232protected:
@@ -247,22 +244,11 @@ public:
247 /*virtual*/ void dump(); 244 /*virtual*/ void dump();
248 /*virtual*/ void sanityCheck(); 245 /*virtual*/ void sanityCheck();
249 246
250 // LLWorkerThread
251public:
252 // called from WORKER THREAD, returns TRUE if done
253 /*virtual*/ bool doWork(S32 param);
254private:
255 // called from MAIN THREAD
256 /*virtual*/ void startWork(S32 param); // called from addWork()
257 /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork()
258
259 // New methods 247 // New methods
260public: 248public:
261 // calcHeaderSize() returns the maximum size of header; 249 // calcHeaderSize() returns the maximum size of header;
262 // 0 indicates we don't know have a header and have to lead the entire file 250 // 0 indicates we don't know have a header and have to lead the entire file
263 virtual S32 calcHeaderSize() { return 0; }; 251 virtual S32 calcHeaderSize() { return 0; };
264 // readHeader() reads size bytes into mData, and sets width/height/ncomponents
265 virtual void readHeader(U8* data, S32 size);
266 // calcDataSize() returns how many bytes to read to load discard_level (including header) 252 // calcDataSize() returns how many bytes to read to load discard_level (including header)
267 virtual S32 calcDataSize(S32 discard_level); 253 virtual S32 calcDataSize(S32 discard_level);
268 // calcDiscardLevelBytes() returns the smallest valid discard level based on the number of input bytes 254 // calcDiscardLevelBytes() returns the smallest valid discard level based on the number of input bytes
@@ -272,27 +258,16 @@ public:
272 258
273 BOOL load(const LLString& filename); 259 BOOL load(const LLString& filename);
274 BOOL save(const LLString& filename); 260 BOOL save(const LLString& filename);
275// BOOL save(LLVFS *vfs, const LLUUID &uuid, const LLAssetType::EType type);
276// Depricated to remove VFS dependency (see .cpp for replacement):
277 261
278 virtual BOOL updateData() = 0; // pure virtual 262 virtual BOOL updateData() = 0; // pure virtual
279 BOOL copyData(U8 *data, S32 size); // calls updateData() 263 void setData(U8 *data, S32 size);
280 BOOL setData(U8 *data, S32 size); // calls updateData() 264 void appendData(U8 *data, S32 size);
281 BOOL appendData(U8 *data, S32 size); // use if some data (e.g header) is already loaded, calls updateData()
282 265
283 // Loads first 4 channels. 266 // Loads first 4 channels.
284 virtual BOOL decode(LLImageRaw* raw_image, F32 decode_time=0.0) = 0; 267 virtual BOOL decode(LLImageRaw* raw_image, F32 decode_time=0.0) = 0;
285 // Subclasses that can handle more than 4 channels should override this function. 268 // Subclasses that can handle more than 4 channels should override this function.
286 virtual BOOL decode(LLImageRaw* raw_image, F32 decode_time, S32 first_channel, S32 max_channel); 269 virtual BOOL decode(LLImageRaw* raw_image, F32 decode_time, S32 first_channel, S32 max_channel);
287 270
288 // Decode methods to return a pointer to raw data for purposes of passing to
289 // opengl or such. This class tracks the decoded data and keeps it alive until
290 // destroyed or releaseDecodedData() is called.
291 virtual BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard = -1, F32 decode_time=0.0);
292 virtual BOOL requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel,
293 S32 discard = -1, F32 decode_time=0.0);
294 virtual void releaseDecodedData();
295
296 virtual BOOL encode(const LLImageRaw* raw_image, F32 encode_time=0.0) = 0; 271 virtual BOOL encode(const LLImageRaw* raw_image, F32 encode_time=0.0) = 0;
297 272
298 S8 getCodec() const; 273 S8 getCodec() const;
@@ -302,16 +277,16 @@ public:
302 S8 getDiscardLevel() const { return mDiscardLevel; } 277 S8 getDiscardLevel() const { return mDiscardLevel; }
303 278
304protected: 279protected:
280 BOOL copyData(U8 *data, S32 size); // calls updateData()
281
282protected:
305 S8 mCodec; 283 S8 mCodec;
306 S8 mDecoding; 284 S8 mDecoding;
307 S8 mDecoded; 285 S8 mDecoded;
308 S8 mDiscardLevel; 286 S8 mDiscardLevel;
309 287
310 LLPointer<LLImageRaw> mDecodedImage;
311
312public: 288public:
313 static S32 sGlobalFormattedMemory; 289 static S32 sGlobalFormattedMemory;
314 static LLWorkerThread* sWorkerThread;
315}; 290};
316 291
317#endif 292#endif
diff --git a/linden/indra/llimage/llimage.vcproj b/linden/indra/llimage/llimage.vcproj
index cd4c735..1f8a6ad 100644
--- a/linden/indra/llimage/llimage.vcproj
+++ b/linden/indra/llimage/llimage.vcproj
@@ -171,6 +171,9 @@
171 <File 171 <File
172 RelativePath=".\llimagetga.cpp"> 172 RelativePath=".\llimagetga.cpp">
173 </File> 173 </File>
174 <File
175 RelativePath=".\llimageworker.cpp">
176 </File>
174 </Filter> 177 </Filter>
175 <Filter 178 <Filter
176 Name="Header Files" 179 Name="Header Files"
@@ -197,6 +200,9 @@
197 <File 200 <File
198 RelativePath=".\llimagetga.h"> 201 RelativePath=".\llimagetga.h">
199 </File> 202 </File>
203 <File
204 RelativePath=".\llimageworker.h">
205 </File>
200 </Filter> 206 </Filter>
201 <Filter 207 <Filter
202 Name="Resource Files" 208 Name="Resource Files"
diff --git a/linden/indra/llimage/llimage_vc8.vcproj b/linden/indra/llimage/llimage_vc8.vcproj
new file mode 100644
index 0000000..052a28f
--- /dev/null
+++ b/linden/indra/llimage/llimage_vc8.vcproj
@@ -0,0 +1,306 @@
1<?xml version="1.0" encoding="Windows-1252"?>
2<VisualStudioProject
3 ProjectType="Visual C++"
4 Version="8.00"
5 Name="llimage"
6 ProjectGUID="{681FDD6C-2FAE-4CB9-AF6D-B952F2B151C5}"
7 Keyword="Win32Proj"
8 >
9 <Platforms>
10 <Platform
11 Name="Win32"
12 />
13 </Platforms>
14 <ToolFiles>
15 </ToolFiles>
16 <Configurations>
17 <Configuration
18 Name="Debug|Win32"
19 OutputDirectory="../lib_$(ConfigurationName)/i686-win32"
20 IntermediateDirectory="$(ConfigurationName)"
21 ConfigurationType="4"
22 InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
23 CharacterSet="1"
24 >
25 <Tool
26 Name="VCPreBuildEventTool"
27 />
28 <Tool
29 Name="VCCustomBuildTool"
30 />
31 <Tool
32 Name="VCXMLDataGeneratorTool"
33 />
34 <Tool
35 Name="VCWebServiceProxyGeneratorTool"
36 />
37 <Tool
38 Name="VCMIDLTool"
39 />
40 <Tool
41 Name="VCCLCompilerTool"
42 Optimization="0"
43 AdditionalIncludeDirectories="..\llcommon;..\llmath; ..\llvfs; ..\..\libraries\i686-win32\include;..\..\libraries\include\"
44 PreprocessorDefinitions="WIN32;_DEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_DEBUG"
45 MinimalRebuild="true"
46 BasicRuntimeChecks="3"
47 RuntimeLibrary="1"
48 StructMemberAlignment="4"
49 TreatWChar_tAsBuiltInType="false"
50 ForceConformanceInForLoopScope="true"
51 UsePrecompiledHeader="0"
52 WarningLevel="3"
53 WarnAsError="true"
54 Detect64BitPortabilityProblems="false"
55 DebugInformationFormat="4"
56 />
57 <Tool
58 Name="VCManagedResourceCompilerTool"
59 />
60 <Tool
61 Name="VCResourceCompilerTool"
62 />
63 <Tool
64 Name="VCPreLinkEventTool"
65 />
66 <Tool
67 Name="VCLibrarianTool"
68 OutputFile="$(OutDir)/llimage.lib"
69 />
70 <Tool
71 Name="VCALinkTool"
72 />
73 <Tool
74 Name="VCXDCMakeTool"
75 />
76 <Tool
77 Name="VCBscMakeTool"
78 />
79 <Tool
80 Name="VCFxCopTool"
81 />
82 <Tool
83 Name="VCPostBuildEventTool"
84 />
85 </Configuration>
86 <Configuration
87 Name="Release|Win32"
88 OutputDirectory="../lib_$(ConfigurationName)/i686-win32"
89 IntermediateDirectory="$(ConfigurationName)"
90 ConfigurationType="4"
91 InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
92 CharacterSet="1"
93 >
94 <Tool
95 Name="VCPreBuildEventTool"
96 />
97 <Tool
98 Name="VCCustomBuildTool"
99 />
100 <Tool
101 Name="VCXMLDataGeneratorTool"
102 />
103 <Tool
104 Name="VCWebServiceProxyGeneratorTool"
105 />
106 <Tool
107 Name="VCMIDLTool"
108 />
109 <Tool
110 Name="VCCLCompilerTool"
111 InlineFunctionExpansion="2"
112 EnableIntrinsicFunctions="true"
113 AdditionalIncludeDirectories="..\llcommon;..\llmath; ..\llvfs; ..\..\libraries\i686-win32\include;..\..\libraries\include\"
114 PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_RELEASE"
115 RuntimeLibrary="0"
116 StructMemberAlignment="0"
117 TreatWChar_tAsBuiltInType="false"
118 ForceConformanceInForLoopScope="true"
119 UsePrecompiledHeader="0"
120 WarningLevel="3"
121 WarnAsError="false"
122 Detect64BitPortabilityProblems="false"
123 DebugInformationFormat="3"
124 />
125 <Tool
126 Name="VCManagedResourceCompilerTool"
127 />
128 <Tool
129 Name="VCResourceCompilerTool"
130 />
131 <Tool
132 Name="VCPreLinkEventTool"
133 />
134 <Tool
135 Name="VCLibrarianTool"
136 OutputFile="$(OutDir)/llimage.lib"
137 />
138 <Tool
139 Name="VCALinkTool"
140 />
141 <Tool
142 Name="VCXDCMakeTool"
143 />
144 <Tool
145 Name="VCBscMakeTool"
146 />
147 <Tool
148 Name="VCFxCopTool"
149 />
150 <Tool
151 Name="VCPostBuildEventTool"
152 />
153 </Configuration>
154 <Configuration
155 Name="ReleaseNoOpt|Win32"
156 OutputDirectory="../lib_$(ConfigurationName)/i686-win32"
157 IntermediateDirectory="$(ConfigurationName)"
158 ConfigurationType="4"
159 InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
160 CharacterSet="1"
161 >
162 <Tool
163 Name="VCPreBuildEventTool"
164 />
165 <Tool
166 Name="VCCustomBuildTool"
167 />
168 <Tool
169 Name="VCXMLDataGeneratorTool"
170 />
171 <Tool
172 Name="VCWebServiceProxyGeneratorTool"
173 />
174 <Tool
175 Name="VCMIDLTool"
176 />
177 <Tool
178 Name="VCCLCompilerTool"
179 Optimization="0"
180 AdditionalIncludeDirectories="..\llcommon;..\llmath; ..\llvfs; ..\..\libraries\i686-win32\include;..\..\libraries\include\"
181 PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;LL_RELEASE"
182 RuntimeLibrary="0"
183 StructMemberAlignment="0"
184 TreatWChar_tAsBuiltInType="false"
185 ForceConformanceInForLoopScope="true"
186 UsePrecompiledHeader="0"
187 WarningLevel="3"
188 WarnAsError="true"
189 Detect64BitPortabilityProblems="false"
190 DebugInformationFormat="3"
191 />
192 <Tool
193 Name="VCManagedResourceCompilerTool"
194 />
195 <Tool
196 Name="VCResourceCompilerTool"
197 />
198 <Tool
199 Name="VCPreLinkEventTool"
200 />
201 <Tool
202 Name="VCLibrarianTool"
203 OutputFile="$(OutDir)/llimage.lib"
204 />
205 <Tool
206 Name="VCALinkTool"
207 />
208 <Tool
209 Name="VCXDCMakeTool"
210 />
211 <Tool
212 Name="VCBscMakeTool"
213 />
214 <Tool
215 Name="VCFxCopTool"
216 />
217 <Tool
218 Name="VCPostBuildEventTool"
219 />
220 </Configuration>
221 </Configurations>
222 <References>
223 </References>
224 <Files>
225 <Filter
226 Name="Source Files"
227 Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
228 UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
229 >
230 <File
231 RelativePath=".\llimage.cpp"
232 >
233 </File>
234 <File
235 RelativePath=".\llimagebmp.cpp"
236 >
237 </File>
238 <File
239 RelativePath=".\llimagedxt.cpp"
240 >
241 </File>
242 <File
243 RelativePath=".\llimagej2c.cpp"
244 >
245 </File>
246 <File
247 RelativePath=".\llimagejpeg.cpp"
248 >
249 </File>
250 <File
251 RelativePath=".\llimagetga.cpp"
252 >
253 </File>
254 <File
255 RelativePath=".\llimageworker.cpp"
256 >
257 </File>
258 </Filter>
259 <Filter
260 Name="Header Files"
261 Filter="h;hpp;hxx;hm;inl;inc;xsd"
262 UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
263 >
264 <File
265 RelativePath=".\llimage.h"
266 >
267 </File>
268 <File
269 RelativePath=".\llimagebmp.h"
270 >
271 </File>
272 <File
273 RelativePath=".\llimageconstants.h"
274 >
275 </File>
276 <File
277 RelativePath=".\llimagedxt.h"
278 >
279 </File>
280 <File
281 RelativePath=".\llimagej2c.h"
282 >
283 </File>
284 <File
285 RelativePath=".\llimagejpeg.h"
286 >
287 </File>
288 <File
289 RelativePath=".\llimagetga.h"
290 >
291 </File>
292 <File
293 RelativePath=".\llimageworker.h"
294 >
295 </File>
296 </Filter>
297 <Filter
298 Name="Resource Files"
299 Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
300 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
301 >
302 </Filter>
303 </Files>
304 <Globals>
305 </Globals>
306</VisualStudioProject>
diff --git a/linden/indra/llimage/llimagebmp.cpp b/linden/indra/llimage/llimagebmp.cpp
index fc9532e..e8cada5 100644
--- a/linden/indra/llimage/llimagebmp.cpp
+++ b/linden/indra/llimage/llimagebmp.cpp
@@ -142,7 +142,10 @@ BOOL LLImageBMP::updateData()
142 LLBMPHeader header; 142 LLBMPHeader header;
143 llassert( sizeof( header ) == BITMAP_HEADER_SIZE ); 143 llassert( sizeof( header ) == BITMAP_HEADER_SIZE );
144 144
145 memcpy((void *)&header, mdata + FILE_HEADER_SIZE, BITMAP_HEADER_SIZE); 145 memcpy( /* Flawfinder: ignore */
146 (void*)&header,
147 mdata + FILE_HEADER_SIZE,
148 BITMAP_HEADER_SIZE);
146 149
147 // convert BMP header from little endian (no-op on little endian builds) 150 // convert BMP header from little endian (no-op on little endian builds)
148 llendianswizzleone(header.mSize); 151 llendianswizzleone(header.mSize);
@@ -276,7 +279,7 @@ BOOL LLImageBMP::updateData()
276 279
277 280
278 extension_size = 4 * 3; 281 extension_size = 4 * 3;
279 memcpy( mBitfieldMask, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE, extension_size); 282 memcpy( mBitfieldMask, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE, extension_size); /* Flawfinder: ignore */
280 } 283 }
281 else 284 else
282 if( windows_95_version ) 285 if( windows_95_version )
@@ -285,11 +288,11 @@ BOOL LLImageBMP::updateData()
285 extension_size = sizeof( win_95_extension ); 288 extension_size = sizeof( win_95_extension );
286 289
287 llassert( sizeof( win_95_extension ) + BITMAP_HEADER_SIZE == 108 ); 290 llassert( sizeof( win_95_extension ) + BITMAP_HEADER_SIZE == 108 );
288 memcpy( &win_95_extension, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE, sizeof( win_95_extension ) ); 291 memcpy( &win_95_extension, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE, sizeof( win_95_extension ) ); /* Flawfinder: ignore */
289 292
290 if( 3 == header.mCompression ) 293 if( 3 == header.mCompression )
291 { 294 {
292 memcpy( mBitfieldMask, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE, 4 * 4); 295 memcpy( mBitfieldMask, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE, 4 * 4); /* Flawfinder: ignore */
293 } 296 }
294 297
295 // Color correction ignored for now 298 // Color correction ignored for now
@@ -317,7 +320,12 @@ BOOL LLImageBMP::updateData()
317 if( 0 != mColorPaletteColors ) 320 if( 0 != mColorPaletteColors )
318 { 321 {
319 mColorPalette = new U8[color_palette_size]; 322 mColorPalette = new U8[color_palette_size];
320 memcpy( mColorPalette, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE + extension_size, color_palette_size ); 323 if (!mColorPalette)
324 {
325 llerrs << "Out of memory in LLImageBMP::updateData()" << llendl;
326 return FALSE;
327 }
328 memcpy( mColorPalette, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE + extension_size, color_palette_size ); /* Flawfinder: ignore */
321 } 329 }
322 330
323 return TRUE; 331 return TRUE;
@@ -587,7 +595,7 @@ BOOL LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
587 U32 cur_pos = 0; 595 U32 cur_pos = 0;
588 memcpy(mdata, magic, 14); 596 memcpy(mdata, magic, 14);
589 cur_pos += 14; 597 cur_pos += 14;
590 memcpy(mdata+cur_pos, &header, 40); 598 memcpy(mdata+cur_pos, &header, 40); /* Flawfinder: ignore */
591 cur_pos += 40; 599 cur_pos += 40;
592 if (getComponents() == 1) 600 if (getComponents() == 1)
593 { 601 {
diff --git a/linden/indra/llimage/llimagedxt.cpp b/linden/indra/llimage/llimagedxt.cpp
index 8b16f97..6676366 100644
--- a/linden/indra/llimage/llimagedxt.cpp
+++ b/linden/indra/llimage/llimagedxt.cpp
@@ -279,13 +279,12 @@ BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
279 } 279 }
280 280
281 raw_image->resize(width, height, ncomponents); 281 raw_image->resize(width, height, ncomponents);
282 memcpy(raw_image->getData(), data, image_size); 282 memcpy(raw_image->getData(), data, image_size); /* Flawfinder: ignore */
283 283
284 return TRUE; 284 return TRUE;
285} 285}
286 286
287// virtual 287BOOL LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard)
288BOOL LLImageDXT::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard, F32 decode_time)
289{ 288{
290 if (discard < 0) 289 if (discard < 0)
291 { 290 {
@@ -302,11 +301,6 @@ BOOL LLImageDXT::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard, F32
302 return TRUE; 301 return TRUE;
303} 302}
304 303
305void LLImageDXT::releaseDecodedData()
306{
307 // nothing to do
308}
309
310BOOL LLImageDXT::encode(const LLImageRaw* raw_image, F32 time, bool explicit_mips) 304BOOL LLImageDXT::encode(const LLImageRaw* raw_image, F32 time, bool explicit_mips)
311{ 305{
312 llassert_always(raw_image); 306 llassert_always(raw_image);
@@ -373,7 +367,7 @@ BOOL LLImageDXT::encode(const LLImageRaw* raw_image, F32 time, bool explicit_mip
373 S32 bytes = formatBytes(format, w, h); 367 S32 bytes = formatBytes(format, w, h);
374 if (mip==0) 368 if (mip==0)
375 { 369 {
376 memcpy(mipdata, raw_image->getData(), bytes); 370 memcpy(mipdata, raw_image->getData(), bytes); /* Flawfinder: ignore */
377 } 371 }
378 else if (explicit_mips) 372 else if (explicit_mips)
379 { 373 {
@@ -425,21 +419,27 @@ bool LLImageDXT::convertToDXR()
425 S32 total_bytes = getDataSize(); 419 S32 total_bytes = getDataSize();
426 U8* olddata = getData(); 420 U8* olddata = getData();
427 U8* newdata = new U8[total_bytes]; 421 U8* newdata = new U8[total_bytes];
422 if (!newdata)
423 {
424 llerrs << "Out of memory in LLImageDXT::convertToDXR()" << llendl;
425 return false;
426 }
428 llassert(total_bytes > 0); 427 llassert(total_bytes > 0);
429 memset(newdata, 0, total_bytes); 428 memset(newdata, 0, total_bytes);
430 memcpy(newdata, olddata, mHeaderSize); 429 memcpy(newdata, olddata, mHeaderSize); /* Flawfinder: ignore */
431 for (S32 mip=0; mip<nmips; mip++) 430 for (S32 mip=0; mip<nmips; mip++)
432 { 431 {
433 S32 bytes = formatBytes(mFileFormat, width, height); 432 S32 bytes = formatBytes(mFileFormat, width, height);
434 S32 newoffset = getMipOffset(mip); 433 S32 newoffset = getMipOffset(mip);
435 S32 oldoffset = mHeaderSize + (total_bytes - newoffset - bytes); 434 S32 oldoffset = mHeaderSize + (total_bytes - newoffset - bytes);
436 memcpy(newdata + newoffset, olddata + oldoffset, bytes); 435 memcpy(newdata + newoffset, olddata + oldoffset, bytes); /* Flawfinder: ignore */
437 width >>= 1; 436 width >>= 1;
438 height >>= 1; 437 height >>= 1;
439 } 438 }
440 dxtfile_header_t* header = (dxtfile_header_t*)newdata; 439 dxtfile_header_t* header = (dxtfile_header_t*)newdata;
441 header->pixel_fmt.fourcc = getFourCC(newformat); 440 header->pixel_fmt.fourcc = getFourCC(newformat);
442 setData(newdata, total_bytes); 441 setData(newdata, total_bytes);
442 updateData();
443 return true; 443 return true;
444} 444}
445 445
@@ -487,7 +487,7 @@ void LLImageDXT::extractMip(const U8 *indata, U8* mipdata, int width, int height
487 for (int h=0;h<mip_height;++h) 487 for (int h=0;h<mip_height;++h)
488 { 488 {
489 int start_offset = initial_offset + line_width * h + line_offset; 489 int start_offset = initial_offset + line_width * h + line_offset;
490 memcpy(mipdata + mip_line_width*h, indata + start_offset, mip_line_width); 490 memcpy(mipdata + mip_line_width*h, indata + start_offset, mip_line_width); /* Flawfinder: ignore */
491 } 491 }
492} 492}
493 493
diff --git a/linden/indra/llimage/llimagedxt.h b/linden/indra/llimage/llimagedxt.h
index c3c01c1..936258a 100644
--- a/linden/indra/llimage/llimagedxt.h
+++ b/linden/indra/llimage/llimagedxt.h
@@ -101,12 +101,11 @@ public:
101 BOOL encode(const LLImageRaw* raw_image, F32 time, bool explicit_mips); 101 BOOL encode(const LLImageRaw* raw_image, F32 time, bool explicit_mips);
102 /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 time=0.0); 102 /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 time=0.0);
103 103
104 /*virtual*/ BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard=-1, F32 decode_time=0.0);
105 /*virtual*/ void releaseDecodedData();
106
107 /*virtual*/ S32 calcHeaderSize(); 104 /*virtual*/ S32 calcHeaderSize();
108 /*virtual*/ S32 calcDataSize(S32 discard_level = 0); 105 /*virtual*/ S32 calcDataSize(S32 discard_level = 0);
109 106
107 BOOL getMipData(LLPointer<LLImageRaw>& raw, S32 discard=-1);
108
110 void setFormat(); 109 void setFormat();
111 S32 getMipOffset(S32 discard); 110 S32 getMipOffset(S32 discard);
112 111
diff --git a/linden/indra/llimage/llimagej2c.cpp b/linden/indra/llimage/llimagej2c.cpp
index 87852e7..51d9522 100644
--- a/linden/indra/llimage/llimagej2c.cpp
+++ b/linden/indra/llimage/llimagej2c.cpp
@@ -30,7 +30,7 @@
30 30
31#include "lldir.h" 31#include "lldir.h"
32#include "llimagej2c.h" 32#include "llimagej2c.h"
33#include "llmemory.h" 33#include "llmemtype.h"
34 34
35typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)(); 35typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
36typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*); 36typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
@@ -243,7 +243,22 @@ BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time, S32 first_chann
243 // Update the raw discard level 243 // Update the raw discard level
244 updateRawDiscardLevel(); 244 updateRawDiscardLevel();
245 245
246 return mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count); 246 mDecoding = TRUE;
247 BOOL res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
248 if (res)
249 {
250 if (!mDecoding)
251 {
252 // Failed
253 raw_imagep->deleteData();
254 }
255 else
256 {
257 mDecoding = FALSE;
258 }
259 return TRUE; // done
260 }
261 return FALSE;
247} 262}
248 263
249 264
@@ -353,7 +368,7 @@ BOOL LLImageJ2C::loadAndValidate(const LLString &filename)
353 U8 *data = new U8[file_size]; 368 U8 *data = new U8[file_size];
354 apr_size_t bytes_read = file_size; 369 apr_size_t bytes_read = file_size;
355 apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read 370 apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
356 if (s != APR_SUCCESS || bytes_read != file_size) 371 if (s != APR_SUCCESS || (S32)bytes_read != file_size)
357 { 372 {
358 delete[] data; 373 delete[] data;
359 setLastError("Unable to read entire file"); 374 setLastError("Unable to read entire file");
@@ -368,9 +383,9 @@ BOOL LLImageJ2C::loadAndValidate(const LLString &filename)
368BOOL LLImageJ2C::validate(U8 *data, U32 file_size) 383BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
369{ 384{
370 LLMemType mt1((LLMemType::EMemType)mMemType); 385 LLMemType mt1((LLMemType::EMemType)mMemType);
371 // Taken from setData()
372 386
373 BOOL res = LLImageFormatted::setData(data, file_size); 387 setData(data, file_size);
388 BOOL res = updateData();
374 if ( !res ) 389 if ( !res )
375 { 390 {
376 return FALSE; 391 return FALSE;
@@ -386,10 +401,9 @@ BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
386 return mImpl->getMetadata(*this); 401 return mImpl->getMetadata(*this);
387} 402}
388 403
389void LLImageJ2C::setDecodingDone(BOOL complete) 404void LLImageJ2C::decodeFailed()
390{ 405{
391 mDecoding = FALSE; 406 mDecoding = FALSE;
392 mDecoded = complete;
393} 407}
394 408
395void LLImageJ2C::updateRawDiscardLevel() 409void LLImageJ2C::updateRawDiscardLevel()
diff --git a/linden/indra/llimage/llimagej2c.h b/linden/indra/llimage/llimagej2c.h
index a6894ab..24a1429 100644
--- a/linden/indra/llimage/llimagej2c.h
+++ b/linden/indra/llimage/llimagej2c.h
@@ -72,7 +72,7 @@ protected:
72 friend class LLImageJ2CImpl; 72 friend class LLImageJ2CImpl;
73 friend class LLImageJ2COJ; 73 friend class LLImageJ2COJ;
74 friend class LLImageJ2CKDU; 74 friend class LLImageJ2CKDU;
75 void setDecodingDone(BOOL complete = TRUE); 75 void decodeFailed();
76 void updateRawDiscardLevel(); 76 void updateRawDiscardLevel();
77 77
78 S32 mMaxBytes; // Maximum number of bytes of data to use... 78 S32 mMaxBytes; // Maximum number of bytes of data to use...
@@ -87,7 +87,17 @@ class LLImageJ2CImpl
87public: 87public:
88 virtual ~LLImageJ2CImpl(); 88 virtual ~LLImageJ2CImpl();
89protected: 89protected:
90 // Find out the image size and number of channels.
91 // Return value:
92 // true: image size and number of channels was determined
93 // false: error on decode
90 virtual BOOL getMetadata(LLImageJ2C &base) = 0; 94 virtual BOOL getMetadata(LLImageJ2C &base) = 0;
95 // Decode the raw image optionally aborting (to continue later) after
96 // decode_time seconds. Decode at most max_channel_count and start
97 // decoding channel first_channel.
98 // Return value:
99 // true: decoding complete (even if it failed)
100 // false: time expired while decoding
91 virtual BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) = 0; 101 virtual BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) = 0;
92 virtual BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0) = 0; 102 virtual BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0) = 0;
93 103
diff --git a/linden/indra/llimage/llimagejpeg.cpp b/linden/indra/llimage/llimagejpeg.cpp
index 5c83f20..fdfcc16 100644
--- a/linden/indra/llimage/llimagejpeg.cpp
+++ b/linden/indra/llimage/llimagejpeg.cpp
@@ -354,7 +354,12 @@ boolean LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )
354 // Double the buffer size; 354 // Double the buffer size;
355 S32 new_buffer_size = self->mOutputBufferSize * 2; 355 S32 new_buffer_size = self->mOutputBufferSize * 2;
356 U8* new_buffer = new U8[ new_buffer_size ]; 356 U8* new_buffer = new U8[ new_buffer_size ];
357 memcpy( new_buffer, self->mOutputBuffer, self->mOutputBufferSize ); 357 if (!new_buffer)
358 {
359 llerrs << "Out of memory in LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )" << llendl;
360 return FALSE;
361 }
362 memcpy( new_buffer, self->mOutputBuffer, self->mOutputBufferSize ); /* Flawfinder: ignore */
358 delete[] self->mOutputBuffer; 363 delete[] self->mOutputBuffer;
359 self->mOutputBuffer = new_buffer; 364 self->mOutputBuffer = new_buffer;
360 365
@@ -378,7 +383,7 @@ void LLImageJPEG::encodeTermDestination( j_compress_ptr cinfo )
378 S32 file_bytes = (S32)(self->mOutputBufferSize - cinfo->dest->free_in_buffer); 383 S32 file_bytes = (S32)(self->mOutputBufferSize - cinfo->dest->free_in_buffer);
379 self->allocateData(file_bytes); 384 self->allocateData(file_bytes);
380 385
381 memcpy( self->getData(), self->mOutputBuffer, file_bytes ); 386 memcpy( self->getData(), self->mOutputBuffer, file_bytes ); /* Flawfinder: ignore */
382} 387}
383 388
384// static 389// static
@@ -435,7 +440,7 @@ void LLImageJPEG::errorEmitMessage( j_common_ptr cinfo, int msg_level )
435void LLImageJPEG::errorOutputMessage( j_common_ptr cinfo ) 440void LLImageJPEG::errorOutputMessage( j_common_ptr cinfo )
436{ 441{
437 // Create the message 442 // Create the message
438 char buffer[JMSG_LENGTH_MAX]; 443 char buffer[JMSG_LENGTH_MAX]; /* Flawfinder: ignore */
439 (*cinfo->err->format_message) (cinfo, buffer); 444 (*cinfo->err->format_message) (cinfo, buffer);
440 445
441 ((LLImageJPEG*) cinfo->client_data)->setLastError( buffer ); 446 ((LLImageJPEG*) cinfo->client_data)->setLastError( buffer );
diff --git a/linden/indra/llimage/llimagetga.cpp b/linden/indra/llimage/llimagetga.cpp
index 722bd1e..d5d60de 100644
--- a/linden/indra/llimage/llimagetga.cpp
+++ b/linden/indra/llimage/llimagetga.cpp
@@ -202,7 +202,7 @@ BOOL LLImageTGA::updateData()
202 // discard the ID field, if any 202 // discard the ID field, if any
203 if (mIDLength) 203 if (mIDLength)
204 { 204 {
205 memcpy(junk, getData()+mDataOffset, mIDLength); 205 memcpy(junk, getData()+mDataOffset, mIDLength); /* Flawfinder: ignore */
206 mDataOffset += mIDLength; 206 mDataOffset += mIDLength;
207 } 207 }
208 208
@@ -239,7 +239,12 @@ BOOL LLImageTGA::updateData()
239 if ( (1 == mImageType) || (9 == mImageType) ) 239 if ( (1 == mImageType) || (9 == mImageType) )
240 { 240 {
241 mColorMap = new U8[ color_map_bytes ]; 241 mColorMap = new U8[ color_map_bytes ];
242 memcpy( mColorMap, getData() + mDataOffset, color_map_bytes ); 242 if (!mColorMap)
243 {
244 llerrs << "Out of Memory in BOOL LLImageTGA::updateData()" << llendl;
245 return FALSE;
246 }
247 memcpy( mColorMap, getData() + mDataOffset, color_map_bytes ); /* Flawfinder: ignore */
243 } 248 }
244 249
245 mDataOffset += color_map_bytes; 250 mDataOffset += color_map_bytes;
@@ -451,7 +456,7 @@ BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaqu
451 } 456 }
452 else if (getComponents() == 1) 457 else if (getComponents() == 1)
453 { 458 {
454 memcpy(dst, src, pixels); 459 memcpy(dst, src, pixels); /* Flawfinder: ignore */
455 } 460 }
456 461
457 return TRUE; 462 return TRUE;
@@ -692,7 +697,7 @@ BOOL LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
692 switch( getComponents() ) 697 switch( getComponents() )
693 { 698 {
694 case 1: 699 case 1:
695 memcpy( dst, src, bytes_per_pixel * pixels ); 700 memcpy( dst, src, bytes_per_pixel * pixels ); /* Flawfinder: ignore */
696 break; 701 break;
697 702
698 case 2: 703 case 2:
@@ -1072,7 +1077,7 @@ bool LLImageTGA::loadFile( const LLString& path )
1072 return false; 1077 return false;
1073 } 1078 }
1074 1079
1075 FILE *file = LLFile::fopen(path.c_str(), "rb"); 1080 FILE* file = LLFile::fopen(path.c_str(), "rb"); /* Flawfinder: ignore */
1076 if( !file ) 1081 if( !file )
1077 { 1082 {
1078 llwarns << "Couldn't open file " << path << llendl; 1083 llwarns << "Couldn't open file " << path << llendl;
diff --git a/linden/indra/llimage/llimageworker.cpp b/linden/indra/llimage/llimageworker.cpp
new file mode 100644
index 0000000..4550848
--- /dev/null
+++ b/linden/indra/llimage/llimageworker.cpp
@@ -0,0 +1,184 @@
1/**
2 * @file llimage.cpp
3 * @brief Base class for images.
4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "linden_common.h"
29
30#include "llimageworker.h"
31#include "llimagedxt.h"
32
33//----------------------------------------------------------------------------
34
35//static
36LLWorkerThread* LLImageWorker::sWorkerThread = NULL;
37S32 LLImageWorker::sCount = 0;
38
39//static
40void LLImageWorker::initClass(LLWorkerThread* workerthread)
41{
42 sWorkerThread = workerthread;
43}
44
45//static
46void LLImageWorker::cleanupClass()
47{
48}
49
50//----------------------------------------------------------------------------
51
52LLImageWorker::LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard, LLResponder* responder)
53 : LLWorkerClass(sWorkerThread, "Image"),
54 mFormattedImage(image),
55 mDecodedType(-1),
56 mDiscardLevel(discard),
57 mPriority(priority),
58 mResponder(responder)
59{
60 ++sCount;
61}
62
63LLImageWorker::~LLImageWorker()
64{
65 mDecodedImage = NULL;
66 mFormattedImage = NULL;
67 --sCount;
68}
69
70//----------------------------------------------------------------------------
71
72//virtual, main thread
73void LLImageWorker::startWork(S32 param)
74{
75 llassert_always(mDecodedImage.isNull());
76 mDecodedType = -1;
77}
78
79bool LLImageWorker::doWork(S32 param)
80{
81 bool decoded = false;
82 if(mDecodedImage.isNull())
83 {
84 if (!mFormattedImage->updateData())
85 {
86 mDecodedType = -2; // failed
87 return true;
88 }
89 if (mDiscardLevel >= 0)
90 {
91 mFormattedImage->setDiscardLevel(mDiscardLevel);
92 }
93 if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
94 {
95 decoded = true; // failed
96 }
97 else
98 {
99 S32 nc = param ? 1 : mFormattedImage->getComponents();
100 mDecodedImage = new LLImageRaw(mFormattedImage->getWidth(),
101 mFormattedImage->getHeight(),
102 nc);
103 }
104 }
105 if (!decoded)
106 {
107 if (param == 0)
108 {
109 // Decode primary channels
110 decoded = mFormattedImage->decode(mDecodedImage, .1f); // 1ms
111 }
112 else
113 {
114 // Decode aux channel
115 decoded = mFormattedImage->decode(mDecodedImage, .1f, param, param); // 1ms
116 }
117 }
118 if (decoded)
119 {
120 // Call the callback immediately; endWork doesn't get called until ckeckWork
121 if (mResponder.notNull())
122 {
123 bool success = (!wasAborted() && mDecodedImage.notNull() && mDecodedImage->getDataSize() != 0);
124 mResponder->completed(success);
125 }
126 }
127 return decoded;
128}
129
130void LLImageWorker::endWork(S32 param, bool aborted)
131{
132 if (mDecodedType != -2)
133 {
134 mDecodedType = aborted ? -2 : param;
135 }
136}
137
138//----------------------------------------------------------------------------
139
140
141BOOL LLImageWorker::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard)
142{
143 // For most codecs, only mDiscardLevel data is available.
144 // (see LLImageDXT for exception)
145 if (discard >= 0 && discard != mFormattedImage->getDiscardLevel())
146 {
147 llerrs << "Request for invalid discard level" << llendl;
148 }
149 checkWork();
150 if (mDecodedType == -2)
151 {
152 return TRUE; // aborted, done
153 }
154 if (mDecodedType != channel)
155 {
156 if (!haveWork())
157 {
158 addWork(channel, mPriority);
159 }
160 return FALSE;
161 }
162 else
163 {
164 llassert_always(!haveWork());
165 llassert_always(mDecodedType == channel);
166 raw = mDecodedImage; // smart pointer acquires ownership of data
167 mDecodedImage = NULL;
168 return TRUE;
169 }
170}
171
172BOOL LLImageWorker::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard)
173{
174 if (mFormattedImage->getCodec() == IMG_CODEC_DXT)
175 {
176 // special case
177 LLImageDXT* imagedxt = (LLImageDXT*)((LLImageFormatted*)mFormattedImage);
178 return imagedxt->getMipData(raw, discard);
179 }
180 else
181 {
182 return requestDecodedAuxData(raw, 0, discard);
183 }
184}
diff --git a/linden/indra/llimage/llimageworker.h b/linden/indra/llimage/llimageworker.h
new file mode 100644
index 0000000..a39d21a
--- /dev/null
+++ b/linden/indra/llimage/llimageworker.h
@@ -0,0 +1,76 @@
1/**
2 * @file llimageworker.h
3 * @brief Object for managing images and their textures.
4 *
5 * Copyright (c) 2000-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#ifndef LL_LLIMAGEWORKER_H
29#define LL_LLIMAGEWORKER_H
30
31#include "llimage.h"
32#include "llworkerthread.h"
33
34class LLImageWorker : public LLWorkerClass
35{
36public:
37 static void initClass(LLWorkerThread* workerthread);
38 static void cleanupClass();
39 static LLWorkerThread* getWorkerThread() { return sWorkerThread; }
40
41 // LLWorkerThread
42public:
43 LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard, LLResponder* responder = NULL);
44 ~LLImageWorker();
45
46 // called from WORKER THREAD, returns TRUE if done
47 /*virtual*/ bool doWork(S32 param);
48
49 BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard = -1);
50 BOOL requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard = -1);
51 void releaseDecodedData();
52 void cancelDecode();
53
54private:
55 // called from MAIN THREAD
56 /*virtual*/ void startWork(S32 param); // called from addWork()
57 /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork()
58
59protected:
60 LLPointer<LLImageFormatted> mFormattedImage;
61 LLPointer<LLImageRaw> mDecodedImage;
62 S32 mDecodedType;
63 S32 mDiscardLevel;
64
65private:
66 U32 mPriority;
67 LLPointer<LLResponder> mResponder;
68
69protected:
70 static LLWorkerThread* sWorkerThread;
71
72public:
73 static S32 sCount;
74};
75
76#endif
diff --git a/linden/indra/llimagej2coj/llimagej2coj.cpp b/linden/indra/llimagej2coj/llimagej2coj.cpp
index f292da9..307f952 100644
--- a/linden/indra/llimagej2coj/llimagej2coj.cpp
+++ b/linden/indra/llimagej2coj/llimagej2coj.cpp
@@ -28,6 +28,8 @@
28#include "linden_common.h" 28#include "linden_common.h"
29#include "llimagej2coj.h" 29#include "llimagej2coj.h"
30 30
31// this is defined so that we get static linking.
32#define OPJ_STATIC
31#include "openjpeg/openjpeg.h" 33#include "openjpeg/openjpeg.h"
32 34
33#include "lltimer.h" 35#include "lltimer.h"
@@ -122,46 +124,61 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
122 124
123 /* decode the stream and fill the image structure */ 125 /* decode the stream and fill the image structure */
124 image = opj_decode(dinfo, cio); 126 image = opj_decode(dinfo, cio);
125 if(!image)
126 {
127 fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
128 opj_destroy_decompress(dinfo);
129 opj_cio_close(cio);
130 return 1;
131 }
132 127
133 /* close the byte stream */ 128 /* close the byte stream */
134 opj_cio_close(cio); 129 opj_cio_close(cio);
135 130
136
137 /* free remaining structures */ 131 /* free remaining structures */
138 if(dinfo) { 132 if(dinfo)
133 {
139 opj_destroy_decompress(dinfo); 134 opj_destroy_decompress(dinfo);
140 } 135 }
141 136
137 // The image decode failed if the return was NULL or the component
138 // count was zero. The latter is just a sanity check before we
139 // dereference the array.
140 if(!image || !image->numcomps)
141 {
142 fprintf(stderr, "ERROR -> decodeImpl: failed to decode image!\n");
143 if (image)
144 opj_image_destroy(image);
145
146 return TRUE; // done
147 }
148
142 // Copy image data into our raw image format (instead of the separate channel format 149 // Copy image data into our raw image format (instead of the separate channel format
143 S32 width = 0;
144 S32 height = 0;
145 150
146 S32 img_components = image->numcomps; 151 S32 img_components = image->numcomps;
147 S32 channels = img_components - first_channel; 152 S32 channels = img_components - first_channel;
148 if( channels > max_channel_count ) 153 if( channels > max_channel_count )
149 {
150 channels = max_channel_count; 154 channels = max_channel_count;
151 } 155
152 width = image->x1 - image->x0; 156 // Component buffers are allocated in an image width by height buffer.
153 height = image->y1 - image->y0; 157 // The image placed in that buffer is ceil(width/2^factor) by
158 // ceil(height/2^factor) and if the factor isn't zero it will be at the
159 // top left of the buffer with black filled in the rest of the pixels.
160 // It is integer math so the formula is written in ceildivpo2.
161 // (Assuming all the components have the same width, height and
162 // factor.)
163 S32 comp_width = image->comps[0].w;
164 S32 f=image->comps[0].factor;
165 S32 width = ceildivpow2(image->x1 - image->x0, f);
166 S32 height = ceildivpow2(image->y1 - image->y0, f);
154 raw_image.resize(width, height, channels); 167 raw_image.resize(width, height, channels);
155 U8 *rawp = raw_image.getData(); 168 U8 *rawp = raw_image.getData();
156 169
157 for (S32 comp = first_channel; comp < first_channel + channels; comp++) 170 // first_channel is what channel to start copying from
171 // dest is what channel to copy to. first_channel comes from the
172 // argument, dest always starts writing at channel zero.
173 for (S32 comp = first_channel, dest=0; comp < first_channel + channels;
174 comp++, dest++)
158 { 175 {
159 S32 offset = comp; 176 S32 offset = dest;
160 for (S32 y = (height - 1); y >= 0; y--) 177 for (S32 y = (height - 1); y >= 0; y--)
161 { 178 {
162 for (S32 x = 0; x < width; x++) 179 for (S32 x = 0; x < width; x++)
163 { 180 {
164 rawp[offset] = image->comps[comp].data[y*width + x]; 181 rawp[offset] = image->comps[comp].data[y*comp_width + x];
165 offset += channels; 182 offset += channels;
166 } 183 }
167 } 184 }
@@ -170,8 +187,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
170 /* free image data structure */ 187 /* free image data structure */
171 opj_image_destroy(image); 188 opj_image_destroy(image);
172 189
173 base.setDecodingDone(); 190 return TRUE; // done
174 return TRUE;
175} 191}
176 192
177 193
@@ -281,6 +297,7 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con
281 codestream_length = cio_tell(cio); 297 codestream_length = cio_tell(cio);
282 298
283 base.copyData(cio->buffer, codestream_length); 299 base.copyData(cio->buffer, codestream_length);
300 base.updateData(); // set width, height
284 301
285 /* close and free the byte stream */ 302 /* close and free the byte stream */
286 opj_cio_close(cio); 303 opj_cio_close(cio);
@@ -323,6 +340,9 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)
323 /* set decoding parameters to default values */ 340 /* set decoding parameters to default values */
324 opj_set_default_decoder_parameters(&parameters); 341 opj_set_default_decoder_parameters(&parameters);
325 342
343 // Only decode what's required to get the size data.
344 parameters.cp_limit_decoding=LIMIT_TO_MAIN_HEADER;
345
326 //parameters.cp_reduce = mRawDiscardLevel; 346 //parameters.cp_reduce = mRawDiscardLevel;
327 347
328 /* decode the code-stream */ 348 /* decode the code-stream */
@@ -344,23 +364,22 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)
344 364
345 /* decode the stream and fill the image structure */ 365 /* decode the stream and fill the image structure */
346 image = opj_decode(dinfo, cio); 366 image = opj_decode(dinfo, cio);
347 if(!image)
348 {
349 fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
350 opj_destroy_decompress(dinfo);
351 opj_cio_close(cio);
352 return 1;
353 }
354 367
355 /* close the byte stream */ 368 /* close the byte stream */
356 opj_cio_close(cio); 369 opj_cio_close(cio);
357 370
358
359 /* free remaining structures */ 371 /* free remaining structures */
360 if(dinfo) { 372 if(dinfo)
373 {
361 opj_destroy_decompress(dinfo); 374 opj_destroy_decompress(dinfo);
362 } 375 }
363 376
377 if(!image)
378 {
379 fprintf(stderr, "ERROR -> getMetadata: failed to decode image!\n");
380 return FALSE;
381 }
382
364 // Copy image data into our raw image format (instead of the separate channel format 383 // Copy image data into our raw image format (instead of the separate channel format
365 S32 width = 0; 384 S32 width = 0;
366 S32 height = 0; 385 S32 height = 0;
@@ -371,5 +390,6 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)
371 base.setSize(width, height, img_components); 390 base.setSize(width, height, img_components);
372 391
373 /* free image data structure */ 392 /* free image data structure */
374 opj_image_destroy(image); return TRUE; 393 opj_image_destroy(image);
394 return TRUE;
375} 395}
diff --git a/linden/indra/llimagej2coj/llimagej2coj.h b/linden/indra/llimagej2coj/llimagej2coj.h
index 3fbf495..c3e3d52 100644
--- a/linden/indra/llimagej2coj/llimagej2coj.h
+++ b/linden/indra/llimagej2coj/llimagej2coj.h
@@ -40,6 +40,11 @@ protected:
40 /*virtual*/ BOOL getMetadata(LLImageJ2C &base); 40 /*virtual*/ BOOL getMetadata(LLImageJ2C &base);
41 /*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count); 41 /*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count);
42 /*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0); 42 /*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0);
43 int ceildivpow2(int a, int b)
44 {
45 // Divide a by b to the power of 2 and round upwards.
46 return (a + (1 << b) - 1) >> b;
47 }
43 48
44 // Temporary variables for in-progress decodes... 49 // Temporary variables for in-progress decodes...
45 LLImageRaw *mRawImagep; 50 LLImageRaw *mRawImagep;