aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llimage/llimage.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llimage/llimage.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llimage/llimage.cpp')
-rw-r--r--linden/indra/llimage/llimage.cpp1791
1 files changed, 1791 insertions, 0 deletions
diff --git a/linden/indra/llimage/llimage.cpp b/linden/indra/llimage/llimage.cpp
new file mode 100644
index 0000000..acd6aef
--- /dev/null
+++ b/linden/indra/llimage/llimage.cpp
@@ -0,0 +1,1791 @@
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 <stdlib.h>
31#include <string.h>
32#include <stdio.h>
33#include <algorithm>
34#include <iostream>
35
36#include "llmath.h"
37#include "stdtypes.h"
38#include "v4coloru.h"
39#include "llmemory.h"
40
41#include "llimage.h"
42#include "llimagebmp.h"
43#include "llimagetga.h"
44#include "llimagej2c.h"
45#if JPEG_SUPPORT
46#include "llimagejpeg.h"
47#endif
48#include "llimagedxt.h"
49
50//---------------------------------------------------------------------------
51// LLImageBase
52//---------------------------------------------------------------------------
53
54LLImageBase::LLImageBase()
55 : mData(NULL),
56 mDataSize(0),
57 mWidth(0),
58 mHeight(0),
59 mComponents(0),
60 mMemType(LLMemType::MTYPE_IMAGEBASE)
61{
62}
63
64// virtual
65LLImageBase::~LLImageBase()
66{
67 deleteData(); // virtual
68}
69
70// virtual
71void LLImageBase::dump()
72{
73 llinfos << "LLImageBase mComponents " << mComponents
74 << " mData " << mData
75 << " mDataSize " << mDataSize
76 << " mWidth " << mWidth
77 << " mHeight " << mHeight
78 << llendl;
79}
80
81// virtual
82void LLImageBase::sanityCheck()
83{
84 if (mWidth > MAX_IMAGE_SIZE
85 || mHeight > MAX_IMAGE_SIZE
86 || mDataSize > (S32)MAX_IMAGE_DATA_SIZE
87 || mComponents > (S8)MAX_IMAGE_COMPONENTS
88 )
89 {
90 llerrs << "Failed LLImageBase::sanityCheck "
91 << "width " << mWidth
92 << "height " << mHeight
93 << "datasize " << mDataSize
94 << "components " << mComponents
95 << "data " << mData
96 << llendl;
97 }
98}
99
100LLString LLImageBase::sLastErrorMessage;
101BOOL LLImageBase::sSizeOverride = FALSE;
102
103BOOL LLImageBase::setLastError(const LLString& message, const LLString& filename)
104{
105 sLastErrorMessage = message;
106 if (filename != "")
107 {
108 sLastErrorMessage += LLString(" FILE:");
109 sLastErrorMessage += filename;
110 }
111 llwarns << sLastErrorMessage << llendl;
112 return FALSE;
113}
114
115// virtual
116void LLImageBase::deleteData()
117{
118 delete[] mData;
119 mData = NULL;
120 mDataSize = 0;
121}
122
123// virtual
124U8* LLImageBase::allocateData(S32 size)
125{
126 LLMemType mt1((LLMemType::EMemType)mMemType);
127
128 if (size < 0)
129 {
130 size = mWidth * mHeight * mComponents;
131 if (size <= 0)
132 {
133 llerrs << llformat("LLImageBase::allocateData called with bad dimentions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl;
134 }
135 }
136 else if ((size <= 0 || size > 4096*4096*16) && sSizeOverride == FALSE)
137 {
138 llerrs << "LLImageBase::allocateData: bad size: " << size << llendl;
139 }
140
141 resetLastError();
142
143 if (!mData || size != mDataSize)
144 {
145 deleteData(); // virtual
146 mData = new U8[size];
147 if (!mData)
148 {
149 llerrs << "allocate image data: " << size << llendl;
150 }
151 mDataSize = size;
152 }
153
154 return mData;
155}
156
157// virtual
158U8* LLImageBase::reallocateData(S32 size)
159{
160 LLMemType mt1((LLMemType::EMemType)mMemType);
161 U8 *new_datap = new U8[size];
162 if (!new_datap)
163 {
164 llwarns << "Out of memory in LLImageBase::reallocateData" << llendl;
165 return 0;
166 }
167 if (mData)
168 {
169 S32 bytes = llmin(mDataSize, size);
170 memcpy(new_datap, mData, bytes);
171 delete[] mData;
172 }
173 mData = new_datap;
174 mDataSize = size;
175 return mData;
176}
177
178
179void LLImageBase::setSize(S32 width, S32 height, S32 ncomponents)
180{
181 mWidth = width;
182 mHeight = height;
183 mComponents = ncomponents;
184}
185
186U8* LLImageBase::allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 size)
187{
188 setSize(width, height, ncomponents);
189 return allocateData(size); // virtual
190}
191
192//---------------------------------------------------------------------------
193// LLImageRaw
194//---------------------------------------------------------------------------
195
196S32 LLImageRaw::sGlobalRawMemory = 0;
197S32 LLImageRaw::sRawImageCount = 0;
198
199LLImageRaw::LLImageRaw()
200 : LLImageBase()
201{
202 mMemType = LLMemType::MTYPE_IMAGERAW;
203 ++sRawImageCount;
204}
205
206LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components)
207 : LLImageBase()
208{
209 mMemType = LLMemType::MTYPE_IMAGERAW;
210 llassert( S32(width) * S32(height) * S32(components) <= MAX_IMAGE_DATA_SIZE );
211 allocateDataSize(width, height, components);
212 ++sRawImageCount;
213}
214
215LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
216 : LLImageBase()
217{
218 mMemType = LLMemType::MTYPE_IMAGERAW;
219 copyData(data, width, height, components);
220 ++sRawImageCount;
221}
222
223LLImageRaw::LLImageRaw(const LLString &filename, bool j2c_lowest_mip_only)
224 : LLImageBase()
225{
226 createFromFile(filename, j2c_lowest_mip_only);
227}
228
229LLImageRaw::~LLImageRaw()
230{
231 // NOTE: ~LLimageBase() call to deleteData() calls LLImageBase::deleteData()
232 // NOT LLImageRaw::deleteData()
233 deleteData();
234 --sRawImageCount;
235}
236
237// virtual
238U8* LLImageRaw::allocateData(S32 size)
239{
240 U8* res = LLImageBase::allocateData(size);
241 sGlobalRawMemory += getDataSize();
242 return res;
243}
244
245// virtual
246U8* LLImageRaw::reallocateData(S32 size)
247{
248 sGlobalRawMemory -= getDataSize();
249 U8* res = LLImageBase::reallocateData(size);
250 sGlobalRawMemory += getDataSize();
251 return res;
252}
253
254// virtual
255void LLImageRaw::deleteData()
256{
257 sGlobalRawMemory -= getDataSize();
258 LLImageBase::deleteData();
259}
260
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)
272{
273 if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components))
274 {
275 return TRUE;
276 }
277 // Reallocate the data buffer.
278 deleteData();
279
280 allocateDataSize(width,height,components);
281
282 return TRUE;
283}
284
285U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const
286{
287 LLMemType mt1((LLMemType::EMemType)mMemType);
288 U8 *data = new U8[width*height*getComponents()];
289
290 // Should do some simple bounds checking
291
292 U32 i;
293 for (i = y_pos; i < y_pos+height; i++)
294 {
295 memcpy(data + i*width*getComponents(),
296 getData() + ((y_pos + i)*getWidth() + x_pos)*getComponents(), getComponents()*width);
297 }
298 return data;
299}
300
301BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
302 const U8 *data, U32 stride, BOOL reverse_y)
303{
304 if (!getData())
305 {
306 return FALSE;
307 }
308 if (!data)
309 {
310 return FALSE;
311 }
312
313 // Should do some simple bounds checking
314
315 U32 i;
316 U32 to_offset;
317 U32 from_offset;
318 if (!reverse_y)
319 {
320 for (i = 0; i < height; i++)
321 {
322 to_offset = (y_pos + i)*getWidth() + x_pos;
323 if (stride != 0)
324 {
325 from_offset = i*stride;
326 }
327 else
328 {
329 from_offset = i*width*getComponents();
330 }
331 memcpy(getData() + to_offset*getComponents(),
332 data + from_offset, getComponents()*width);
333 }
334 }
335 else
336 {
337 for (i = 0; i < height; i++)
338 {
339 to_offset = (y_pos + i)*getWidth() + x_pos;
340 if (stride != 0)
341 {
342 from_offset = (height - 1 - i)*stride;
343 }
344 else
345 {
346 from_offset = (height - 1 - i)*width*getComponents();
347 }
348 memcpy(getData() + to_offset*getComponents(),
349 data + from_offset, getComponents()*width);
350 }
351 }
352 return TRUE;
353}
354
355void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a)
356{
357 llassert( getComponents() <= 4 );
358 // This is fairly bogus, but it'll do for now.
359 U8 *pos = getData();
360 U32 x, y;
361 for (x = 0; x < getWidth(); x++)
362 {
363 for (y = 0; y < getHeight(); y++)
364 {
365 *pos = r;
366 pos++;
367 if (getComponents() == 1)
368 {
369 continue;
370 }
371 *pos = g;
372 pos++;
373 if (getComponents() == 2)
374 {
375 continue;
376 }
377 *pos = b;
378 pos++;
379 if (getComponents() == 3)
380 {
381 continue;
382 }
383 *pos = a;
384 pos++;
385 }
386 }
387}
388
389// Reverses the order of the rows in the image
390void LLImageRaw::verticalFlip()
391{
392 LLMemType mt1((LLMemType::EMemType)mMemType);
393 S32 row_bytes = getWidth() * getComponents();
394 U8* line_buffer = new U8[row_bytes];
395 S32 mid_row = getHeight() / 2;
396 for( S32 row = 0; row < mid_row; row++ )
397 {
398 U8* row_a_data = getData() + row * row_bytes;
399 U8* row_b_data = getData() + (getHeight() - 1 - row) * row_bytes;
400 memcpy( line_buffer, row_a_data, row_bytes );
401 memcpy( row_a_data, row_b_data, row_bytes );
402 memcpy( row_b_data, line_buffer, row_bytes );
403 }
404 delete[] line_buffer;
405}
406
407
408void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
409{
410 // Find new sizes
411 S32 new_width = MIN_IMAGE_SIZE;
412 S32 new_height = MIN_IMAGE_SIZE;
413
414 while( (new_width < getWidth()) && (new_width < max_dim) )
415 {
416 new_width <<= 1;
417 }
418
419 while( (new_height < getHeight()) && (new_height < max_dim) )
420 {
421 new_height <<= 1;
422 }
423
424 scale( new_width, new_height, scale_image );
425}
426
427void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image)
428{
429 // Find new sizes
430 S32 new_width = max_dim;
431 S32 new_height = max_dim;
432
433 while( (new_width > getWidth()) && (new_width > MIN_IMAGE_SIZE) )
434 {
435 new_width >>= 1;
436 }
437
438 while( (new_height > getHeight()) && (new_height > MIN_IMAGE_SIZE) )
439 {
440 new_height >>= 1;
441 }
442
443 scale( new_width, new_height, scale_image );
444}
445
446void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
447{
448 // Strong bias towards rounding down (to save bandwidth)
449 // No bias would mean THRESHOLD == 1.5f;
450 const F32 THRESHOLD = 1.75f;
451
452 // Find new sizes
453 S32 larger_w = max_dim; // 2^n >= mWidth
454 S32 smaller_w = max_dim; // 2^(n-1) <= mWidth
455 while( (smaller_w > getWidth()) && (smaller_w > MIN_IMAGE_SIZE) )
456 {
457 larger_w = smaller_w;
458 smaller_w >>= 1;
459 }
460 S32 new_width = ( (F32)getWidth() / smaller_w > THRESHOLD ) ? larger_w : smaller_w;
461
462
463 S32 larger_h = max_dim; // 2^m >= mHeight
464 S32 smaller_h = max_dim; // 2^(m-1) <= mHeight
465 while( (smaller_h > getHeight()) && (smaller_h > MIN_IMAGE_SIZE) )
466 {
467 larger_h = smaller_h;
468 smaller_h >>= 1;
469 }
470 S32 new_height = ( (F32)getHeight() / smaller_h > THRESHOLD ) ? larger_h : smaller_h;
471
472
473 scale( new_width, new_height );
474}
475
476
477
478
479// Calculates (U8)(255*(a/255.f)*(b/255.f) + 0.5f). Thanks, Jim Blinn!
480inline U8 LLImageRaw::fastFractionalMult( U8 a, U8 b )
481{
482 U32 i = a * b + 128;
483 return U8((i + (i>>8)) >> 8);
484}
485
486
487void LLImageRaw::composite( LLImageRaw* src )
488{
489 LLImageRaw* dst = this; // Just for clarity.
490
491 llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
492 llassert( (3 == dst->getComponents()) || (4 == dst->getComponents()) );
493
494 if( 3 == dst->getComponents() )
495 {
496 if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
497 {
498 // No scaling needed
499 if( 3 == src->getComponents() )
500 {
501 copyUnscaled( src ); // alpha is one so just copy the data.
502 }
503 else
504 {
505 compositeUnscaled4onto3( src );
506 }
507 }
508 else
509 {
510 if( 3 == src->getComponents() )
511 {
512 copyScaled( src ); // alpha is one so just copy the data.
513 }
514 else
515 {
516 compositeScaled4onto3( src );
517 }
518 }
519 }
520 else
521 {
522 // 4 == dst->mComponents
523 llassert(0); // not implemented yet.
524 }
525}
526
527// Src and dst can be any size. Src has 4 components. Dst has 3 components.
528void LLImageRaw::compositeScaled4onto3(LLImageRaw* src)
529{
530 LLMemType mt1((LLMemType::EMemType)mMemType);
531 llinfos << "compositeScaled4onto3" << llendl;
532
533 LLImageRaw* dst = this; // Just for clarity.
534
535 llassert( (4 == src->getComponents()) && (3 == dst->getComponents()) );
536
537 // Vertical: scale but no composite
538 S32 temp_data_size = src->getWidth() * dst->getHeight() * src->getComponents();
539 U8* temp_buffer = new U8[ temp_data_size ];
540 for( S32 col = 0; col < src->getWidth(); col++ )
541 {
542 copyLineScaled( src->getData() + (src->getComponents() * col), temp_buffer + (src->getComponents() * col), src->getHeight(), dst->getHeight(), src->getWidth(), src->getWidth() );
543 }
544
545 // Horizontal: scale and composite
546 for( S32 row = 0; row < dst->getHeight(); row++ )
547 {
548 compositeRowScaled4onto3( temp_buffer + (src->getComponents() * src->getWidth() * row), dst->getData() + (dst->getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth() );
549 }
550
551 // Clean up
552 delete[] temp_buffer;
553}
554
555
556// Src and dst are same size. Src has 4 components. Dst has 3 components.
557void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src )
558{
559 /*
560 //test fastFractionalMult()
561 {
562 U8 i = 255;
563 U8 j = 255;
564 do
565 {
566 do
567 {
568 llassert( fastFractionalMult(i, j) == (U8)(255*(i/255.f)*(j/255.f) + 0.5f) );
569 } while( j-- );
570 } while( i-- );
571 }
572 */
573
574 LLImageRaw* dst = this; // Just for clarity.
575
576 llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
577 llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
578
579
580 U8* src_data = src->getData();
581 U8* dst_data = dst->getData();
582 S32 pixels = getWidth() * getHeight();
583 while( pixels-- )
584 {
585 U8 alpha = src_data[3];
586 if( alpha )
587 {
588 if( 255 == alpha )
589 {
590 dst_data[0] = src_data[0];
591 dst_data[1] = src_data[1];
592 dst_data[2] = src_data[2];
593 }
594 else
595 {
596
597 U8 transparency = 255 - alpha;
598 dst_data[0] = fastFractionalMult( dst_data[0], transparency ) + fastFractionalMult( src_data[0], alpha );
599 dst_data[1] = fastFractionalMult( dst_data[1], transparency ) + fastFractionalMult( src_data[1], alpha );
600 dst_data[2] = fastFractionalMult( dst_data[2], transparency ) + fastFractionalMult( src_data[2], alpha );
601 }
602 }
603
604 src_data += 4;
605 dst_data += 3;
606 }
607}
608
609// Fill the buffer with a constant color
610void LLImageRaw::fill( const LLColor4U& color )
611{
612 S32 pixels = getWidth() * getHeight();
613 if( 4 == getComponents() )
614 {
615 U32* data = (U32*) getData();
616 for( S32 i = 0; i < pixels; i++ )
617 {
618 data[i] = color.mAll;
619 }
620 }
621 else
622 if( 3 == getComponents() )
623 {
624 U8* data = getData();
625 for( S32 i = 0; i < pixels; i++ )
626 {
627 data[0] = color.mV[0];
628 data[1] = color.mV[1];
629 data[2] = color.mV[2];
630 data += 3;
631 }
632 }
633}
634
635
636
637
638// Src and dst can be any size. Src and dst can each have 3 or 4 components.
639void LLImageRaw::copy(LLImageRaw* src)
640{
641 LLImageRaw* dst = this; // Just for clarity.
642
643 llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
644 llassert( (3 == dst->getComponents()) || (4 == dst->getComponents()) );
645
646 if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
647 {
648 // No scaling needed
649 if( src->getComponents() == dst->getComponents() )
650 {
651 copyUnscaled( src );
652 }
653 else
654 if( 3 == src->getComponents() )
655 {
656 copyUnscaled3onto4( src );
657 }
658 else
659 {
660 // 4 == src->getComponents()
661 copyUnscaled4onto3( src );
662 }
663 }
664 else
665 {
666 // Scaling needed
667 // No scaling needed
668 if( src->getComponents() == dst->getComponents() )
669 {
670 copyScaled( src );
671 }
672 else
673 if( 3 == src->getComponents() )
674 {
675 copyScaled3onto4( src );
676 }
677 else
678 {
679 // 4 == src->getComponents()
680 copyScaled4onto3( src );
681 }
682 }
683}
684
685// Src and dst are same size. Src and dst have same number of components.
686void LLImageRaw::copyUnscaled(LLImageRaw* src)
687{
688 LLImageRaw* dst = this; // Just for clarity.
689
690 llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
691 llassert( src->getComponents() == dst->getComponents() );
692 llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
693
694 memcpy( dst->getData(), src->getData(), getWidth() * getHeight() * getComponents() );
695}
696
697
698// Src and dst can be any size. Src has 3 components. Dst has 4 components.
699void LLImageRaw::copyScaled3onto4(LLImageRaw* src)
700{
701 llassert( (3 == src->getComponents()) && (4 == getComponents()) );
702
703 // Slow, but simple. Optimize later if needed.
704 LLImageRaw temp( src->getWidth(), src->getHeight(), 4);
705 temp.copyUnscaled3onto4( src );
706 copyScaled( &temp );
707}
708
709
710// Src and dst can be any size. Src has 4 components. Dst has 3 components.
711void LLImageRaw::copyScaled4onto3(LLImageRaw* src)
712{
713 llassert( (4 == src->getComponents()) && (3 == getComponents()) );
714
715 // Slow, but simple. Optimize later if needed.
716 LLImageRaw temp( src->getWidth(), src->getHeight(), 3);
717 temp.copyUnscaled4onto3( src );
718 copyScaled( &temp );
719}
720
721
722// Src and dst are same size. Src has 4 components. Dst has 3 components.
723void LLImageRaw::copyUnscaled4onto3( LLImageRaw* src )
724{
725 LLImageRaw* dst = this; // Just for clarity.
726
727 llassert( (3 == dst->getComponents()) && (4 == src->getComponents()) );
728 llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
729
730 S32 pixels = getWidth() * getHeight();
731 U8* src_data = src->getData();
732 U8* dst_data = dst->getData();
733 for( S32 i=0; i<pixels; i++ )
734 {
735 dst_data[0] = src_data[0];
736 dst_data[1] = src_data[1];
737 dst_data[2] = src_data[2];
738 src_data += 4;
739 dst_data += 3;
740 }
741}
742
743
744// Src and dst are same size. Src has 3 components. Dst has 4 components.
745void LLImageRaw::copyUnscaled3onto4( LLImageRaw* src )
746{
747 LLImageRaw* dst = this; // Just for clarity.
748 llassert( 3 == src->getComponents() );
749 llassert( 4 == dst->getComponents() );
750 llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
751
752 S32 pixels = getWidth() * getHeight();
753 U8* src_data = src->getData();
754 U8* dst_data = dst->getData();
755 for( S32 i=0; i<pixels; i++ )
756 {
757 dst_data[0] = src_data[0];
758 dst_data[1] = src_data[1];
759 dst_data[2] = src_data[2];
760 dst_data[3] = 255;
761 src_data += 3;
762 dst_data += 4;
763 }
764}
765
766
767// Src and dst can be any size. Src and dst have same number of components.
768void LLImageRaw::copyScaled( LLImageRaw* src )
769{
770 LLMemType mt1((LLMemType::EMemType)mMemType);
771 LLImageRaw* dst = this; // Just for clarity.
772
773 llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
774 llassert( src->getComponents() == dst->getComponents() );
775
776 if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
777 {
778 memcpy( dst->getData(), src->getData(), getWidth() * getHeight() * getComponents() );
779 return;
780 }
781
782 // Vertical
783 S32 temp_data_size = src->getWidth() * dst->getHeight() * getComponents();
784 U8* temp_buffer = new U8[ temp_data_size ];
785 for( S32 col = 0; col < src->getWidth(); col++ )
786 {
787 copyLineScaled( src->getData() + (getComponents() * col), temp_buffer + (getComponents() * col), src->getHeight(), dst->getHeight(), src->getWidth(), src->getWidth() );
788 }
789
790 // Horizontal
791 for( S32 row = 0; row < dst->getHeight(); row++ )
792 {
793 copyLineScaled( temp_buffer + (getComponents() * src->getWidth() * row), dst->getData() + (getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth(), 1, 1 );
794 }
795
796 // Clean up
797 delete[] temp_buffer;
798}
799
800
801void LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
802{
803 LLMemType mt1((LLMemType::EMemType)mMemType);
804 llassert( (3 == getComponents()) || (4 == getComponents()) );
805
806 S32 old_width = getWidth();
807 S32 old_height = getHeight();
808
809 if( (old_width == new_width) && (old_height == new_height) )
810 {
811 return; // Nothing to do.
812 }
813
814 // Reallocate the data buffer.
815
816 if (scale_image_data)
817 {
818 // Vertical
819 S32 temp_data_size = old_width * new_height * getComponents();
820 U8* temp_buffer = new U8[ temp_data_size ];
821 for( S32 col = 0; col < old_width; col++ )
822 {
823 copyLineScaled( getData() + (getComponents() * col), temp_buffer + (getComponents() * col), old_height, new_height, old_width, old_width );
824 }
825
826 deleteData();
827
828 U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
829
830 // Horizontal
831 for( S32 row = 0; row < new_height; row++ )
832 {
833 copyLineScaled( temp_buffer + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 );
834 }
835
836 // Clean up
837 delete[] temp_buffer;
838 }
839 else
840 {
841 // copy out existing image data
842 S32 temp_data_size = old_width * old_height * getComponents();
843 U8* temp_buffer = new U8[ temp_data_size ];
844 memcpy(temp_buffer, getData(), temp_data_size);
845
846 // allocate new image data, will delete old data
847 U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
848
849 for( S32 row = 0; row < new_height; row++ )
850 {
851 if (row < old_height)
852 {
853 memcpy(new_buffer + (new_width * row * getComponents()), temp_buffer + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width));
854 if (old_width < new_width)
855 {
856 // pad out rest of row with black
857 memset(new_buffer + (getComponents() * ((new_width * row) + old_width)), 0, getComponents() * (new_width - old_width));
858 }
859 }
860 else
861 {
862 // pad remaining rows with black
863 memset(new_buffer + (new_width * row * getComponents()), 0, new_width * getComponents());
864 }
865 }
866
867 // Clean up
868 delete[] temp_buffer;
869 }
870}
871
872void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step )
873{
874 const S32 components = getComponents();
875 llassert( components >= 1 && components <= 4 );
876
877 const F32 ratio = F32(in_pixel_len) / out_pixel_len; // ratio of old to new
878 const F32 norm_factor = 1.f / ratio;
879
880 S32 goff = components >= 2 ? 1 : 0;
881 S32 boff = components >= 3 ? 2 : 0;
882 for( S32 x = 0; x < out_pixel_len; x++ )
883 {
884 // Sample input pixels in range from sample0 to sample1.
885 // Avoid floating point accumulation error... don't just add ratio each time. JC
886 const F32 sample0 = x * ratio;
887 const F32 sample1 = (x+1) * ratio;
888 const S32 index0 = llfloor(sample0); // left integer (floor)
889 const S32 index1 = llfloor(sample1); // right integer (floor)
890 const F32 fract0 = 1.f - (sample0 - F32(index0)); // spill over on left
891 const F32 fract1 = sample1 - F32(index1); // spill-over on right
892
893 if( index0 == index1 )
894 {
895 // Interval is embedded in one input pixel
896 S32 t0 = x * out_pixel_step * components;
897 S32 t1 = index0 * in_pixel_step * components;
898 U8* outp = out + t0;
899 U8* inp = in + t1;
900 for (S32 i = 0; i < components; ++i)
901 {
902 *outp = *inp;
903 ++outp;
904 ++inp;
905 }
906 }
907 else
908 {
909 // Left straddle
910 S32 t1 = index0 * in_pixel_step * components;
911 F32 r = in[t1 + 0] * fract0;
912 F32 g = in[t1 + goff] * fract0;
913 F32 b = in[t1 + boff] * fract0;
914 F32 a = 0;
915 if( components == 4)
916 {
917 a = in[t1 + 3] * fract0;
918 }
919
920 // Central interval
921 if (components < 4)
922 {
923 for( S32 u = index0 + 1; u < index1; u++ )
924 {
925 S32 t2 = u * in_pixel_step * components;
926 r += in[t2 + 0];
927 g += in[t2 + goff];
928 b += in[t2 + boff];
929 }
930 }
931 else
932 {
933 for( S32 u = index0 + 1; u < index1; u++ )
934 {
935 S32 t2 = u * in_pixel_step * components;
936 r += in[t2 + 0];
937 g += in[t2 + 1];
938 b += in[t2 + 2];
939 a += in[t2 + 3];
940 }
941 }
942
943 // right straddle
944 // Watch out for reading off of end of input array.
945 if( fract1 && index1 < in_pixel_len )
946 {
947 S32 t3 = index1 * in_pixel_step * components;
948 if (components < 4)
949 {
950 U8 in0 = in[t3 + 0];
951 U8 in1 = in[t3 + goff];
952 U8 in2 = in[t3 + boff];
953 r += in0 * fract1;
954 g += in1 * fract1;
955 b += in2 * fract1;
956 }
957 else
958 {
959 U8 in0 = in[t3 + 0];
960 U8 in1 = in[t3 + 1];
961 U8 in2 = in[t3 + 2];
962 U8 in3 = in[t3 + 3];
963 r += in0 * fract1;
964 g += in1 * fract1;
965 b += in2 * fract1;
966 a += in3 * fract1;
967 }
968 }
969
970 r *= norm_factor;
971 g *= norm_factor;
972 b *= norm_factor;
973 a *= norm_factor; // skip conditional
974
975 S32 t4 = x * out_pixel_step * components;
976 out[t4 + 0] = U8(llround(r));
977 if (components >= 2)
978 out[t4 + 1] = U8(llround(g));
979 if (components >= 3)
980 out[t4 + 2] = U8(llround(b));
981 if( components == 4)
982 out[t4 + 3] = U8(llround(a));
983 }
984 }
985}
986
987void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len )
988{
989 llassert( getComponents() == 3 );
990
991 const S32 IN_COMPONENTS = 4;
992 const S32 OUT_COMPONENTS = 3;
993
994 const F32 ratio = F32(in_pixel_len) / out_pixel_len; // ratio of old to new
995 const F32 norm_factor = 1.f / ratio;
996
997 for( S32 x = 0; x < out_pixel_len; x++ )
998 {
999 // Sample input pixels in range from sample0 to sample1.
1000 // Avoid floating point accumulation error... don't just add ratio each time. JC
1001 const F32 sample0 = x * ratio;
1002 const F32 sample1 = (x+1) * ratio;
1003 const S32 index0 = S32(sample0); // left integer (floor)
1004 const S32 index1 = S32(sample1); // right integer (floor)
1005 const F32 fract0 = 1.f - (sample0 - F32(index0)); // spill over on left
1006 const F32 fract1 = sample1 - F32(index1); // spill-over on right
1007
1008 U8 in_scaled_r;
1009 U8 in_scaled_g;
1010 U8 in_scaled_b;
1011 U8 in_scaled_a;
1012
1013 if( index0 == index1 )
1014 {
1015 // Interval is embedded in one input pixel
1016 S32 t1 = index0 * IN_COMPONENTS;
1017 in_scaled_r = in[t1 + 0];
1018 in_scaled_g = in[t1 + 0];
1019 in_scaled_b = in[t1 + 0];
1020 in_scaled_a = in[t1 + 0];
1021 }
1022 else
1023 {
1024 // Left straddle
1025 S32 t1 = index0 * IN_COMPONENTS;
1026 F32 r = in[t1 + 0] * fract0;
1027 F32 g = in[t1 + 1] * fract0;
1028 F32 b = in[t1 + 2] * fract0;
1029 F32 a = in[t1 + 3] * fract0;
1030
1031 // Central interval
1032 for( S32 u = index0 + 1; u < index1; u++ )
1033 {
1034 S32 t2 = u * IN_COMPONENTS;
1035 r += in[t2 + 0];
1036 g += in[t2 + 1];
1037 b += in[t2 + 2];
1038 a += in[t2 + 3];
1039 }
1040
1041 // right straddle
1042 // Watch out for reading off of end of input array.
1043 if( fract1 && index1 < in_pixel_len )
1044 {
1045 S32 t3 = index1 * IN_COMPONENTS;
1046 r += in[t3 + 0] * fract1;
1047 g += in[t3 + 1] * fract1;
1048 b += in[t3 + 2] * fract1;
1049 a += in[t3 + 3] * fract1;
1050 }
1051
1052 r *= norm_factor;
1053 g *= norm_factor;
1054 b *= norm_factor;
1055 a *= norm_factor;
1056
1057 in_scaled_r = U8(llround(r));
1058 in_scaled_g = U8(llround(g));
1059 in_scaled_b = U8(llround(b));
1060 in_scaled_a = U8(llround(a));
1061 }
1062
1063 if( in_scaled_a )
1064 {
1065 if( 255 == in_scaled_a )
1066 {
1067 out[0] = in_scaled_r;
1068 out[1] = in_scaled_g;
1069 out[2] = in_scaled_b;
1070 }
1071 else
1072 {
1073 U8 transparency = 255 - in_scaled_a;
1074 out[0] = fastFractionalMult( out[0], transparency ) + fastFractionalMult( in_scaled_r, in_scaled_a );
1075 out[1] = fastFractionalMult( out[1], transparency ) + fastFractionalMult( in_scaled_g, in_scaled_a );
1076 out[2] = fastFractionalMult( out[2], transparency ) + fastFractionalMult( in_scaled_b, in_scaled_a );
1077 }
1078 }
1079 out += OUT_COMPONENTS;
1080 }
1081}
1082
1083
1084//----------------------------------------------------------------------------
1085
1086static struct
1087{
1088 const char* exten;
1089 S8 codec;
1090}
1091file_extensions[] =
1092{
1093 { "bmp", IMG_CODEC_BMP },
1094 { "tga", IMG_CODEC_TGA },
1095 { "j2c", IMG_CODEC_J2C },
1096 { "jp2", IMG_CODEC_J2C },
1097 { "texture", IMG_CODEC_J2C },
1098 { "jpg", IMG_CODEC_JPEG },
1099 { "jpeg", IMG_CODEC_JPEG },
1100 { "mip", IMG_CODEC_DXT },
1101 { "dxt", IMG_CODEC_DXT }
1102};
1103#define NUM_FILE_EXTENSIONS sizeof(file_extensions)/sizeof(file_extensions[0])
1104
1105static LLString find_file(LLString &name, S8 *codec)
1106{
1107 LLString tname;
1108 for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++)
1109 {
1110 tname = name + "." + LLString(file_extensions[i].exten);
1111 llifstream ifs(tname.c_str(), llifstream::binary);
1112 if (ifs.is_open())
1113 {
1114 ifs.close();
1115 if (codec)
1116 *codec = file_extensions[i].codec;
1117 return LLString(file_extensions[i].exten);
1118 }
1119 }
1120 return LLString("");
1121}
1122
1123static S8 get_codec(const LLString& exten)
1124{
1125 for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++)
1126 {
1127 if (exten == file_extensions[i].exten)
1128 return file_extensions[i].codec;
1129 }
1130 return IMG_CODEC_INVALID;
1131}
1132
1133bool LLImageRaw::createFromFile(const LLString &filename, bool j2c_lowest_mip_only)
1134{
1135 LLString name = filename;
1136 size_t dotidx = name.rfind('.');
1137 S8 codec = IMG_CODEC_INVALID;
1138 LLString exten;
1139
1140 deleteData(); // delete any existing data
1141
1142 if (dotidx != LLString::npos)
1143 {
1144 exten = name.substr(dotidx+1);
1145 LLString::toLower(exten);
1146 codec = get_codec(exten);
1147 }
1148 else
1149 {
1150 exten = find_file(name, &codec);
1151 name = name + "." + exten;
1152 }
1153 if (codec == IMG_CODEC_INVALID)
1154 {
1155 return false; // format not recognized
1156 }
1157
1158 llifstream ifs(name.c_str(), llifstream::binary);
1159 if (!ifs.is_open())
1160 {
1161 // SJB: changed from llinfos to lldebugs to reduce spam
1162 lldebugs << "Unable to open image file: " << name << llendl;
1163 return false;
1164 }
1165
1166 ifs.seekg (0, std::ios::end);
1167 int length = ifs.tellg();
1168 if (j2c_lowest_mip_only && length > 2048)
1169 {
1170 length = 2048;
1171 }
1172 ifs.seekg (0, std::ios::beg);
1173
1174 if (!length)
1175 {
1176 llinfos << "Zero length file file: " << name << llendl;
1177 return false;
1178 }
1179
1180 LLPointer<LLImageFormatted> image;
1181 switch(codec)
1182 {
1183 //case IMG_CODEC_RGB:
1184 case IMG_CODEC_BMP:
1185 image = new LLImageBMP();
1186 break;
1187 case IMG_CODEC_TGA:
1188 image = new LLImageTGA();
1189 break;
1190#if JPEG_SUPPORT
1191 case IMG_CODEC_JPEG:
1192 image = new LLImageJPEG();
1193 break;
1194#endif
1195 case IMG_CODEC_J2C:
1196 image = new LLImageJ2C();
1197 break;
1198 case IMG_CODEC_DXT:
1199 image = new LLImageDXT();
1200 break;
1201 default:
1202 return false;
1203 }
1204 llassert(image.notNull());
1205
1206 U8 *buffer = image->allocateData(length);
1207 ifs.read ((char*)buffer, length);
1208 ifs.close();
1209
1210 image->updateData();
1211
1212 if (j2c_lowest_mip_only && codec == IMG_CODEC_J2C)
1213 {
1214 S32 width = image->getWidth();
1215 S32 height = image->getHeight();
1216 S32 discard_level = 0;
1217 while (width > 1 && height > 1 && discard_level < MAX_DISCARD_LEVEL)
1218 {
1219 width >>= 1;
1220 height >>= 1;
1221 discard_level++;
1222 }
1223 ((LLImageJ2C *)((LLImageFormatted*)image))->setDiscardLevel(discard_level);
1224 }
1225
1226 BOOL success = image->decode(this, 100000.0f);
1227 image = NULL; // deletes image
1228
1229 if (!success)
1230 {
1231 deleteData();
1232 llwarns << "Unable to decode image" << name << llendl;
1233 return false;
1234 }
1235
1236 return true;
1237}
1238
1239//---------------------------------------------------------------------------
1240// LLImageFormatted
1241//---------------------------------------------------------------------------
1242
1243//static
1244S32 LLImageFormatted::sGlobalFormattedMemory = 0;
1245
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)
1264 : LLImageBase(), LLWorkerClass(sWorkerThread, "ImageFormatted"),
1265 mCodec(codec),
1266 mDecoding(0),
1267 mDecoded(0),
1268 mDiscardLevel(0)
1269{
1270 mMemType = LLMemType::MTYPE_IMAGEFORMATTED;
1271}
1272
1273// virtual
1274LLImageFormatted::~LLImageFormatted()
1275{
1276 // NOTE: ~LLimageBase() call to deleteData() calls LLImageBase::deleteData()
1277 // NOT LLImageFormatted::deleteData()
1278 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}
1319
1320//----------------------------------------------------------------------------
1321
1322// static
1323LLImageFormatted* LLImageFormatted::createFromExtension(const LLString& instring)
1324{
1325 LLString exten;
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)
1338 {
1339 case IMG_CODEC_BMP:
1340 image = new LLImageBMP();
1341 break;
1342 case IMG_CODEC_TGA:
1343 image = new LLImageTGA();
1344 break;
1345#if JPEG_SUPPORT
1346 case IMG_CODEC_JPEG:
1347 image = new LLImageJPEG();
1348 break;
1349#endif
1350 case IMG_CODEC_J2C:
1351 image = new LLImageJ2C();
1352 break;
1353 case IMG_CODEC_DXT:
1354 image = new LLImageDXT();
1355 break;
1356 default:
1357 break;
1358 }
1359 return image;
1360}
1361//----------------------------------------------------------------------------
1362
1363// virtual
1364void LLImageFormatted::dump()
1365{
1366 LLImageBase::dump();
1367
1368 llinfos << "LLImageFormatted"
1369 << " mDecoding " << mDecoding
1370 << " mCodec " << S32(mCodec)
1371 << " mDecoded " << mDecoded
1372 << llendl;
1373}
1374
1375//----------------------------------------------------------------------------
1376
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)
1387{
1388 if (discard_level < 0)
1389 {
1390 discard_level = mDiscardLevel;
1391 }
1392 S32 w = getWidth() >> discard_level;
1393 S32 h = getHeight() >> discard_level;
1394 w = llmax(w, 1);
1395 h = llmax(h, 1);
1396 return w * h * getComponents();
1397}
1398
1399S32 LLImageFormatted::calcDiscardLevelBytes(S32 bytes)
1400{
1401 llassert(bytes >= 0);
1402 S32 discard_level = 0;
1403 while (1)
1404 {
1405 S32 bytes_needed = calcDataSize(discard_level); // virtual
1406 if (bytes_needed <= bytes)
1407 {
1408 break;
1409 }
1410 discard_level++;
1411 if (discard_level > MAX_IMAGE_MIP)
1412 {
1413 return -1;
1414 }
1415 }
1416 return discard_level;
1417}
1418
1419
1420//----------------------------------------------------------------------------
1421
1422// Subclasses that can handle more than 4 channels should override this function.
1423BOOL LLImageFormatted::decode(LLImageRaw* raw_image,F32 decode_time, S32 first_channel, S32 max_channel)
1424{
1425 llassert( (first_channel == 0) && (max_channel == 4) );
1426 return decode( raw_image, decode_time ); // Loads first 4 channels by default.
1427}
1428
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//----------------------------------------------------------------------------
1506
1507// virtual
1508U8* LLImageFormatted::allocateData(S32 size)
1509{
1510 U8* res = LLImageBase::allocateData(size); // calls deleteData()
1511 sGlobalFormattedMemory += getDataSize();
1512 return res;
1513}
1514
1515// virtual
1516U8* LLImageFormatted::reallocateData(S32 size)
1517{
1518 sGlobalFormattedMemory -= getDataSize();
1519 U8* res = LLImageBase::reallocateData(size);
1520 sGlobalFormattedMemory += getDataSize();
1521 return res;
1522}
1523
1524// virtual
1525void LLImageFormatted::deleteData()
1526{
1527 sGlobalFormattedMemory -= getDataSize();
1528 LLImageBase::deleteData();
1529}
1530
1531//----------------------------------------------------------------------------
1532
1533// virtual
1534void LLImageFormatted::sanityCheck()
1535{
1536 LLImageBase::sanityCheck();
1537
1538 if (mCodec >= IMG_CODEC_EOF)
1539 {
1540 llerrs << "Failed LLImageFormatted::sanityCheck "
1541 << "decoding " << S32(mDecoding)
1542 << "decoded " << S32(mDecoded)
1543 << "codec " << S32(mCodec)
1544 << llendl;
1545 }
1546}
1547
1548//----------------------------------------------------------------------------
1549
1550BOOL LLImageFormatted::copyData(U8 *data, S32 size)
1551{
1552 if (data && data != getData())
1553 {
1554 deleteData();
1555 allocateData(size);
1556 memcpy(getData(), data, size);
1557 }
1558 updateData(); // virtual
1559
1560 return TRUE;
1561}
1562
1563BOOL LLImageFormatted::appendData(U8 *data, S32 size)
1564{
1565 LLMemType mt1((LLMemType::EMemType)mMemType);
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 {
1578 memcpy(new_data + old_size, data, size);
1579 updateData(); // virtual
1580 }
1581 return TRUE;
1582}
1583
1584BOOL LLImageFormatted::setData(U8 *data, S32 size)
1585{
1586 if (data && data != getData())
1587 {
1588 deleteData();
1589 setDataAndSize(data, size); // Access private LLImageBase members
1590 sGlobalFormattedMemory += getDataSize();
1591 }
1592 return updateData(); // virtual
1593}
1594
1595//----------------------------------------------------------------------------
1596
1597BOOL LLImageFormatted::load(const LLString &filename)
1598{
1599 resetLastError();
1600
1601 S32 file_size = 0;
1602 apr_file_t* apr_file = ll_apr_file_open(filename, LL_APR_RB, &file_size);
1603 if (!apr_file)
1604 {
1605 setLastError("Unable to open file for reading", filename);
1606 return FALSE;
1607 }
1608 if (file_size == 0)
1609 {
1610 setLastError("File is empty",filename);
1611 apr_file_close(apr_file);
1612 return FALSE;
1613 }
1614
1615 BOOL res;
1616 U8 *data = allocateData(file_size);
1617 apr_size_t bytes_read = file_size;
1618 apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
1619 if (s != APR_SUCCESS || (S32) bytes_read != file_size)
1620 {
1621 deleteData();
1622 setLastError("Unable to read entire file",filename);
1623 res = FALSE;
1624 }
1625 else
1626 {
1627 res = updateData();
1628 }
1629 apr_file_close(apr_file);
1630
1631 return res;
1632}
1633
1634BOOL LLImageFormatted::save(const LLString &filename)
1635{
1636 resetLastError();
1637
1638 apr_file_t* apr_file = ll_apr_file_open(filename, LL_APR_WB);
1639 if (!apr_file)
1640 {
1641 setLastError("Unable to open file for reading", filename);
1642 return FALSE;
1643 }
1644
1645 ll_apr_file_write(apr_file, getData(), getDataSize());
1646 apr_file_close(apr_file);
1647
1648 return TRUE;
1649}
1650
1651// BOOL LLImageFormatted::save(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
1652// Depricated to remove VFS dependency.
1653// Use:
1654// LLVFile::writeFile(image->getData(), image->getDataSize(), vfs, uuid, type);
1655
1656//----------------------------------------------------------------------------
1657
1658S8 LLImageFormatted::getCodec() const
1659{
1660 return mCodec;
1661}
1662
1663//============================================================================
1664
1665//----------------------------------------------------------------------------
1666
1667static void avg4_colors4(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst)
1668{
1669 dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2);
1670 dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2);
1671 dst[2] = (U8)(((U32)(a[2]) + b[2] + c[2] + d[2])>>2);
1672 dst[3] = (U8)(((U32)(a[3]) + b[3] + c[3] + d[3])>>2);
1673}
1674
1675static void avg4_colors3(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst)
1676{
1677 dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2);
1678 dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2);
1679 dst[2] = (U8)(((U32)(a[2]) + b[2] + c[2] + d[2])>>2);
1680}
1681
1682static void avg4_colors2(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst)
1683{
1684 dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2);
1685 dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2);
1686}
1687
1688//static
1689void LLImageBase::generateMip(const U8* indata, U8* mipdata, S32 width, S32 height, S32 nchannels)
1690{
1691 llassert(width > 0 && height > 0);
1692 U8* data = mipdata;
1693 S32 in_width = width*2;
1694 for (S32 h=0; h<height; h++)
1695 {
1696 for (S32 w=0; w<width; w++)
1697 {
1698 switch(nchannels)
1699 {
1700 case 4:
1701 avg4_colors4(indata, indata+4, indata+4*in_width, indata+4*in_width+4, data);
1702 break;
1703 case 3:
1704 avg4_colors3(indata, indata+3, indata+3*in_width, indata+3*in_width+3, data);
1705 break;
1706 case 2:
1707 avg4_colors2(indata, indata+2, indata+2*in_width, indata+2*in_width+2, data);
1708 break;
1709 case 1:
1710 *(U8*)data = (U8)(((U32)(indata[0]) + indata[1] + indata[in_width] + indata[in_width+1])>>2);
1711 break;
1712 default:
1713 llerrs << "generateMmip called with bad num channels" << llendl;
1714 }
1715 indata += nchannels*2;
1716 data += nchannels;
1717 }
1718 indata += nchannels*in_width; // skip odd lines
1719 }
1720}
1721
1722
1723//============================================================================
1724
1725//static
1726F32 LLImageBase::calc_download_priority(F32 virtual_size, F32 visible_pixels, S32 bytes_sent)
1727{
1728 F32 w_priority;
1729
1730 F32 bytes_weight = 1.f;
1731 if (!bytes_sent)
1732 {
1733 bytes_weight = 20.f;
1734 }
1735 else if (bytes_sent < 1000)
1736 {
1737 bytes_weight = 1.f;
1738 }
1739 else if (bytes_sent < 2000)
1740 {
1741 bytes_weight = 1.f/1.5f;
1742 }
1743 else if (bytes_sent < 4000)
1744 {
1745 bytes_weight = 1.f/3.f;
1746 }
1747 else if (bytes_sent < 8000)
1748 {
1749 bytes_weight = 1.f/6.f;
1750 }
1751 else if (bytes_sent < 16000)
1752 {
1753 bytes_weight = 1.f/12.f;
1754 }
1755 else if (bytes_sent < 32000)
1756 {
1757 bytes_weight = 1.f/20.f;
1758 }
1759 else if (bytes_sent < 64000)
1760 {
1761 bytes_weight = 1.f/32.f;
1762 }
1763 else
1764 {
1765 bytes_weight = 1.f/64.f;
1766 }
1767 bytes_weight *= bytes_weight;
1768
1769
1770 //llinfos << "VS: " << virtual_size << llendl;
1771 F32 virtual_size_factor = virtual_size / (10.f*10.f);
1772
1773 // The goal is for weighted priority to be <= 0 when we've reached a point where
1774 // we've sent enough data.
1775 //llinfos << "BytesSent: " << bytes_sent << llendl;
1776 //llinfos << "BytesWeight: " << bytes_weight << llendl;
1777 //llinfos << "PreLog: " << bytes_weight * virtual_size_factor << llendl;
1778 w_priority = (F32)log10(bytes_weight * virtual_size_factor);
1779
1780 //llinfos << "PreScale: " << w_priority << llendl;
1781
1782 // We don't want to affect how MANY bytes we send based on the visible pixels, but the order
1783 // in which they're sent. We post-multiply so we don't change the zero point.
1784 if (w_priority > 0.f)
1785 {
1786 F32 pixel_weight = (F32)log10(visible_pixels + 1)*3.0f;
1787 w_priority *= pixel_weight;
1788 }
1789
1790 return w_priority;
1791}