aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llimage
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
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')
-rw-r--r--linden/indra/llimage/files.lst6
-rw-r--r--linden/indra/llimage/llimage.cpp1791
-rw-r--r--linden/indra/llimage/llimage.h317
-rw-r--r--linden/indra/llimage/llimage.vcproj209
-rw-r--r--linden/indra/llimage/llimagebmp.cpp643
-rw-r--r--linden/indra/llimage/llimagebmp.h64
-rw-r--r--linden/indra/llimage/llimagedxt.cpp494
-rw-r--r--linden/indra/llimage/llimagedxt.h139
-rw-r--r--linden/indra/llimage/llimagej2c.cpp402
-rw-r--r--linden/indra/llimage/llimagej2c.h99
-rw-r--r--linden/indra/llimage/llimagejpeg.cpp621
-rw-r--r--linden/indra/llimage/llimagejpeg.h82
-rw-r--r--linden/indra/llimage/llimagetga.cpp1109
-rw-r--r--linden/indra/llimage/llimagetga.h108
-rw-r--r--linden/indra/llimage/llmapimagetype.h41
15 files changed, 6125 insertions, 0 deletions
diff --git a/linden/indra/llimage/files.lst b/linden/indra/llimage/files.lst
new file mode 100644
index 0000000..83f53bc
--- /dev/null
+++ b/linden/indra/llimage/files.lst
@@ -0,0 +1,6 @@
1llimage/llimagebmp.cpp
2llimage/llimage.cpp
3llimage/llimagedxt.cpp
4llimage/llimagej2c.cpp
5llimage/llimagejpeg.cpp
6llimage/llimagetga.cpp \ No newline at end of file
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}
diff --git a/linden/indra/llimage/llimage.h b/linden/indra/llimage/llimage.h
new file mode 100644
index 0000000..eb1805a
--- /dev/null
+++ b/linden/indra/llimage/llimage.h
@@ -0,0 +1,317 @@
1/**
2 * @file llimage.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_LLIMAGE_H
29#define LL_LLIMAGE_H
30
31#include "stdtypes.h"
32#include "lluuid.h"
33#include "llstring.h"
34#include "llmemory.h"
35#include "llworkerthread.h"
36
37const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2
38const S32 MAX_IMAGE_MIP = 11; // 2048x2048
39const S32 MAX_DISCARD_LEVEL = 5;
40
41const S32 MIN_IMAGE_SIZE = (1<<MIN_IMAGE_MIP); // 4, only used for expand/contract power of 2
42const S32 MAX_IMAGE_SIZE = (1<<MAX_IMAGE_MIP); // 2048
43const S32 MIN_IMAGE_AREA = MIN_IMAGE_SIZE * MIN_IMAGE_SIZE;
44const S32 MAX_IMAGE_AREA = MAX_IMAGE_SIZE * MAX_IMAGE_SIZE;
45const S32 MAX_IMAGE_COMPONENTS = 8;
46const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS;
47
48// Note! These CANNOT be changed without invalidating the viewer VFS files, I think?
49const S32 FIRST_PACKET_SIZE = 600;
50const S32 MAX_IMG_PACKET_SIZE = 1000;
51
52// Base classes for images.
53// There are two major parts for the image:
54// The compressed representation, and the decompressed representation.
55
56class LLImageFormatted;
57class LLImageRaw;
58class LLColor4U;
59
60enum
61{
62 IMG_CODEC_INVALID = 0,
63 IMG_CODEC_RGB = 1,
64 IMG_CODEC_J2C = 2,
65 IMG_CODEC_BMP = 3,
66 IMG_CODEC_TGA = 4,
67 IMG_CODEC_JPEG = 5,
68 IMG_CODEC_DXT = 6,
69 IMG_CODEC_EOF = 7
70};
71
72//============================================================================
73
74class LLImageBase : public LLThreadSafeRefCount
75{
76protected:
77 virtual ~LLImageBase();
78
79public:
80 LLImageBase();
81
82 enum
83 {
84 TYPE_NORMAL = 0,
85 TYPE_AVATAR_BAKE = 1,
86 };
87
88 virtual void deleteData();
89 virtual U8* allocateData(S32 size = -1);
90 virtual U8* reallocateData(S32 size = -1);
91
92 virtual void dump();
93 virtual void sanityCheck();
94
95 U16 getWidth() const { return mWidth; }
96 U16 getHeight() const { return mHeight; }
97 S8 getComponents() const { return mComponents; }
98 S32 getDataSize() const { return mDataSize; }
99
100 const U8 *getData() const { return mData; } // read only
101 U8 *getData() { return mData; }
102
103 void setSize(S32 width, S32 height, S32 ncomponents);
104 U8* allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 size = -1); // setSize() + allocateData()
105
106protected:
107 // special accessor to allow direct setting of mData and mDataSize by LLImageFormatted
108 void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; };
109
110public:
111 static const LLString& getLastError() {return sLastErrorMessage;};
112 static void resetLastError() {sLastErrorMessage = LLString("No Error"); };
113 static BOOL setLastError(const LLString& message, const LLString& filename = ""); // returns FALSE
114
115 static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
116
117 // Function for calculating the download priority for textes
118 // <= 0 priority means that there's no need for more data.
119 static F32 calc_download_priority(F32 virtual_size, F32 visible_area, S32 bytes_sent);
120
121 static void setSizeOverride(BOOL enabled) { sSizeOverride = enabled; }
122
123private:
124 U8 *mData;
125 S32 mDataSize;
126
127 U16 mWidth;
128 U16 mHeight;
129
130 S8 mComponents;
131
132public:
133 S16 mMemType; // debug
134
135 static LLString sLastErrorMessage;
136
137 static BOOL sSizeOverride;
138};
139
140// Raw representation of an image (used for textures, and other uncompressed formats
141class LLImageRaw : public LLImageBase
142{
143protected:
144 /*virtual*/ ~LLImageRaw();
145
146public:
147 LLImageRaw();
148 LLImageRaw(U16 width, U16 height, S8 components);
149 LLImageRaw(U8 *data, U16 width, U16 height, S8 components);
150 // Construct using createFromFile (used by tools)
151 LLImageRaw(const LLString& filename, bool j2c_lowest_mip_only = false);
152
153 /*virtual*/ void deleteData();
154 /*virtual*/ U8* allocateData(S32 size = -1);
155 /*virtual*/ U8* reallocateData(S32 size);
156
157 BOOL copyData(U8 *data, U16 width, U16 height, S8 components);
158
159 BOOL resize(U16 width, U16 height, S8 components);
160
161 U8 * getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const;
162 BOOL setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
163 const U8 *data, U32 stride = 0, BOOL reverse_y = FALSE);
164
165 void clear(U8 r=0, U8 g=0, U8 b=0, U8 a=255);
166
167 void verticalFlip();
168
169 void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
170 void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
171 void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
172 void scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE );
173
174 // Fill the buffer with a constant color
175 void fill( const LLColor4U& color );
176
177 // Copy operations
178
179 // Src and dst can be any size. Src and dst can each have 3 or 4 components.
180 void copy( LLImageRaw* src );
181
182 // Src and dst are same size. Src and dst have same number of components.
183 void copyUnscaled( LLImageRaw* src );
184
185 // Src and dst are same size. Src has 4 components. Dst has 3 components.
186 void copyUnscaled4onto3( LLImageRaw* src );
187
188 // Src and dst are same size. Src has 3 components. Dst has 4 components.
189 void copyUnscaled3onto4( LLImageRaw* src );
190
191 // Src and dst can be any size. Src and dst have same number of components.
192 void copyScaled( LLImageRaw* src );
193
194 // Src and dst can be any size. Src has 3 components. Dst has 4 components.
195 void copyScaled3onto4( LLImageRaw* src );
196
197 // Src and dst can be any size. Src has 4 components. Dst has 3 components.
198 void copyScaled4onto3( LLImageRaw* src );
199
200
201 // Composite operations
202
203 // Src and dst can be any size. Src and dst can each have 3 or 4 components.
204 void composite( LLImageRaw* src );
205
206 // Src and dst can be any size. Src has 4 components. Dst has 3 components.
207 void compositeScaled4onto3( LLImageRaw* src );
208
209 // Src and dst are same size. Src has 4 components. Dst has 3 components.
210 void compositeUnscaled4onto3( LLImageRaw* src );
211
212protected:
213 // Create an image from a local file (generally used in tools)
214 bool createFromFile(const LLString& filename, bool j2c_lowest_mip_only = false);
215
216 void copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step );
217 void compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len );
218
219 U8 fastFractionalMult(U8 a,U8 b);
220
221public:
222 static S32 sGlobalRawMemory;
223 static S32 sRawImageCount;
224};
225
226// Compressed representation of image.
227// Subclass from this class for the different representations (J2C, bmp)
228class LLImageFormatted : public LLImageBase, public LLWorkerClass
229{
230public:
231 static void initClass(bool threaded = true, bool run_always = true);
232 static void cleanupClass();
233 static LLImageFormatted* createFromExtension(const LLString& instring);
234
235protected:
236 /*virtual*/ ~LLImageFormatted();
237
238public:
239 LLImageFormatted(S8 codec);
240
241 // LLImageBase
242public:
243 /*virtual*/ void deleteData();
244 /*virtual*/ U8* allocateData(S32 size = -1);
245 /*virtual*/ U8* reallocateData(S32 size);
246
247 /*virtual*/ void dump();
248 /*virtual*/ void sanityCheck();
249
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
260public:
261 // calcHeaderSize() returns the maximum size of header;
262 // 0 indicates we don't know have a header and have to lead the entire file
263 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)
267 virtual S32 calcDataSize(S32 discard_level);
268 // calcDiscardLevelBytes() returns the smallest valid discard level based on the number of input bytes
269 virtual S32 calcDiscardLevelBytes(S32 bytes);
270 // getRawDiscardLevel()by default returns mDiscardLevel, but may be overridden (LLImageJ2C)
271 virtual S8 getRawDiscardLevel() { return mDiscardLevel; }
272
273 BOOL load(const LLString& filename);
274 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
278 virtual BOOL updateData() = 0; // pure virtual
279 BOOL copyData(U8 *data, S32 size); // calls updateData()
280 BOOL setData(U8 *data, S32 size); // calls updateData()
281 BOOL appendData(U8 *data, S32 size); // use if some data (e.g header) is already loaded, calls updateData()
282
283 // Loads first 4 channels.
284 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.
286 virtual BOOL decode(LLImageRaw* raw_image, F32 decode_time, S32 first_channel, S32 max_channel);
287
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;
297
298 S8 getCodec() const;
299 BOOL isDecoding() const { return mDecoding ? TRUE : FALSE; }
300 BOOL isDecoded() const { return mDecoded ? TRUE : FALSE; }
301 void setDiscardLevel(S8 discard_level) { mDiscardLevel = discard_level; }
302 S8 getDiscardLevel() const { return mDiscardLevel; }
303
304protected:
305 S8 mCodec;
306 S8 mDecoding;
307 S8 mDecoded;
308 S8 mDiscardLevel;
309
310 LLPointer<LLImageRaw> mDecodedImage;
311
312public:
313 static S32 sGlobalFormattedMemory;
314 static LLWorkerThread* sWorkerThread;
315};
316
317#endif
diff --git a/linden/indra/llimage/llimage.vcproj b/linden/indra/llimage/llimage.vcproj
new file mode 100644
index 0000000..cd4c735
--- /dev/null
+++ b/linden/indra/llimage/llimage.vcproj
@@ -0,0 +1,209 @@
1<?xml version="1.0" encoding="Windows-1252"?>
2<VisualStudioProject
3 ProjectType="Visual C++"
4 Version="7.10"
5 Name="llimage"
6 ProjectGUID="{681FDD6C-2FAE-4CB9-AF6D-B952F2B151C5}"
7 Keyword="Win32Proj">
8 <Platforms>
9 <Platform
10 Name="Win32"/>
11 </Platforms>
12 <Configurations>
13 <Configuration
14 Name="Debug|Win32"
15 OutputDirectory="../lib_$(ConfigurationName)/i686-win32"
16 IntermediateDirectory="$(ConfigurationName)"
17 ConfigurationType="4"
18 CharacterSet="1">
19 <Tool
20 Name="VCCLCompilerTool"
21 Optimization="0"
22 AdditionalIncludeDirectories="..\llcommon;..\llmath; ..\llvfs; ..\..\libraries\i686-win32\include;..\..\libraries\include\"
23 PreprocessorDefinitions="WIN32;_DEBUG;_LIB;LL_WINDOWS;LL_DEBUG"
24 MinimalRebuild="TRUE"
25 BasicRuntimeChecks="3"
26 RuntimeLibrary="1"
27 StructMemberAlignment="4"
28 ForceConformanceInForLoopScope="TRUE"
29 UsePrecompiledHeader="0"
30 WarningLevel="3"
31 WarnAsError="TRUE"
32 Detect64BitPortabilityProblems="FALSE"
33 DebugInformationFormat="4"/>
34 <Tool
35 Name="VCCustomBuildTool"/>
36 <Tool
37 Name="VCLibrarianTool"
38 OutputFile="$(OutDir)/llimage.lib"/>
39 <Tool
40 Name="VCMIDLTool"/>
41 <Tool
42 Name="VCPostBuildEventTool"/>
43 <Tool
44 Name="VCPreBuildEventTool"/>
45 <Tool
46 Name="VCPreLinkEventTool"/>
47 <Tool
48 Name="VCResourceCompilerTool"/>
49 <Tool
50 Name="VCWebServiceProxyGeneratorTool"/>
51 <Tool
52 Name="VCXMLDataGeneratorTool"/>
53 <Tool
54 Name="VCManagedWrapperGeneratorTool"/>
55 <Tool
56 Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
57 </Configuration>
58 <Configuration
59 Name="Release|Win32"
60 OutputDirectory="../lib_$(ConfigurationName)/i686-win32"
61 IntermediateDirectory="$(ConfigurationName)"
62 ConfigurationType="4"
63 CharacterSet="1">
64 <Tool
65 Name="VCCLCompilerTool"
66 GlobalOptimizations="TRUE"
67 InlineFunctionExpansion="2"
68 EnableIntrinsicFunctions="TRUE"
69 OptimizeForProcessor="3"
70 OptimizeForWindowsApplication="TRUE"
71 AdditionalIncludeDirectories="..\llcommon;..\llmath; ..\llvfs; ..\..\libraries\i686-win32\include;..\..\libraries\include\"
72 PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;LL_RELEASE"
73 RuntimeLibrary="0"
74 StructMemberAlignment="0"
75 ForceConformanceInForLoopScope="TRUE"
76 UsePrecompiledHeader="0"
77 WarningLevel="3"
78 WarnAsError="FALSE"
79 Detect64BitPortabilityProblems="FALSE"
80 DebugInformationFormat="3"/>
81 <Tool
82 Name="VCCustomBuildTool"/>
83 <Tool
84 Name="VCLibrarianTool"
85 OutputFile="$(OutDir)/llimage.lib"/>
86 <Tool
87 Name="VCMIDLTool"/>
88 <Tool
89 Name="VCPostBuildEventTool"/>
90 <Tool
91 Name="VCPreBuildEventTool"/>
92 <Tool
93 Name="VCPreLinkEventTool"/>
94 <Tool
95 Name="VCResourceCompilerTool"/>
96 <Tool
97 Name="VCWebServiceProxyGeneratorTool"/>
98 <Tool
99 Name="VCXMLDataGeneratorTool"/>
100 <Tool
101 Name="VCManagedWrapperGeneratorTool"/>
102 <Tool
103 Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
104 </Configuration>
105 <Configuration
106 Name="ReleaseNoOpt|Win32"
107 OutputDirectory="../lib_$(ConfigurationName)/i686-win32"
108 IntermediateDirectory="$(ConfigurationName)"
109 ConfigurationType="4"
110 CharacterSet="1">
111 <Tool
112 Name="VCCLCompilerTool"
113 Optimization="0"
114 AdditionalIncludeDirectories="..\llcommon;..\llmath; ..\llvfs; ..\..\libraries\i686-win32\include;..\..\libraries\include\"
115 PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;LL_RELEASE"
116 RuntimeLibrary="0"
117 StructMemberAlignment="0"
118 ForceConformanceInForLoopScope="TRUE"
119 UsePrecompiledHeader="0"
120 WarningLevel="3"
121 WarnAsError="TRUE"
122 Detect64BitPortabilityProblems="FALSE"
123 DebugInformationFormat="3"/>
124 <Tool
125 Name="VCCustomBuildTool"/>
126 <Tool
127 Name="VCLibrarianTool"
128 OutputFile="$(OutDir)/llimage.lib"/>
129 <Tool
130 Name="VCMIDLTool"/>
131 <Tool
132 Name="VCPostBuildEventTool"/>
133 <Tool
134 Name="VCPreBuildEventTool"/>
135 <Tool
136 Name="VCPreLinkEventTool"/>
137 <Tool
138 Name="VCResourceCompilerTool"/>
139 <Tool
140 Name="VCWebServiceProxyGeneratorTool"/>
141 <Tool
142 Name="VCXMLDataGeneratorTool"/>
143 <Tool
144 Name="VCManagedWrapperGeneratorTool"/>
145 <Tool
146 Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
147 </Configuration>
148 </Configurations>
149 <References>
150 </References>
151 <Files>
152 <Filter
153 Name="Source Files"
154 Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
155 UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
156 <File
157 RelativePath=".\llimage.cpp">
158 </File>
159 <File
160 RelativePath=".\llimagebmp.cpp">
161 </File>
162 <File
163 RelativePath=".\llimagedxt.cpp">
164 </File>
165 <File
166 RelativePath=".\llimagej2c.cpp">
167 </File>
168 <File
169 RelativePath=".\llimagejpeg.cpp">
170 </File>
171 <File
172 RelativePath=".\llimagetga.cpp">
173 </File>
174 </Filter>
175 <Filter
176 Name="Header Files"
177 Filter="h;hpp;hxx;hm;inl;inc;xsd"
178 UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
179 <File
180 RelativePath=".\llimage.h">
181 </File>
182 <File
183 RelativePath=".\llimagebmp.h">
184 </File>
185 <File
186 RelativePath=".\llimageconstants.h">
187 </File>
188 <File
189 RelativePath=".\llimagedxt.h">
190 </File>
191 <File
192 RelativePath=".\llimagej2c.h">
193 </File>
194 <File
195 RelativePath=".\llimagejpeg.h">
196 </File>
197 <File
198 RelativePath=".\llimagetga.h">
199 </File>
200 </Filter>
201 <Filter
202 Name="Resource Files"
203 Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
204 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
205 </Filter>
206 </Files>
207 <Globals>
208 </Globals>
209</VisualStudioProject>
diff --git a/linden/indra/llimage/llimagebmp.cpp b/linden/indra/llimage/llimagebmp.cpp
new file mode 100644
index 0000000..fc9532e
--- /dev/null
+++ b/linden/indra/llimage/llimagebmp.cpp
@@ -0,0 +1,643 @@
1/**
2 * @file llimagebmp.cpp
3 *
4 * Copyright (c) 2001-2007, Linden Research, Inc.
5 *
6 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement
9 * ("Other License"), formally executed by you and Linden Lab. Terms of
10 * the GPL can be found in doc/GPL-license.txt in this distribution, or
11 * online at http://secondlife.com/developers/opensource/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at http://secondlife.com/developers/opensource/flossexception
17 *
18 * By copying, modifying or distributing this software, you acknowledge
19 * that you have read and understood your obligations described above,
20 * and agree to abide by those obligations.
21 *
22 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
23 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
24 * COMPLETENESS OR PERFORMANCE.
25 */
26
27#include "linden_common.h"
28
29#include "llimagebmp.h"
30#include "llerror.h"
31
32#include "llendianswizzle.h"
33
34
35/**
36 * @struct LLBMPHeader
37 *
38 * This struct helps deal with bmp files.
39 */
40struct LLBMPHeader
41{
42 S32 mSize;
43 S32 mWidth;
44 S32 mHeight;
45 S16 mPlanes;
46 S16 mBitsPerPixel;
47 S16 mCompression;
48 S16 mAlignmentPadding; // pads out to next word boundary
49 S32 mImageSize;
50 S32 mHorzPelsPerMeter;
51 S32 mVertPelsPerMeter;
52 S32 mNumColors;
53 S32 mNumColorsImportant;
54};
55
56/**
57 * @struct Win95BmpHeaderExtension
58 */
59struct Win95BmpHeaderExtension
60{
61 U32 mReadMask;
62 U32 mGreenMask;
63 U32 mBlueMask;
64 U32 mAlphaMask;
65 U32 mColorSpaceType;
66 U16 mRed[3]; // Red CIE endpoint
67 U16 mGreen[3]; // Green CIE endpoint
68 U16 mBlue[3]; // Blue CIE endpoint
69 U32 mGamma[3]; // Gamma scale for r g and b
70};
71
72/**
73 * LLImageBMP
74 */
75LLImageBMP::LLImageBMP()
76 :
77 LLImageFormatted(IMG_CODEC_BMP),
78 mColorPaletteColors( 0 ),
79 mColorPalette( NULL ),
80 mBitmapOffset( 0 ),
81 mBitsPerPixel( 0 ),
82 mOriginAtTop( FALSE )
83{
84 mBitfieldMask[0] = 0;
85 mBitfieldMask[1] = 0;
86 mBitfieldMask[2] = 0;
87 mBitfieldMask[3] = 0;
88}
89
90LLImageBMP::~LLImageBMP()
91{
92 delete[] mColorPalette;
93}
94
95
96BOOL LLImageBMP::updateData()
97{
98 resetLastError();
99
100 // Check to make sure that this instance has been initialized with data
101 U8* mdata = getData();
102 if (!mdata || (0 == getDataSize()))
103 {
104 setLastError("Uninitialized instance of LLImageBMP");
105 return FALSE;
106 }
107
108 // Read the bitmap headers in order to get all the useful info
109 // about this image
110
111 ////////////////////////////////////////////////////////////////////
112 // Part 1: "File Header"
113 // 14 bytes consisting of
114 // 2 bytes: either BM or BA
115 // 4 bytes: file size in bytes
116 // 4 bytes: reserved (always 0)
117 // 4 bytes: bitmap offset (starting position of image data in bytes)
118 const S32 FILE_HEADER_SIZE = 14;
119 if ((mdata[0] != 'B') || (mdata[1] != 'M'))
120 {
121 if ((mdata[0] != 'B') || (mdata[1] != 'A'))
122 {
123 setLastError("OS/2 bitmap array BMP files are not supported");
124 return FALSE;
125 }
126 else
127 {
128 setLastError("Does not appear to be a bitmap file");
129 return FALSE;
130 }
131 }
132
133 mBitmapOffset = mdata[13];
134 mBitmapOffset <<= 8; mBitmapOffset += mdata[12];
135 mBitmapOffset <<= 8; mBitmapOffset += mdata[11];
136 mBitmapOffset <<= 8; mBitmapOffset += mdata[10];
137
138
139 ////////////////////////////////////////////////////////////////////
140 // Part 2: "Bitmap Header"
141 const S32 BITMAP_HEADER_SIZE = 40;
142 LLBMPHeader header;
143 llassert( sizeof( header ) == BITMAP_HEADER_SIZE );
144
145 memcpy((void *)&header, mdata + FILE_HEADER_SIZE, BITMAP_HEADER_SIZE);
146
147 // convert BMP header from little endian (no-op on little endian builds)
148 llendianswizzleone(header.mSize);
149 llendianswizzleone(header.mWidth);
150 llendianswizzleone(header.mHeight);
151 llendianswizzleone(header.mPlanes);
152 llendianswizzleone(header.mBitsPerPixel);
153 llendianswizzleone(header.mCompression);
154 llendianswizzleone(header.mAlignmentPadding);
155 llendianswizzleone(header.mImageSize);
156 llendianswizzleone(header.mHorzPelsPerMeter);
157 llendianswizzleone(header.mVertPelsPerMeter);
158 llendianswizzleone(header.mNumColors);
159 llendianswizzleone(header.mNumColorsImportant);
160
161 BOOL windows_nt_version = FALSE;
162 BOOL windows_95_version = FALSE;
163 if( 12 == header.mSize )
164 {
165 setLastError("Windows 2.x and OS/2 1.x BMP files are not supported");
166 return FALSE;
167 }
168 else
169 if( 40 == header.mSize )
170 {
171 if( 3 == header.mCompression )
172 {
173 // Windows NT
174 windows_nt_version = TRUE;
175 }
176 else
177 {
178 // Windows 3.x
179 }
180 }
181 else
182 if( 12 <= header.mSize && 64 <= header.mSize )
183 {
184 setLastError("OS/2 2.x BMP files are not supported");
185 return FALSE;
186 }
187 else
188 if( 108 == header.mSize )
189 {
190 // BITMAPV4HEADER
191 windows_95_version = TRUE;
192 }
193 else
194 if( 108 < header.mSize )
195 {
196 // BITMAPV5HEADER or greater
197 // Should work as long at Microsoft maintained backwards compatibility (which they did in V4 and V5)
198 windows_95_version = TRUE;
199 }
200
201 S32 width = header.mWidth;
202 S32 height = header.mHeight;
203 if (height < 0)
204 {
205 mOriginAtTop = TRUE;
206 height = -height;
207 }
208 else
209 {
210 mOriginAtTop = FALSE;
211 }
212
213 mBitsPerPixel = header.mBitsPerPixel;
214 S32 components;
215 switch( mBitsPerPixel )
216 {
217 case 8:
218 components = 1;
219 break;
220 case 24:
221 case 32:
222 components = 3;
223 break;
224 case 1:
225 case 4:
226 case 16: // Started work on 16, but doesn't work yet
227 // These are legal, but we don't support them yet.
228 setLastError("Unsupported bit depth");
229 return FALSE;
230 default:
231 setLastError("Unrecognized bit depth");
232 return FALSE;
233 }
234
235 setSize(width, height, components);
236
237 switch( header.mCompression )
238 {
239 case 0:
240 // Uncompressed
241 break;
242
243 case 1:
244 setLastError("8 bit RLE compression not supported.");
245 return FALSE;
246
247 case 2:
248 setLastError("4 bit RLE compression not supported.");
249 return FALSE;
250
251 case 3:
252 // Windows NT or Windows 95
253 break;
254
255 default:
256 setLastError("Unsupported compression format.");
257 return FALSE;
258 }
259
260 ////////////////////////////////////////////////////////////////////
261 // Part 3: Bitfield Masks and other color data
262 S32 extension_size = 0;
263 if( windows_nt_version )
264 {
265 if( (16 != header.mBitsPerPixel) && (32 != header.mBitsPerPixel) )
266 {
267 setLastError("Bitfield encoding requires 16 or 32 bits per pixel.");
268 return FALSE;
269 }
270
271 if( 0 != header.mNumColors )
272 {
273 setLastError("Bitfield encoding is not compatible with a color table.");
274 return FALSE;
275 }
276
277
278 extension_size = 4 * 3;
279 memcpy( mBitfieldMask, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE, extension_size);
280 }
281 else
282 if( windows_95_version )
283 {
284 Win95BmpHeaderExtension win_95_extension;
285 extension_size = sizeof( win_95_extension );
286
287 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 ) );
289
290 if( 3 == header.mCompression )
291 {
292 memcpy( mBitfieldMask, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE, 4 * 4);
293 }
294
295 // Color correction ignored for now
296 }
297
298
299 ////////////////////////////////////////////////////////////////////
300 // Part 4: Color Palette (optional)
301 // Note: There's no color palette if there are 16 or more bits per pixel
302 S32 color_palette_size = 0;
303 mColorPaletteColors = 0;
304 if( header.mBitsPerPixel < 16 )
305 {
306 if( 0 == header.mNumColors )
307 {
308 mColorPaletteColors = (1 << header.mBitsPerPixel);
309 }
310 else
311 {
312 mColorPaletteColors = header.mNumColors;
313 }
314 }
315 color_palette_size = mColorPaletteColors * 4;
316
317 if( 0 != mColorPaletteColors )
318 {
319 mColorPalette = new U8[color_palette_size];
320 memcpy( mColorPalette, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE + extension_size, color_palette_size );
321 }
322
323 return TRUE;
324}
325
326BOOL LLImageBMP::decode(LLImageRaw* raw_image, F32 decode_time)
327{
328 llassert_always(raw_image);
329
330 resetLastError();
331
332 // Check to make sure that this instance has been initialized with data
333 U8* mdata = getData();
334 if (!mdata || (0 == getDataSize()))
335 {
336 setLastError("llimagebmp trying to decode an image with no data!");
337 return FALSE;
338 }
339
340 raw_image->resize(getWidth(), getHeight(), 3);
341
342 U8* src = mdata + mBitmapOffset;
343 U8* dst = raw_image->getData();
344
345 BOOL success = FALSE;
346
347 switch( mBitsPerPixel )
348 {
349 case 8:
350 if( mColorPaletteColors >= 256 )
351 {
352 success = decodeColorTable8( dst, src );
353 }
354 break;
355
356 case 16:
357 success = decodeColorMask16( dst, src );
358 break;
359
360 case 24:
361 success = decodeTruecolor24( dst, src );
362 break;
363
364 case 32:
365 success = decodeColorMask32( dst, src );
366 break;
367 }
368
369 if( success && mOriginAtTop )
370 {
371 raw_image->verticalFlip();
372 }
373
374 return success;
375}
376
377U32 LLImageBMP::countTrailingZeros( U32 m )
378{
379 U32 shift_count = 0;
380 while( !(m & 1) )
381 {
382 shift_count++;
383 m >>= 1;
384 }
385 return shift_count;
386}
387
388
389BOOL LLImageBMP::decodeColorMask16( U8* dst, U8* src )
390{
391 llassert( 16 == mBitsPerPixel );
392
393 if( !mBitfieldMask[0] && !mBitfieldMask[1] && !mBitfieldMask[2] )
394 {
395 // Use default values
396 mBitfieldMask[0] = 0x00007C00;
397 mBitfieldMask[1] = 0x000003E0;
398 mBitfieldMask[2] = 0x0000001F;
399 }
400
401 S32 src_row_span = getWidth() * 2;
402 S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4
403
404 U32 r_shift = countTrailingZeros( mBitfieldMask[2] );
405 U32 g_shift = countTrailingZeros( mBitfieldMask[1] );
406 U32 b_shift = countTrailingZeros( mBitfieldMask[0] );
407
408 for( S32 row = 0; row < getHeight(); row++ )
409 {
410 for( S32 col = 0; col < getWidth(); col++ )
411 {
412 U32 value = *((U16*)src);
413 dst[0] = U8((value & mBitfieldMask[2]) >> r_shift); // Red
414 dst[1] = U8((value & mBitfieldMask[1]) >> g_shift); // Green
415 dst[2] = U8((value & mBitfieldMask[0]) >> b_shift); // Blue
416 src += 2;
417 dst += 3;
418 }
419 src += alignment_bytes;
420 }
421
422 return TRUE;
423}
424
425BOOL LLImageBMP::decodeColorMask32( U8* dst, U8* src )
426{
427 // Note: alpha is not supported
428
429 llassert( 32 == mBitsPerPixel );
430
431 if( !mBitfieldMask[0] && !mBitfieldMask[1] && !mBitfieldMask[2] )
432 {
433 // Use default values
434 mBitfieldMask[0] = 0x00FF0000;
435 mBitfieldMask[1] = 0x0000FF00;
436 mBitfieldMask[2] = 0x000000FF;
437 }
438
439
440 S32 src_row_span = getWidth() * 4;
441 S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4
442
443 U32 r_shift = countTrailingZeros( mBitfieldMask[0] );
444 U32 g_shift = countTrailingZeros( mBitfieldMask[1] );
445 U32 b_shift = countTrailingZeros( mBitfieldMask[2] );
446
447 for( S32 row = 0; row < getHeight(); row++ )
448 {
449 for( S32 col = 0; col < getWidth(); col++ )
450 {
451 U32 value = *((U32*)src);
452 dst[0] = U8((value & mBitfieldMask[0]) >> r_shift); // Red
453 dst[1] = U8((value & mBitfieldMask[1]) >> g_shift); // Green
454 dst[2] = U8((value & mBitfieldMask[2]) >> b_shift); // Blue
455 src += 4;
456 dst += 3;
457 }
458 src += alignment_bytes;
459 }
460
461 return TRUE;
462}
463
464
465BOOL LLImageBMP::decodeColorTable8( U8* dst, U8* src )
466{
467 llassert( (8 == mBitsPerPixel) && (mColorPaletteColors >= 256) );
468
469 S32 src_row_span = getWidth() * 1;
470 S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4
471
472 for( S32 row = 0; row < getHeight(); row++ )
473 {
474 for( S32 col = 0; col < getWidth(); col++ )
475 {
476 S32 index = 4 * src[0];
477 dst[0] = mColorPalette[index + 2]; // Red
478 dst[1] = mColorPalette[index + 1]; // Green
479 dst[2] = mColorPalette[index + 0]; // Blue
480 src++;
481 dst += 3;
482 }
483 src += alignment_bytes;
484 }
485
486 return TRUE;
487}
488
489
490BOOL LLImageBMP::decodeTruecolor24( U8* dst, U8* src )
491{
492 llassert( 24 == mBitsPerPixel );
493 llassert( 3 == getComponents() );
494 S32 src_row_span = getWidth() * 3;
495 S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4
496
497 for( S32 row = 0; row < getHeight(); row++ )
498 {
499 for( S32 col = 0; col < getWidth(); col++ )
500 {
501 dst[0] = src[2]; // Red
502 dst[1] = src[1]; // Green
503 dst[2] = src[0]; // Blue
504 src += 3;
505 dst += 3;
506 }
507 src += alignment_bytes;
508 }
509
510 return TRUE;
511}
512
513BOOL LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
514{
515 llassert_always(raw_image);
516
517 resetLastError();
518
519 S32 src_components = raw_image->getComponents();
520 S32 dst_components = ( src_components < 3 ) ? 1 : 3;
521
522 if( (2 == src_components) || (4 == src_components) )
523 {
524 llinfos << "Dropping alpha information during BMP encoding" << llendl;
525 }
526
527 setSize(raw_image->getWidth(), raw_image->getHeight(), dst_components);
528
529 U8 magic[14];
530 LLBMPHeader header;
531 int header_bytes = 14+sizeof(header);
532 llassert(header_bytes == 54);
533 if (getComponents() == 1)
534 {
535 header_bytes += 1024; // Need colour LUT.
536 }
537 int line_bytes = getComponents() * getWidth();
538 int alignment_bytes = (3 * line_bytes) % 4;
539 line_bytes += alignment_bytes;
540 int file_bytes = line_bytes*getHeight() + header_bytes;
541
542 // Allocate the new buffer for the data.
543 allocateData(file_bytes);
544
545 magic[0] = 'B'; magic[1] = 'M';
546 magic[2] = (U8) file_bytes;
547 magic[3] = (U8)(file_bytes>>8);
548 magic[4] = (U8)(file_bytes>>16);
549 magic[5] = (U8)(file_bytes>>24);
550 magic[6] = magic[7] = magic[8] = magic[9] = 0;
551 magic[10] = (U8) header_bytes;
552 magic[11] = (U8)(header_bytes>>8);
553 magic[12] = (U8)(header_bytes>>16);
554 magic[13] = (U8)(header_bytes>>24);
555 header.mSize = 40;
556 header.mWidth = getWidth();
557 header.mHeight = getHeight();
558 header.mPlanes = 1;
559 header.mBitsPerPixel = (getComponents()==1)?8:24;
560 header.mCompression = 0;
561 header.mAlignmentPadding = 0;
562 header.mImageSize = 0;
563#if LL_DARWIN
564 header.mHorzPelsPerMeter = header.mVertPelsPerMeter = 2834; // 72dpi
565#else
566 header.mHorzPelsPerMeter = header.mVertPelsPerMeter = 0;
567#endif
568 header.mNumColors = header.mNumColorsImportant = 0;
569
570 // convert BMP header to little endian (no-op on little endian builds)
571 llendianswizzleone(header.mSize);
572 llendianswizzleone(header.mWidth);
573 llendianswizzleone(header.mHeight);
574 llendianswizzleone(header.mPlanes);
575 llendianswizzleone(header.mBitsPerPixel);
576 llendianswizzleone(header.mCompression);
577 llendianswizzleone(header.mAlignmentPadding);
578 llendianswizzleone(header.mImageSize);
579 llendianswizzleone(header.mHorzPelsPerMeter);
580 llendianswizzleone(header.mVertPelsPerMeter);
581 llendianswizzleone(header.mNumColors);
582 llendianswizzleone(header.mNumColorsImportant);
583
584 U8* mdata = getData();
585
586 // Output magic, then header, then the palette table, then the data.
587 U32 cur_pos = 0;
588 memcpy(mdata, magic, 14);
589 cur_pos += 14;
590 memcpy(mdata+cur_pos, &header, 40);
591 cur_pos += 40;
592 if (getComponents() == 1)
593 {
594 S32 n;
595 for (n=0; n < 256; n++)
596 {
597 mdata[cur_pos++] = (U8)n;
598 mdata[cur_pos++] = (U8)n;
599 mdata[cur_pos++] = (U8)n;
600 mdata[cur_pos++] = 0;
601 }
602 }
603
604 // Need to iterate through, because we need to flip the RGB.
605 const U8* src = raw_image->getData();
606 U8* dst = mdata + cur_pos;
607
608 for( S32 row = 0; row < getHeight(); row++ )
609 {
610 for( S32 col = 0; col < getWidth(); col++ )
611 {
612 switch( src_components )
613 {
614 case 1:
615 *dst++ = *src++;
616 break;
617 case 2:
618 {
619 U32 lum = src[0];
620 U32 alpha = src[1];
621 *dst++ = (U8)(lum * alpha / 255);
622 src += 2;
623 break;
624 }
625 case 3:
626 case 4:
627 dst[0] = src[2];
628 dst[1] = src[1];
629 dst[2] = src[0];
630 src += src_components;
631 dst += 3;
632 break;
633 }
634
635 for( S32 i = 0; i < alignment_bytes; i++ )
636 {
637 *dst++ = 0;
638 }
639 }
640 }
641
642 return TRUE;
643}
diff --git a/linden/indra/llimage/llimagebmp.h b/linden/indra/llimage/llimagebmp.h
new file mode 100644
index 0000000..43724f2
--- /dev/null
+++ b/linden/indra/llimage/llimagebmp.h
@@ -0,0 +1,64 @@
1/**
2 * @file llimagebmp.h
3 * @brief Image implementation for BMP.
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#ifndef LL_LLIMAGEBMP_H
29#define LL_LLIMAGEBMP_H
30
31#include "llimage.h"
32
33// This class compresses and decompressed BMP files
34
35class LLImageBMP : public LLImageFormatted
36{
37protected:
38 virtual ~LLImageBMP();
39
40public:
41 LLImageBMP();
42
43 /*virtual*/ BOOL updateData();
44 /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 time=0.0);
45 /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 time=0.0);
46
47protected:
48 BOOL decodeColorTable8( U8* dst, U8* src );
49 BOOL decodeColorMask16( U8* dst, U8* src );
50 BOOL decodeTruecolor24( U8* dst, U8* src );
51 BOOL decodeColorMask32( U8* dst, U8* src );
52
53 U32 countTrailingZeros( U32 m );
54
55protected:
56 S32 mColorPaletteColors;
57 U8* mColorPalette;
58 S32 mBitmapOffset;
59 S32 mBitsPerPixel;
60 U32 mBitfieldMask[4]; // rgba
61 BOOL mOriginAtTop;
62};
63
64#endif
diff --git a/linden/indra/llimage/llimagedxt.cpp b/linden/indra/llimage/llimagedxt.cpp
new file mode 100644
index 0000000..8b16f97
--- /dev/null
+++ b/linden/indra/llimage/llimagedxt.cpp
@@ -0,0 +1,494 @@
1/**
2 * @file llimagedxt.cpp
3 *
4 * Copyright (c) 2001-2007, Linden Research, Inc.
5 *
6 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement
9 * ("Other License"), formally executed by you and Linden Lab. Terms of
10 * the GPL can be found in doc/GPL-license.txt in this distribution, or
11 * online at http://secondlife.com/developers/opensource/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at http://secondlife.com/developers/opensource/flossexception
17 *
18 * By copying, modifying or distributing this software, you acknowledge
19 * that you have read and understood your obligations described above,
20 * and agree to abide by those obligations.
21 *
22 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
23 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
24 * COMPLETENESS OR PERFORMANCE.
25 */
26
27#include "linden_common.h"
28
29#include "llimagedxt.h"
30
31//static
32void LLImageDXT::checkMinWidthHeight(EFileFormat format, S32& width, S32& height)
33{
34 S32 mindim = (format >= FORMAT_DXT1 && format <= FORMAT_DXR5) ? 4 : 1;
35 width = llmax(width, mindim);
36 height = llmax(height, mindim);
37}
38
39//static
40S32 LLImageDXT::formatBits(EFileFormat format)
41{
42 switch (format)
43 {
44 case FORMAT_DXT1: return 4;
45 case FORMAT_DXR1: return 4;
46 case FORMAT_I8: return 8;
47 case FORMAT_A8: return 8;
48 case FORMAT_DXT3: return 8;
49 case FORMAT_DXR3: return 8;
50 case FORMAT_DXR5: return 8;
51 case FORMAT_DXT5: return 8;
52 case FORMAT_RGB8: return 24;
53 case FORMAT_RGBA8: return 32;
54 default:
55 llerrs << "LLImageDXT::Unknown format: " << format << llendl;
56 return 0;
57 }
58};
59
60//static
61S32 LLImageDXT::formatBytes(EFileFormat format, S32 width, S32 height)
62{
63 checkMinWidthHeight(format, width, height);
64 S32 bytes = ((width*height*formatBits(format)+7)>>3);
65 S32 aligned = (bytes+3)&~3;
66 return aligned;
67}
68
69//static
70S32 LLImageDXT::formatComponents(EFileFormat format)
71{
72 switch (format)
73 {
74 case FORMAT_DXT1: return 3;
75 case FORMAT_DXR1: return 3;
76 case FORMAT_I8: return 1;
77 case FORMAT_A8: return 1;
78 case FORMAT_DXT3: return 4;
79 case FORMAT_DXR3: return 4;
80 case FORMAT_DXT5: return 4;
81 case FORMAT_DXR5: return 4;
82 case FORMAT_RGB8: return 3;
83 case FORMAT_RGBA8: return 4;
84 default:
85 llerrs << "LLImageDXT::Unknown format: " << format << llendl;
86 return 0;
87 }
88};
89
90// static
91LLImageDXT::EFileFormat LLImageDXT::getFormat(S32 fourcc)
92{
93 switch(fourcc)
94 {
95 case 0x20203849: return FORMAT_I8;
96 case 0x20203841: return FORMAT_A8;
97 case 0x20424752: return FORMAT_RGB8;
98 case 0x41424752: return FORMAT_RGBA8;
99 case 0x31525844: return FORMAT_DXR1;
100 case 0x32525844: return FORMAT_DXR2;
101 case 0x33525844: return FORMAT_DXR3;
102 case 0x34525844: return FORMAT_DXR4;
103 case 0x35525844: return FORMAT_DXR5;
104 case 0x31545844: return FORMAT_DXT1;
105 case 0x32545844: return FORMAT_DXT2;
106 case 0x33545844: return FORMAT_DXT3;
107 case 0x34545844: return FORMAT_DXT4;
108 case 0x35545844: return FORMAT_DXT5;
109 default: return FORMAT_UNKNOWN;
110 }
111}
112
113//static
114S32 LLImageDXT::getFourCC(EFileFormat format)
115{
116 switch(format)
117 {
118 case FORMAT_I8: return 0x20203849;
119 case FORMAT_A8: return 0x20203841;
120 case FORMAT_RGB8: return 0x20424752;
121 case FORMAT_RGBA8: return 0x41424752;
122 case FORMAT_DXR1: return 0x31525844;
123 case FORMAT_DXR2: return 0x32525844;
124 case FORMAT_DXR3: return 0x33525844;
125 case FORMAT_DXR4: return 0x34525844;
126 case FORMAT_DXR5: return 0x35525844;
127 case FORMAT_DXT1: return 0x31545844;
128 case FORMAT_DXT2: return 0x32545844;
129 case FORMAT_DXT3: return 0x33545844;
130 case FORMAT_DXT4: return 0x34545844;
131 case FORMAT_DXT5: return 0x35545844;
132 default: return 0x00000000;
133 }
134}
135
136//static
137void LLImageDXT::calcDiscardWidthHeight(S32 discard_level, EFileFormat format, S32& width, S32& height)
138{
139 while (discard_level > 0 && width > 1 && height > 1)
140 {
141 discard_level--;
142 width >>= 1;
143 height >>= 1;
144 }
145 checkMinWidthHeight(format, width, height);
146}
147
148//static
149S32 LLImageDXT::calcNumMips(S32 width, S32 height)
150{
151 S32 nmips = 0;
152 while (width > 0 && height > 0)
153 {
154 width >>= 1;
155 height >>= 1;
156 nmips++;
157 }
158 return nmips;
159}
160
161//============================================================================
162
163LLImageDXT::LLImageDXT()
164 : LLImageFormatted(IMG_CODEC_DXT),
165 mFileFormat(FORMAT_UNKNOWN),
166 mHeaderSize(0)
167{
168}
169
170LLImageDXT::~LLImageDXT()
171{
172}
173
174// virtual
175BOOL LLImageDXT::updateData()
176{
177 resetLastError();
178
179 U8* data = getData();
180 S32 data_size = getDataSize();
181
182 if (!data || !data_size)
183 {
184 setLastError("LLImageDXT uninitialized");
185 return FALSE;
186 }
187
188 S32 width, height, miplevelmax;
189 dxtfile_header_t* header = (dxtfile_header_t*)data;
190 if (header->fourcc != 0x20534444)
191 {
192 dxtfile_header_old_t* oldheader = (dxtfile_header_old_t*)header;
193 mHeaderSize = sizeof(dxtfile_header_old_t);
194 mFileFormat = EFileFormat(oldheader->format);
195 miplevelmax = llmin(oldheader->maxlevel,MAX_IMAGE_MIP);
196 width = oldheader->maxwidth;
197 height = oldheader->maxheight;
198 }
199 else
200 {
201 mHeaderSize = sizeof(dxtfile_header_t);
202 mFileFormat = getFormat(header->pixel_fmt.fourcc);
203 miplevelmax = llmin(header->num_mips-1,MAX_IMAGE_MIP);
204 width = header->maxwidth;
205 height = header->maxheight;
206 }
207
208 if (data_size < mHeaderSize)
209 {
210 llerrs << "LLImageDXT: not enough data" << llendl;
211 }
212 S32 ncomponents = formatComponents(mFileFormat);
213 setSize(width, height, ncomponents);
214
215 S32 discard = calcDiscardLevelBytes(data_size);
216 discard = llmin(discard, miplevelmax);
217 setDiscardLevel(discard);
218
219 return TRUE;
220}
221
222// discard: 0 = largest (last) mip
223S32 LLImageDXT::getMipOffset(S32 discard)
224{
225 if (mFileFormat >= FORMAT_DXT1 && mFileFormat <= FORMAT_DXT5)
226 {
227 llerrs << "getMipOffset called with old (unsupported) format" << llendl;
228 }
229 S32 width = getWidth(), height = getHeight();
230 S32 num_mips = calcNumMips(width, height);
231 discard = llclamp(discard, 0, num_mips-1);
232 S32 last_mip = num_mips-1-discard;
233 llassert(mHeaderSize > 0);
234 S32 offset = mHeaderSize;
235 for (S32 mipidx = num_mips-1; mipidx >= 0; mipidx--)
236 {
237 if (mipidx < last_mip)
238 {
239 offset += formatBytes(mFileFormat, width, height);
240 }
241 width >>= 1;
242 height >>= 1;
243 }
244 return offset;
245}
246
247void LLImageDXT::setFormat()
248{
249 S32 ncomponents = getComponents();
250 switch (ncomponents)
251 {
252 case 3: mFileFormat = FORMAT_DXR1; break;
253 case 4: mFileFormat = FORMAT_DXR3; break;
254 default: llerrs << "LLImageDXT::setFormat called with ncomponents = " << ncomponents << llendl;
255 }
256 mHeaderSize = calcHeaderSize();
257}
258
259// virtual
260BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
261{
262 llassert_always(raw_image);
263
264 if (mFileFormat >= FORMAT_DXT1 && mFileFormat <= FORMAT_DXR5)
265 {
266 llwarns << "Attempt to decode compressed LLImageDXT to Raw (unsupported)" << llendl;
267 return FALSE;
268 }
269
270 S32 width = getWidth(), height = getHeight();
271 S32 ncomponents = getComponents();
272 S32 image_size = formatBytes(mFileFormat, width, height);
273 U8* data = getData() + getMipOffset(0);
274
275 if ((!getData()) || (data + image_size > getData() + getDataSize()))
276 {
277 setLastError("LLImageDXT trying to decode an image with not enough data!");
278 return FALSE;
279 }
280
281 raw_image->resize(width, height, ncomponents);
282 memcpy(raw_image->getData(), data, image_size);
283
284 return TRUE;
285}
286
287// virtual
288BOOL LLImageDXT::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard, F32 decode_time)
289{
290 if (discard < 0)
291 {
292 discard = mDiscardLevel;
293 }
294 else if (discard < mDiscardLevel)
295 {
296 llerrs << "Request for invalid discard level" << llendl;
297 }
298 U8* data = getData() + getMipOffset(discard);
299 S32 width, height;
300 calcDiscardWidthHeight(discard, mFileFormat, width, height);
301 raw = new LLImageRaw(data, width, height, getComponents());
302 return TRUE;
303}
304
305void LLImageDXT::releaseDecodedData()
306{
307 // nothing to do
308}
309
310BOOL LLImageDXT::encode(const LLImageRaw* raw_image, F32 time, bool explicit_mips)
311{
312 llassert_always(raw_image);
313
314 S32 ncomponents = raw_image->getComponents();
315 EFileFormat format;
316 switch (ncomponents)
317 {
318 case 1:
319 format = FORMAT_A8;
320 break;
321 case 3:
322 format = FORMAT_RGB8;
323 break;
324 case 4:
325 format = FORMAT_RGBA8;
326 break;
327 default:
328 llerrs << "LLImageDXT::encode: Unhandled channel number: " << ncomponents << llendl;
329 return 0;
330 }
331
332 S32 width = raw_image->getWidth();
333 S32 height = raw_image->getHeight();
334
335 if (explicit_mips)
336 {
337 height = (height/3)*2;
338 }
339
340 setSize(width, height, ncomponents);
341 mHeaderSize = sizeof(dxtfile_header_t);
342 mFileFormat = format;
343
344 S32 nmips = calcNumMips(width, height);
345 S32 w = width;
346 S32 h = height;
347
348 S32 totbytes = mHeaderSize;
349 for (S32 mip=0; mip<nmips; mip++)
350 {
351 totbytes += formatBytes(format,w,h);
352 w >>= 1;
353 h >>= 1;
354 }
355
356 allocateData(totbytes);
357
358 U8* data = getData();
359 dxtfile_header_t* header = (dxtfile_header_t*)data;
360 llassert(mHeaderSize > 0);
361 memset(header, 0, mHeaderSize);
362 header->fourcc = 0x20534444;
363 header->pixel_fmt.fourcc = getFourCC(format);
364 header->num_mips = nmips;
365 header->maxwidth = width;
366 header->maxheight = height;
367
368 U8* prev_mipdata = 0;
369 w = width, h = height;
370 for (S32 mip=0; mip<nmips; mip++)
371 {
372 U8* mipdata = data + getMipOffset(mip);
373 S32 bytes = formatBytes(format, w, h);
374 if (mip==0)
375 {
376 memcpy(mipdata, raw_image->getData(), bytes);
377 }
378 else if (explicit_mips)
379 {
380 extractMip(raw_image->getData(), mipdata, width, height, w, h, format);
381 }
382 else
383 {
384 generateMip(prev_mipdata, mipdata, w, h, ncomponents);
385 }
386 w >>= 1;
387 h >>= 1;
388 checkMinWidthHeight(format, w, h);
389 prev_mipdata = mipdata;
390 }
391
392 return TRUE;
393}
394
395// virtual
396BOOL LLImageDXT::encode(const LLImageRaw* raw_image, F32 time)
397{
398 return encode(raw_image, time, false);
399}
400
401// virtual
402bool LLImageDXT::convertToDXR()
403{
404 EFileFormat newformat = FORMAT_UNKNOWN;
405 switch (mFileFormat)
406 {
407 case FORMAT_DXR1:
408 case FORMAT_DXR2:
409 case FORMAT_DXR3:
410 case FORMAT_DXR4:
411 case FORMAT_DXR5:
412 return false; // nothing to do
413 case FORMAT_DXT1: newformat = FORMAT_DXR1; break;
414 case FORMAT_DXT2: newformat = FORMAT_DXR2; break;
415 case FORMAT_DXT3: newformat = FORMAT_DXR3; break;
416 case FORMAT_DXT4: newformat = FORMAT_DXR4; break;
417 case FORMAT_DXT5: newformat = FORMAT_DXR5; break;
418 default:
419 llwarns << "convertToDXR: can not convert format: " << llformat("0x%08x",getFourCC(mFileFormat)) << llendl;
420 return false;
421 }
422 mFileFormat = newformat;
423 S32 width = getWidth(), height = getHeight();
424 S32 nmips = calcNumMips(width,height);
425 S32 total_bytes = getDataSize();
426 U8* olddata = getData();
427 U8* newdata = new U8[total_bytes];
428 llassert(total_bytes > 0);
429 memset(newdata, 0, total_bytes);
430 memcpy(newdata, olddata, mHeaderSize);
431 for (S32 mip=0; mip<nmips; mip++)
432 {
433 S32 bytes = formatBytes(mFileFormat, width, height);
434 S32 newoffset = getMipOffset(mip);
435 S32 oldoffset = mHeaderSize + (total_bytes - newoffset - bytes);
436 memcpy(newdata + newoffset, olddata + oldoffset, bytes);
437 width >>= 1;
438 height >>= 1;
439 }
440 dxtfile_header_t* header = (dxtfile_header_t*)newdata;
441 header->pixel_fmt.fourcc = getFourCC(newformat);
442 setData(newdata, total_bytes);
443 return true;
444}
445
446// virtual
447S32 LLImageDXT::calcHeaderSize()
448{
449 return llmax(sizeof(dxtfile_header_old_t), sizeof(dxtfile_header_t));
450}
451
452// virtual
453S32 LLImageDXT::calcDataSize(S32 discard_level)
454{
455 if (mFileFormat == FORMAT_UNKNOWN)
456 {
457 llerrs << "calcDataSize called with unloaded LLImageDXT" << llendl;
458 return 0;
459 }
460 if (discard_level < 0)
461 {
462 discard_level = mDiscardLevel;
463 }
464 S32 bytes = getMipOffset(discard_level); // size of header + previous mips
465 S32 w = getWidth() >> discard_level;
466 S32 h = getHeight() >> discard_level;
467 bytes += formatBytes(mFileFormat,w,h);
468 return bytes;
469}
470
471//============================================================================
472
473//static
474void LLImageDXT::extractMip(const U8 *indata, U8* mipdata, int width, int height,
475 int mip_width, int mip_height, EFileFormat format)
476{
477 int initial_offset = formatBytes(format, width, height);
478 int line_width = formatBytes(format, width, 1);
479 int mip_line_width = formatBytes(format, mip_width, 1);
480 int line_offset = 0;
481
482 for (int ww=width>>1; ww>mip_width; ww>>=1)
483 {
484 line_offset += formatBytes(format, ww, 1);
485 }
486
487 for (int h=0;h<mip_height;++h)
488 {
489 int start_offset = initial_offset + line_width * h + line_offset;
490 memcpy(mipdata + mip_line_width*h, indata + start_offset, mip_line_width);
491 }
492}
493
494//============================================================================
diff --git a/linden/indra/llimage/llimagedxt.h b/linden/indra/llimage/llimagedxt.h
new file mode 100644
index 0000000..c3c01c1
--- /dev/null
+++ b/linden/indra/llimage/llimagedxt.h
@@ -0,0 +1,139 @@
1/**
2 * @file llimagedxt.h
3 *
4 * Copyright (c) 2001-2007, Linden Research, Inc.
5 *
6 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement
9 * ("Other License"), formally executed by you and Linden Lab. Terms of
10 * the GPL can be found in doc/GPL-license.txt in this distribution, or
11 * online at http://secondlife.com/developers/opensource/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at http://secondlife.com/developers/opensource/flossexception
17 *
18 * By copying, modifying or distributing this software, you acknowledge
19 * that you have read and understood your obligations described above,
20 * and agree to abide by those obligations.
21 *
22 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
23 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
24 * COMPLETENESS OR PERFORMANCE.
25 */
26
27#ifndef LL_LLIMAGEDXT_H
28#define LL_LLIMAGEDXT_H
29
30#include "llimage.h"
31
32// This class decodes and encodes LL DXT files (which may unclude uncompressed RGB or RGBA mipped data)
33
34class LLImageDXT : public LLImageFormatted
35{
36public:
37 enum EFileFormat
38 {
39 FORMAT_UNKNOWN = 0,
40 FORMAT_I8 = 1,
41 FORMAT_A8,
42 FORMAT_RGB8,
43 FORMAT_RGBA8,
44 FORMAT_DXT1,
45 FORMAT_DXT2,
46 FORMAT_DXT3,
47 FORMAT_DXT4,
48 FORMAT_DXT5,
49 FORMAT_DXR1,
50 FORMAT_DXR2,
51 FORMAT_DXR3,
52 FORMAT_DXR4,
53 FORMAT_DXR5,
54 FORMAT_NOFILE = 0xff,
55 };
56
57 struct dxtfile_header_old_t
58 {
59 S32 format;
60 S32 maxlevel;
61 S32 maxwidth;
62 S32 maxheight;
63 };
64
65 struct dxtfile_header_t
66 {
67 S32 fourcc;
68 // begin DDSURFACEDESC2 struct
69 S32 header_size; // size of the header
70 S32 flags; // flags - unused
71 S32 maxheight;
72 S32 maxwidth;
73 S32 image_size; // size of the compressed image
74 S32 depth;
75 S32 num_mips;
76 S32 reserved[11];
77 struct pixel_format
78 {
79 S32 struct_size; // size of this structure
80 S32 flags;
81 S32 fourcc;
82 S32 bit_count;
83 S32 r_mask;
84 S32 g_mask;
85 S32 b_mask;
86 S32 a_mask;
87 } pixel_fmt;
88 S32 caps[4];
89 S32 reserved2;
90 };
91
92protected:
93 /*virtual*/ ~LLImageDXT();
94
95public:
96 LLImageDXT();
97
98 /*virtual*/ BOOL updateData();
99
100 /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 time=0.0);
101 BOOL encode(const LLImageRaw* raw_image, F32 time, bool explicit_mips);
102 /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 time=0.0);
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();
108 /*virtual*/ S32 calcDataSize(S32 discard_level = 0);
109
110 void setFormat();
111 S32 getMipOffset(S32 discard);
112
113 EFileFormat getFileFormat() { return mFileFormat; }
114 bool isCompressed() { return (mFileFormat >= FORMAT_DXT1 && mFileFormat <= FORMAT_DXR5); }
115
116 bool convertToDXR(); // convert from DXT to DXR
117
118 static void checkMinWidthHeight(EFileFormat format, S32& width, S32& height);
119 static S32 formatBits(EFileFormat format);
120 static S32 formatBytes(EFileFormat format, S32 width, S32 height);
121 static S32 formatOffset(EFileFormat format, S32 width, S32 height, S32 max_width, S32 max_height);
122 static S32 formatComponents(EFileFormat format);
123
124 static EFileFormat getFormat(S32 fourcc);
125 static S32 getFourCC(EFileFormat format);
126
127 static void calcDiscardWidthHeight(S32 discard_level, EFileFormat format, S32& width, S32& height);
128 static S32 calcNumMips(S32 width, S32 height);
129
130private:
131 static void extractMip(const U8 *indata, U8* mipdata, int width, int height,
132 int mip_width, int mip_height, EFileFormat format);
133
134private:
135 EFileFormat mFileFormat;
136 S32 mHeaderSize;
137};
138
139#endif
diff --git a/linden/indra/llimage/llimagej2c.cpp b/linden/indra/llimage/llimagej2c.cpp
new file mode 100644
index 0000000..87852e7
--- /dev/null
+++ b/linden/indra/llimage/llimagej2c.cpp
@@ -0,0 +1,402 @@
1/**
2 * @file llimagej2c.cpp
3 *
4 * Copyright (c) 2001-2007, Linden Research, Inc.
5 *
6 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement
9 * ("Other License"), formally executed by you and Linden Lab. Terms of
10 * the GPL can be found in doc/GPL-license.txt in this distribution, or
11 * online at http://secondlife.com/developers/opensource/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at http://secondlife.com/developers/opensource/flossexception
17 *
18 * By copying, modifying or distributing this software, you acknowledge
19 * that you have read and understood your obligations described above,
20 * and agree to abide by those obligations.
21 *
22 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
23 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
24 * COMPLETENESS OR PERFORMANCE.
25 */
26#include "linden_common.h"
27
28#include <apr-1/apr_pools.h>
29#include <apr-1/apr_dso.h>
30
31#include "lldir.h"
32#include "llimagej2c.h"
33#include "llmemory.h"
34
35typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
36typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
37
38//some "private static" variables so we only attempt to load
39//dynamic libaries once
40CreateLLImageJ2CFunction j2cimpl_create_func;
41DestroyLLImageJ2CFunction j2cimpl_destroy_func;
42apr_pool_t *j2cimpl_dso_memory_pool;
43apr_dso_handle_t *j2cimpl_dso_handle;
44
45//Declare the prototype for theses functions here, their functionality
46//will be implemented in other files which define a derived LLImageJ2CImpl
47//but only ONE static library which has the implementation for this
48//function should ever be included
49LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl();
50void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl);
51
52//static
53//Loads the required "create" and "destroy" functions needed
54void LLImageJ2C::openDSO()
55{
56 //attempt to load a DSO and get some functions from it
57 std::string dso_name;
58 std::string dso_path;
59
60 bool all_functions_loaded = false;
61 apr_status_t rv;
62
63#if LL_WINDOWS
64 dso_name = "llkdu.dll";
65#elif LL_DARWIN
66 dso_name = "libllkdu.dylib";
67#else
68 dso_name = "libllkdu.so";
69#endif
70
71 dso_path = gDirUtilp->findFile(dso_name,
72 gDirUtilp->getAppRODataDir(),
73 gDirUtilp->getExecutableDir());
74
75 j2cimpl_dso_handle = NULL;
76 j2cimpl_dso_memory_pool = NULL;
77
78 //attempt to load the shared library
79 apr_pool_create(&j2cimpl_dso_memory_pool, NULL);
80 rv = apr_dso_load(&j2cimpl_dso_handle,
81 dso_path.c_str(),
82 j2cimpl_dso_memory_pool);
83
84 //now, check for success
85 if ( rv == APR_SUCCESS )
86 {
87 //found the dynamic library
88 //now we want to load the functions we're interested in
89 CreateLLImageJ2CFunction create_func = NULL;
90 DestroyLLImageJ2CFunction dest_func = NULL;
91
92 rv = apr_dso_sym((apr_dso_handle_sym_t*)&create_func,
93 j2cimpl_dso_handle,
94 "createLLImageJ2CKDU");
95 if ( rv == APR_SUCCESS )
96 {
97 //we've loaded the create function ok
98 //we need to delete via the DSO too
99 //so lets check for a destruction function
100 rv = apr_dso_sym((apr_dso_handle_sym_t*)&dest_func,
101 j2cimpl_dso_handle,
102 "destroyLLImageJ2CKDU");
103 if ( rv == APR_SUCCESS )
104 {
105 //k, everything is loaded alright
106 j2cimpl_create_func = create_func;
107 j2cimpl_destroy_func = dest_func;
108 all_functions_loaded = true;
109 }
110 }
111 }
112
113 if ( !all_functions_loaded )
114 {
115 //something went wrong with the DSO or function loading..
116 //fall back onto our satefy impl creation function
117
118#if 0
119 // precious verbose debugging, sadly we can't use our
120 // 'llinfos' stream etc. this early in the initialisation seq.
121 char errbuf[256];
122 fprintf(stderr, "failed to load syms from DSO %s (%s)\n",
123 dso_name.c_str(), dso_path.c_str());
124 apr_strerror(rv, errbuf, sizeof(errbuf));
125 fprintf(stderr, "error: %d, %s\n", rv, errbuf);
126 apr_dso_error(j2cimpl_dso_handle, errbuf, sizeof(errbuf));
127 fprintf(stderr, "dso-error: %d, %s\n", rv, errbuf);
128#endif
129
130 if ( j2cimpl_dso_handle )
131 {
132 apr_dso_unload(j2cimpl_dso_handle);
133 j2cimpl_dso_handle = NULL;
134 }
135
136 if ( j2cimpl_dso_memory_pool )
137 {
138 apr_pool_destroy(j2cimpl_dso_memory_pool);
139 j2cimpl_dso_memory_pool = NULL;
140 }
141 }
142}
143
144//static
145void LLImageJ2C::closeDSO()
146{
147 if ( j2cimpl_dso_handle ) apr_dso_unload(j2cimpl_dso_handle);
148 if (j2cimpl_dso_memory_pool) apr_pool_destroy(j2cimpl_dso_memory_pool);
149}
150
151LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
152 mMaxBytes(0),
153 mRawDiscardLevel(-1),
154 mRate(0.0f)
155{
156 //We assume here that if we wanted to destory via
157 //a dynamic library that the approriate open calls were made
158 //before any calls to this constructor.
159
160 //Therefore, a NULL creation function pointer here means
161 //we either did not want to create using functions from the dynamic
162 //library or there were issues loading it, either way
163 //use our fall back
164 if ( !j2cimpl_create_func )
165 {
166 j2cimpl_create_func = fallbackCreateLLImageJ2CImpl;
167 }
168
169 mImpl = j2cimpl_create_func();
170}
171
172// virtual
173LLImageJ2C::~LLImageJ2C()
174{
175 //We assume here that if we wanted to destory via
176 //a dynamic library that the approriate open calls were made
177 //before any calls to this destructor.
178
179 //Therefore, a NULL creation function pointer here means
180 //we either did not want to destroy using functions from the dynamic
181 //library or there were issues loading it, either way
182 //use our fall back
183 if ( !j2cimpl_destroy_func )
184 {
185 j2cimpl_destroy_func = fallbackDestroyLLImageJ2CImpl;
186 }
187
188 if ( mImpl )
189 {
190 j2cimpl_destroy_func(mImpl);
191 }
192}
193
194// virtual
195S8 LLImageJ2C::getRawDiscardLevel()
196{
197 return mRawDiscardLevel;
198}
199
200BOOL LLImageJ2C::updateData()
201{
202 resetLastError();
203
204 // Check to make sure that this instance has been initialized with data
205 if (!getData() || (getDataSize() < 16))
206 {
207 setLastError("LLImageJ2C uninitialized");
208 return FALSE;
209 }
210
211 if (!mImpl->getMetadata(*this))
212 {
213 return FALSE;
214 }
215 // SJB: override discard based on mMaxBytes elsewhere
216 S32 max_bytes = getDataSize(); // mMaxBytes ? mMaxBytes : getDataSize();
217 S32 discard = calcDiscardLevelBytes(max_bytes);
218 setDiscardLevel(discard);
219
220 return TRUE;
221}
222
223
224BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
225{
226 return decode(raw_imagep, decode_time, 0, 4);
227}
228
229
230BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
231{
232 LLMemType mt1((LLMemType::EMemType)mMemType);
233
234 resetLastError();
235
236 // Check to make sure that this instance has been initialized with data
237 if (!getData() || (getDataSize() < 16))
238 {
239 setLastError("LLImageJ2C uninitialized");
240 return FALSE;
241 }
242
243 // Update the raw discard level
244 updateRawDiscardLevel();
245
246 return mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
247}
248
249
250BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
251{
252 return encode(raw_imagep, NULL, encode_time);
253}
254
255
256BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
257{
258 LLMemType mt1((LLMemType::EMemType)mMemType);
259 return mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time);
260}
261
262//static
263S32 LLImageJ2C::calcHeaderSizeJ2C()
264{
265 return 600; //2048; // ??? hack... just needs to be >= actual header size...
266}
267
268//static
269S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate)
270{
271 if (rate <= 0.f) rate = .125f;
272 while (discard_level > 0)
273 {
274 if (w < 1 || h < 1)
275 break;
276 w >>= 1;
277 h >>= 1;
278 discard_level--;
279 }
280 S32 bytes = (S32)((F32)(w*h*comp)*rate);
281 bytes = llmax(bytes, calcHeaderSizeJ2C());
282 return bytes;
283}
284
285S32 LLImageJ2C::calcHeaderSize()
286{
287 return calcHeaderSizeJ2C();
288}
289
290S32 LLImageJ2C::calcDataSize(S32 discard_level)
291{
292 return calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), discard_level, mRate);
293}
294
295S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
296{
297 llassert(bytes >= 0);
298 S32 discard_level = 0;
299 if (bytes == 0)
300 {
301 return MAX_DISCARD_LEVEL;
302 }
303 while (1)
304 {
305 S32 bytes_needed = calcDataSize(discard_level); // virtual
306 if (bytes >= bytes_needed - (bytes_needed>>2)) // For J2c, up the res at 75% of the optimal number of bytes
307 {
308 break;
309 }
310 discard_level++;
311 if (discard_level >= MAX_DISCARD_LEVEL)
312 {
313 break;
314 }
315 }
316 return discard_level;
317}
318
319void LLImageJ2C::setRate(F32 rate)
320{
321 mRate = rate;
322}
323
324void LLImageJ2C::setMaxBytes(S32 max_bytes)
325{
326 mMaxBytes = max_bytes;
327}
328// NOT USED
329// void LLImageJ2C::setReversible(const BOOL reversible)
330// {
331// mReversible = reversible;
332// }
333
334
335BOOL LLImageJ2C::loadAndValidate(const LLString &filename)
336{
337 resetLastError();
338
339 S32 file_size = 0;
340 apr_file_t* apr_file = ll_apr_file_open(filename, LL_APR_RB, &file_size);
341 if (!apr_file)
342 {
343 setLastError("Unable to open file for reading", filename);
344 return FALSE;
345 }
346 if (file_size == 0)
347 {
348 setLastError("File is empty",filename);
349 apr_file_close(apr_file);
350 return FALSE;
351 }
352
353 U8 *data = new U8[file_size];
354 apr_size_t bytes_read = file_size;
355 apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
356 if (s != APR_SUCCESS || bytes_read != file_size)
357 {
358 delete[] data;
359 setLastError("Unable to read entire file");
360 return FALSE;
361 }
362 apr_file_close(apr_file);
363
364 return validate(data, file_size);
365}
366
367
368BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
369{
370 LLMemType mt1((LLMemType::EMemType)mMemType);
371 // Taken from setData()
372
373 BOOL res = LLImageFormatted::setData(data, file_size);
374 if ( !res )
375 {
376 return FALSE;
377 }
378
379 // Check to make sure that this instance has been initialized with data
380 if (!getData() || (0 == getDataSize()))
381 {
382 setLastError("LLImageJ2C uninitialized");
383 return FALSE;
384 }
385
386 return mImpl->getMetadata(*this);
387}
388
389void LLImageJ2C::setDecodingDone(BOOL complete)
390{
391 mDecoding = FALSE;
392 mDecoded = complete;
393}
394
395void LLImageJ2C::updateRawDiscardLevel()
396{
397 mRawDiscardLevel = mMaxBytes ? calcDiscardLevelBytes(mMaxBytes) : mDiscardLevel;
398}
399
400LLImageJ2CImpl::~LLImageJ2CImpl()
401{
402}
diff --git a/linden/indra/llimage/llimagej2c.h b/linden/indra/llimage/llimagej2c.h
new file mode 100644
index 0000000..a6894ab
--- /dev/null
+++ b/linden/indra/llimage/llimagej2c.h
@@ -0,0 +1,99 @@
1/**
2 * @file llimagej2c.h
3 * @brief Image implmenation for jpeg2000.
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#ifndef LL_LLIMAGEJ2C_H
29#define LL_LLIMAGEJ2C_H
30
31#include "llimage.h"
32#include "llassettype.h"
33
34class LLImageJ2CImpl;
35class LLImageJ2C : public LLImageFormatted
36{
37protected:
38 virtual ~LLImageJ2C();
39
40public:
41 LLImageJ2C();
42
43 // Base class overrides
44 /*virtual*/ BOOL updateData();
45 /*virtual*/ BOOL decode(LLImageRaw *raw_imagep, F32 decode_time=0.0);
46 /*virtual*/ BOOL decode(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count);
47 /*virtual*/ BOOL encode(const LLImageRaw *raw_imagep, F32 encode_time=0.0);
48 /*virtual*/ S32 calcHeaderSize();
49 /*virtual*/ S32 calcDataSize(S32 discard_level = 0);
50 /*virtual*/ S32 calcDiscardLevelBytes(S32 bytes);
51 /*virtual*/ S8 getRawDiscardLevel();
52
53 // Encode with comment text
54 BOOL encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time=0.0);
55
56 BOOL validate(U8 *data, U32 file_size);
57 BOOL loadAndValidate(const LLString &filename);
58
59 // Encode accessors
60 void setReversible(const BOOL reversible); // Use non-lossy?
61 void setRate(F32 rate);
62 void setMaxBytes(S32 max_bytes);
63 S32 getMaxBytes() const { return mMaxBytes; }
64
65 static S32 calcHeaderSizeJ2C();
66 static S32 calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate = 0.f);
67
68 static void openDSO();
69 static void closeDSO();
70
71protected:
72 friend class LLImageJ2CImpl;
73 friend class LLImageJ2COJ;
74 friend class LLImageJ2CKDU;
75 void setDecodingDone(BOOL complete = TRUE);
76 void updateRawDiscardLevel();
77
78 S32 mMaxBytes; // Maximum number of bytes of data to use...
79 S8 mRawDiscardLevel;
80 F32 mRate;
81 LLImageJ2CImpl *mImpl;
82};
83
84// Derive from this class to implement JPEG2000 decoding
85class LLImageJ2CImpl
86{
87public:
88 virtual ~LLImageJ2CImpl();
89protected:
90 virtual BOOL getMetadata(LLImageJ2C &base) = 0;
91 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;
93
94 friend class LLImageJ2C;
95};
96
97#define LINDEN_J2C_COMMENT_PREFIX "LL_"
98
99#endif
diff --git a/linden/indra/llimage/llimagejpeg.cpp b/linden/indra/llimage/llimagejpeg.cpp
new file mode 100644
index 0000000..5c83f20
--- /dev/null
+++ b/linden/indra/llimage/llimagejpeg.cpp
@@ -0,0 +1,621 @@
1/**
2 * @file llimagejpeg.cpp
3 *
4 * Copyright (c) 2002-2007, Linden Research, Inc.
5 *
6 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement
9 * ("Other License"), formally executed by you and Linden Lab. Terms of
10 * the GPL can be found in doc/GPL-license.txt in this distribution, or
11 * online at http://secondlife.com/developers/opensource/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at http://secondlife.com/developers/opensource/flossexception
17 *
18 * By copying, modifying or distributing this software, you acknowledge
19 * that you have read and understood your obligations described above,
20 * and agree to abide by those obligations.
21 *
22 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
23 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
24 * COMPLETENESS OR PERFORMANCE.
25 */
26
27#include "linden_common.h"
28#include "stdtypes.h"
29
30#include "llimagejpeg.h"
31
32#include "llerror.h"
33
34LLImageJPEG::LLImageJPEG()
35 :
36 LLImageFormatted(IMG_CODEC_JPEG),
37 mOutputBuffer( NULL ),
38 mOutputBufferSize( 0 ),
39 mEncodeQuality( 75 ) // on a scale from 1 to 100
40{
41}
42
43LLImageJPEG::~LLImageJPEG()
44{
45 llassert( !mOutputBuffer ); // Should already be deleted at end of encode.
46 delete[] mOutputBuffer;
47}
48
49BOOL LLImageJPEG::updateData()
50{
51 resetLastError();
52
53 // Check to make sure that this instance has been initialized with data
54 if (!getData() || (0 == getDataSize()))
55 {
56 setLastError("Uninitialized instance of LLImageJPEG");
57 return FALSE;
58 }
59
60 ////////////////////////////////////////
61 // Step 1: allocate and initialize JPEG decompression object
62
63 // This struct contains the JPEG decompression parameters and pointers to
64 // working space (which is allocated as needed by the JPEG library).
65 struct jpeg_decompress_struct cinfo;
66 cinfo.client_data = this;
67
68 struct jpeg_error_mgr jerr;
69 cinfo.err = jpeg_std_error(&jerr);
70
71 // Customize with our own callbacks
72 jerr.error_exit = &LLImageJPEG::errorExit; // Error exit handler: does not return to caller
73 jerr.emit_message = &LLImageJPEG::errorEmitMessage; // Conditionally emit a trace or warning message
74 jerr.output_message = &LLImageJPEG::errorOutputMessage; // Routine that actually outputs a trace or error message
75
76 try
77 {
78 // Now we can initialize the JPEG decompression object.
79 jpeg_create_decompress(&cinfo);
80
81 ////////////////////////////////////////
82 // Step 2: specify data source
83 // (Code is modified version of jpeg_stdio_src();
84 if (cinfo.src == NULL)
85 {
86 cinfo.src = (struct jpeg_source_mgr *)
87 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
88 sizeof(struct jpeg_source_mgr));
89 }
90 cinfo.src->init_source = &LLImageJPEG::decodeInitSource;
91 cinfo.src->fill_input_buffer = &LLImageJPEG::decodeFillInputBuffer;
92 cinfo.src->skip_input_data = &LLImageJPEG::decodeSkipInputData;
93 cinfo.src->resync_to_restart = jpeg_resync_to_restart; // For now, use default method, but we should be able to do better.
94 cinfo.src->term_source = &LLImageJPEG::decodeTermSource;
95
96 cinfo.src->bytes_in_buffer = getDataSize();
97 cinfo.src->next_input_byte = getData();
98
99 ////////////////////////////////////////
100 // Step 3: read file parameters with jpeg_read_header()
101 jpeg_read_header( &cinfo, TRUE );
102
103 // Data set by jpeg_read_header
104 setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
105
106 /*
107 // More data set by jpeg_read_header
108 cinfo.num_components;
109 cinfo.jpeg_color_space; // Colorspace of image
110 cinfo.saw_JFIF_marker; // TRUE if a JFIF APP0 marker was seen
111 cinfo.JFIF_major_version; // Version information from JFIF marker
112 cinfo.JFIF_minor_version; //
113 cinfo.density_unit; // Resolution data from JFIF marker
114 cinfo.X_density;
115 cinfo.Y_density;
116 cinfo.saw_Adobe_marker; // TRUE if an Adobe APP14 marker was seen
117 cinfo.Adobe_transform; // Color transform code from Adobe marker
118 */
119 }
120 catch (int)
121 {
122 jpeg_destroy_decompress(&cinfo);
123
124 return FALSE;
125 }
126 ////////////////////////////////////////
127 // Step 4: Release JPEG decompression object
128 jpeg_destroy_decompress(&cinfo);
129
130 return TRUE;
131}
132
133// Initialize source --- called by jpeg_read_header
134// before any data is actually read.
135void LLImageJPEG::decodeInitSource( j_decompress_ptr cinfo )
136{
137 // no work necessary here
138}
139
140// Fill the input buffer --- called whenever buffer is emptied.
141boolean LLImageJPEG::decodeFillInputBuffer( j_decompress_ptr cinfo )
142{
143// jpeg_source_mgr* src = cinfo->src;
144// LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
145
146 // Should never get here, since we provide the entire buffer up front.
147 ERREXIT(cinfo, JERR_INPUT_EMPTY);
148
149 return TRUE;
150}
151
152// Skip data --- used to skip over a potentially large amount of
153// uninteresting data (such as an APPn marker).
154//
155// Writers of suspendable-input applications must note that skip_input_data
156// is not granted the right to give a suspension return. If the skip extends
157// beyond the data currently in the buffer, the buffer can be marked empty so
158// that the next read will cause a fill_input_buffer call that can suspend.
159// Arranging for additional bytes to be discarded before reloading the input
160// buffer is the application writer's problem.
161void LLImageJPEG::decodeSkipInputData (j_decompress_ptr cinfo, long num_bytes)
162{
163 jpeg_source_mgr* src = cinfo->src;
164// LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
165
166 src->next_input_byte += (size_t) num_bytes;
167 src->bytes_in_buffer -= (size_t) num_bytes;
168}
169
170void LLImageJPEG::decodeTermSource (j_decompress_ptr cinfo)
171{
172 // no work necessary here
173}
174
175
176BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
177{
178 llassert_always(raw_image);
179
180 resetLastError();
181
182 // Check to make sure that this instance has been initialized with data
183 if (!getData() || (0 == getDataSize()))
184 {
185 setLastError("LLImageJPEG trying to decode an image with no data!");
186 return FALSE;
187 }
188
189 S32 row_stride = 0;
190 U8* raw_image_data = NULL;
191
192 ////////////////////////////////////////
193 // Step 1: allocate and initialize JPEG decompression object
194
195 // This struct contains the JPEG decompression parameters and pointers to
196 // working space (which is allocated as needed by the JPEG library).
197 struct jpeg_decompress_struct cinfo;
198
199 struct jpeg_error_mgr jerr;
200 cinfo.err = jpeg_std_error(&jerr);
201
202 // Customize with our own callbacks
203 jerr.error_exit = &LLImageJPEG::errorExit; // Error exit handler: does not return to caller
204 jerr.emit_message = &LLImageJPEG::errorEmitMessage; // Conditionally emit a trace or warning message
205 jerr.output_message = &LLImageJPEG::errorOutputMessage; // Routine that actually outputs a trace or error message
206
207
208 try
209 {
210 // Now we can initialize the JPEG decompression object.
211 jpeg_create_decompress(&cinfo);
212
213 ////////////////////////////////////////
214 // Step 2: specify data source
215 // (Code is modified version of jpeg_stdio_src();
216 if (cinfo.src == NULL)
217 {
218 cinfo.src = (struct jpeg_source_mgr *)
219 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
220 sizeof(struct jpeg_source_mgr));
221 }
222 cinfo.src->init_source = &LLImageJPEG::decodeInitSource;
223 cinfo.src->fill_input_buffer = &LLImageJPEG::decodeFillInputBuffer;
224 cinfo.src->skip_input_data = &LLImageJPEG::decodeSkipInputData;
225 cinfo.src->resync_to_restart = jpeg_resync_to_restart; // For now, use default method, but we should be able to do better.
226 cinfo.src->term_source = &LLImageJPEG::decodeTermSource;
227 cinfo.src->bytes_in_buffer = getDataSize();
228 cinfo.src->next_input_byte = getData();
229
230 ////////////////////////////////////////
231 // Step 3: read file parameters with jpeg_read_header()
232
233 jpeg_read_header(&cinfo, TRUE);
234
235 // We can ignore the return value from jpeg_read_header since
236 // (a) suspension is not possible with our data source, and
237 // (b) we passed TRUE to reject a tables-only JPEG file as an error.
238 // See libjpeg.doc for more info.
239
240 setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
241
242 raw_image->resize(getWidth(), getHeight(), getComponents());
243 raw_image_data = raw_image->getData();
244
245
246 ////////////////////////////////////////
247 // Step 4: set parameters for decompression
248 cinfo.out_color_components = 3;
249 cinfo.out_color_space = JCS_RGB;
250
251
252 ////////////////////////////////////////
253 // Step 5: Start decompressor
254
255 jpeg_start_decompress(&cinfo);
256 // We can ignore the return value since suspension is not possible
257 // with our data source.
258
259 // We may need to do some setup of our own at this point before reading
260 // the data. After jpeg_start_decompress() we have the correct scaled
261 // output image dimensions available, as well as the output colormap
262 // if we asked for color quantization.
263 // In this example, we need to make an output work buffer of the right size.
264
265 // JSAMPLEs per row in output buffer
266 row_stride = cinfo.output_width * cinfo.output_components;
267
268 ////////////////////////////////////////
269 // Step 6: while (scan lines remain to be read)
270 // jpeg_read_scanlines(...);
271
272 // Here we use the library's state variable cinfo.output_scanline as the
273 // loop counter, so that we don't have to keep track ourselves.
274
275 // Move pointer to last line
276 raw_image_data += row_stride * (cinfo.output_height - 1);
277
278 while (cinfo.output_scanline < cinfo.output_height)
279 {
280 // jpeg_read_scanlines expects an array of pointers to scanlines.
281 // Here the array is only one element long, but you could ask for
282 // more than one scanline at a time if that's more convenient.
283
284 jpeg_read_scanlines(&cinfo, &raw_image_data, 1);
285 raw_image_data -= row_stride; // move pointer up a line
286 }
287
288 ////////////////////////////////////////
289 // Step 7: Finish decompression
290 jpeg_finish_decompress(&cinfo);
291
292 ////////////////////////////////////////
293 // Step 8: Release JPEG decompression object
294 jpeg_destroy_decompress(&cinfo);
295 }
296
297 catch (int)
298 {
299 jpeg_destroy_decompress(&cinfo);
300 return FALSE;
301 }
302
303 // Check to see whether any corrupt-data warnings occurred
304 if( jerr.num_warnings != 0 )
305 {
306 // TODO: extract the warning to find out what went wrong.
307 setLastError( "Unable to decode JPEG image.");
308 return FALSE;
309 }
310
311 return TRUE;
312}
313
314
315// Initialize destination --- called by jpeg_start_compress before any data is actually written.
316// static
317void LLImageJPEG::encodeInitDestination ( j_compress_ptr cinfo )
318{
319 LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
320
321 cinfo->dest->next_output_byte = self->mOutputBuffer;
322 cinfo->dest->free_in_buffer = self->mOutputBufferSize;
323}
324
325
326// Empty the output buffer --- called whenever buffer fills up.
327//
328// In typical applications, this should write the entire output buffer
329// (ignoring the current state of next_output_byte & free_in_buffer),
330// reset the pointer & count to the start of the buffer, and return TRUE
331// indicating that the buffer has been dumped.
332//
333// In applications that need to be able to suspend compression due to output
334// overrun, a FALSE return indicates that the buffer cannot be emptied now.
335// In this situation, the compressor will return to its caller (possibly with
336// an indication that it has not accepted all the supplied scanlines). The
337// application should resume compression after it has made more room in the
338// output buffer. Note that there are substantial restrictions on the use of
339// suspension --- see the documentation.
340//
341// When suspending, the compressor will back up to a convenient restart point
342// (typically the start of the current MCU). next_output_byte & free_in_buffer
343// indicate where the restart point will be if the current call returns FALSE.
344// Data beyond this point will be regenerated after resumption, so do not
345// write it out when emptying the buffer externally.
346
347boolean LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )
348{
349 LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
350
351 // Should very rarely happen, since our output buffer is
352 // as large as the input to start out with.
353
354 // Double the buffer size;
355 S32 new_buffer_size = self->mOutputBufferSize * 2;
356 U8* new_buffer = new U8[ new_buffer_size ];
357 memcpy( new_buffer, self->mOutputBuffer, self->mOutputBufferSize );
358 delete[] self->mOutputBuffer;
359 self->mOutputBuffer = new_buffer;
360
361 cinfo->dest->next_output_byte = self->mOutputBuffer + self->mOutputBufferSize;
362 cinfo->dest->free_in_buffer = self->mOutputBufferSize;
363 self->mOutputBufferSize = new_buffer_size;
364
365 return TRUE;
366}
367
368// Terminate destination --- called by jpeg_finish_compress
369// after all data has been written. Usually needs to flush buffer.
370//
371// NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
372// application must deal with any cleanup that should happen even
373// for error exit.
374void LLImageJPEG::encodeTermDestination( j_compress_ptr cinfo )
375{
376 LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
377
378 S32 file_bytes = (S32)(self->mOutputBufferSize - cinfo->dest->free_in_buffer);
379 self->allocateData(file_bytes);
380
381 memcpy( self->getData(), self->mOutputBuffer, file_bytes );
382}
383
384// static
385void LLImageJPEG::errorExit( j_common_ptr cinfo )
386{
387 //LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
388
389 // Always display the message
390 (*cinfo->err->output_message)(cinfo);
391
392 // Let the memory manager delete any temp files
393 jpeg_destroy(cinfo);
394
395 // Return control to the setjmp point
396 throw 1;
397}
398
399// Decide whether to emit a trace or warning message.
400// msg_level is one of:
401// -1: recoverable corrupt-data warning, may want to abort.
402// 0: important advisory messages (always display to user).
403// 1: first level of tracing detail.
404// 2,3,...: successively more detailed tracing messages.
405// An application might override this method if it wanted to abort on warnings
406// or change the policy about which messages to display.
407// static
408void LLImageJPEG::errorEmitMessage( j_common_ptr cinfo, int msg_level )
409{
410 struct jpeg_error_mgr * err = cinfo->err;
411
412 if (msg_level < 0)
413 {
414 // It's a warning message. Since corrupt files may generate many warnings,
415 // the policy implemented here is to show only the first warning,
416 // unless trace_level >= 3.
417 if (err->num_warnings == 0 || err->trace_level >= 3)
418 {
419 (*err->output_message) (cinfo);
420 }
421 // Always count warnings in num_warnings.
422 err->num_warnings++;
423 }
424 else
425 {
426 // It's a trace message. Show it if trace_level >= msg_level.
427 if (err->trace_level >= msg_level)
428 {
429 (*err->output_message) (cinfo);
430 }
431 }
432}
433
434// static
435void LLImageJPEG::errorOutputMessage( j_common_ptr cinfo )
436{
437 // Create the message
438 char buffer[JMSG_LENGTH_MAX];
439 (*cinfo->err->format_message) (cinfo, buffer);
440
441 ((LLImageJPEG*) cinfo->client_data)->setLastError( buffer );
442
443 BOOL is_decode = (cinfo->is_decompressor != 0);
444 llwarns << "LLImageJPEG " << (is_decode ? "decode " : "encode ") << " failed: " << buffer << llendl;
445}
446
447BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
448{
449 llassert_always(raw_image);
450
451 resetLastError();
452
453 switch( raw_image->getComponents() )
454 {
455 case 1:
456 case 3:
457 break;
458 default:
459 setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
460 return FALSE;
461 }
462
463 setSize(raw_image->getWidth(), raw_image->getHeight(), raw_image->getComponents());
464
465 // Allocate a temporary buffer big enough to hold the entire compressed image (and then some)
466 // (Note: we make it bigger in emptyOutputBuffer() if we need to)
467 delete[] mOutputBuffer;
468 mOutputBufferSize = getWidth() * getHeight() * getComponents() + 1024;
469 mOutputBuffer = new U8[ mOutputBufferSize ];
470
471 const U8* raw_image_data = NULL;
472 S32 row_stride = 0;
473
474 ////////////////////////////////////////
475 // Step 1: allocate and initialize JPEG compression object
476
477 // This struct contains the JPEG compression parameters and pointers to
478 // working space (which is allocated as needed by the JPEG library).
479 struct jpeg_compress_struct cinfo;
480 cinfo.client_data = this;
481
482 // We have to set up the error handler first, in case the initialization
483 // step fails. (Unlikely, but it could happen if you are out of memory.)
484 // This routine fills in the contents of struct jerr, and returns jerr's
485 // address which we place into the link field in cinfo.
486 struct jpeg_error_mgr jerr;
487 cinfo.err = jpeg_std_error(&jerr);
488
489 // Customize with our own callbacks
490 jerr.error_exit = &LLImageJPEG::errorExit; // Error exit handler: does not return to caller
491 jerr.emit_message = &LLImageJPEG::errorEmitMessage; // Conditionally emit a trace or warning message
492 jerr.output_message = &LLImageJPEG::errorOutputMessage; // Routine that actually outputs a trace or error message
493
494 // Establish the setjmp return context mSetjmpBuffer. Used by library to abort.
495 if( setjmp(mSetjmpBuffer) )
496 {
497 // If we get here, the JPEG code has signaled an error.
498 // We need to clean up the JPEG object, close the input file, and return.
499 jpeg_destroy_compress(&cinfo);
500 delete[] mOutputBuffer;
501 mOutputBuffer = NULL;
502 mOutputBufferSize = 0;
503 return FALSE;
504 }
505
506 try
507 {
508
509 // Now we can initialize the JPEG compression object.
510 jpeg_create_compress(&cinfo);
511
512 ////////////////////////////////////////
513 // Step 2: specify data destination
514 // (code is a modified form of jpeg_stdio_dest() )
515 if( cinfo.dest == NULL)
516 {
517 cinfo.dest = (struct jpeg_destination_mgr *)
518 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
519 sizeof(struct jpeg_destination_mgr));
520 }
521 cinfo.dest->next_output_byte = mOutputBuffer; // => next byte to write in buffer
522 cinfo.dest->free_in_buffer = mOutputBufferSize; // # of byte spaces remaining in buffer
523 cinfo.dest->init_destination = &LLImageJPEG::encodeInitDestination;
524 cinfo.dest->empty_output_buffer = &LLImageJPEG::encodeEmptyOutputBuffer;
525 cinfo.dest->term_destination = &LLImageJPEG::encodeTermDestination;
526
527 ////////////////////////////////////////
528 // Step 3: set parameters for compression
529 //
530 // First we supply a description of the input image.
531 // Four fields of the cinfo struct must be filled in:
532
533 cinfo.image_width = getWidth(); // image width and height, in pixels
534 cinfo.image_height = getHeight();
535
536 switch( getComponents() )
537 {
538 case 1:
539 cinfo.input_components = 1; // # of color components per pixel
540 cinfo.in_color_space = JCS_GRAYSCALE; // colorspace of input image
541 break;
542 case 3:
543 cinfo.input_components = 3; // # of color components per pixel
544 cinfo.in_color_space = JCS_RGB; // colorspace of input image
545 break;
546 default:
547 setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
548 return FALSE;
549 }
550
551 // Now use the library's routine to set default compression parameters.
552 // (You must set at least cinfo.in_color_space before calling this,
553 // since the defaults depend on the source color space.)
554 jpeg_set_defaults(&cinfo);
555
556 // Now you can set any non-default parameters you wish to.
557 jpeg_set_quality(&cinfo, mEncodeQuality, TRUE ); // limit to baseline-JPEG values
558
559 ////////////////////////////////////////
560 // Step 4: Start compressor
561 //
562 // TRUE ensures that we will write a complete interchange-JPEG file.
563 // Pass TRUE unless you are very sure of what you're doing.
564
565 jpeg_start_compress(&cinfo, TRUE);
566
567 ////////////////////////////////////////
568 // Step 5: while (scan lines remain to be written)
569 // jpeg_write_scanlines(...);
570
571 // Here we use the library's state variable cinfo.next_scanline as the
572 // loop counter, so that we don't have to keep track ourselves.
573 // To keep things simple, we pass one scanline per call; you can pass
574 // more if you wish, though.
575
576 row_stride = getWidth() * getComponents(); // JSAMPLEs per row in image_buffer
577
578 // NOTE: For compatibility with LLImage, we need to invert the rows.
579 raw_image_data = raw_image->getData();
580
581 const U8* last_row_data = raw_image_data + (getHeight()-1) * row_stride;
582
583 JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
584 while (cinfo.next_scanline < cinfo.image_height)
585 {
586 // jpeg_write_scanlines expects an array of pointers to scanlines.
587 // Here the array is only one element long, but you could pass
588 // more than one scanline at a time if that's more convenient.
589
590 //Ugly const uncast here (jpeg_write_scanlines should take a const* but doesn't)
591 //row_pointer[0] = (JSAMPROW)(raw_image_data + (cinfo.next_scanline * row_stride));
592 row_pointer[0] = (JSAMPROW)(last_row_data - (cinfo.next_scanline * row_stride));
593
594 jpeg_write_scanlines(&cinfo, row_pointer, 1);
595 }
596
597 ////////////////////////////////////////
598 // Step 6: Finish compression
599 jpeg_finish_compress(&cinfo);
600
601 // After finish_compress, we can release the temp output buffer.
602 delete[] mOutputBuffer;
603 mOutputBuffer = NULL;
604 mOutputBufferSize = 0;
605
606 ////////////////////////////////////////
607 // Step 7: release JPEG compression object
608 jpeg_destroy_compress(&cinfo);
609 }
610
611 catch(int)
612 {
613 jpeg_destroy_compress(&cinfo);
614 delete[] mOutputBuffer;
615 mOutputBuffer = NULL;
616 mOutputBufferSize = 0;
617 return FALSE;
618 }
619
620 return TRUE;
621}
diff --git a/linden/indra/llimage/llimagejpeg.h b/linden/indra/llimage/llimagejpeg.h
new file mode 100644
index 0000000..8f8e7bb
--- /dev/null
+++ b/linden/indra/llimage/llimagejpeg.h
@@ -0,0 +1,82 @@
1/**
2 * @file llimagejpeg.h
3 * @brief This class compresses and decompresses JPEG files
4 *
5 * Copyright (c) 2002-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_LLIMAGEJPEG_H
29#define LL_LLIMAGEJPEG_H
30
31#include <setjmp.h>
32
33#include "llimage.h"
34
35extern "C" {
36#include "jpeglib/jinclude.h"
37#include "jpeglib/jpeglib.h"
38#include "jpeglib/jerror.h"
39}
40
41class LLImageJPEG : public LLImageFormatted
42{
43protected:
44 virtual ~LLImageJPEG();
45
46public:
47 LLImageJPEG();
48
49 /*virtual*/ BOOL updateData();
50 /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 time=0.0);
51 /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 time=0.0);
52
53 void setEncodeQuality( S32 q ) { mEncodeQuality = q; } // on a scale from 1 to 100
54 S32 getEncodeQuality() { return mEncodeQuality; }
55
56 // Callbacks registered with jpeglib
57 static void encodeInitDestination ( j_compress_ptr cinfo );
58 static boolean encodeEmptyOutputBuffer(j_compress_ptr cinfo);
59 static void encodeTermDestination(j_compress_ptr cinfo);
60
61 static void decodeInitSource(j_decompress_ptr cinfo);
62 static boolean decodeFillInputBuffer(j_decompress_ptr cinfo);
63 static void decodeSkipInputData(j_decompress_ptr cinfo, long num_bytes);
64 static void decodeTermSource(j_decompress_ptr cinfo);
65
66
67 static void errorExit(j_common_ptr cinfo);
68 static void errorEmitMessage(j_common_ptr cinfo, int msg_level);
69 static void errorOutputMessage(j_common_ptr cinfo);
70
71 static BOOL decompress(LLImageJPEG* imagep);
72
73protected:
74 U8* mOutputBuffer; // temp buffer used during encoding
75 S32 mOutputBufferSize; // bytes in mOuputBuffer
76
77 S32 mEncodeQuality; // on a scale from 1 to 100
78
79 jmp_buf mSetjmpBuffer; // To allow the library to abort.
80};
81
82#endif // LL_LLIMAGEJPEG_H
diff --git a/linden/indra/llimage/llimagetga.cpp b/linden/indra/llimage/llimagetga.cpp
new file mode 100644
index 0000000..722bd1e
--- /dev/null
+++ b/linden/indra/llimage/llimagetga.cpp
@@ -0,0 +1,1109 @@
1/**
2 * @file llimagetga.cpp
3 *
4 * Copyright (c) 2001-2007, Linden Research, Inc.
5 *
6 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement
9 * ("Other License"), formally executed by you and Linden Lab. Terms of
10 * the GPL can be found in doc/GPL-license.txt in this distribution, or
11 * online at http://secondlife.com/developers/opensource/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at http://secondlife.com/developers/opensource/flossexception
17 *
18 * By copying, modifying or distributing this software, you acknowledge
19 * that you have read and understood your obligations described above,
20 * and agree to abide by those obligations.
21 *
22 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
23 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
24 * COMPLETENESS OR PERFORMANCE.
25 */
26
27#include "linden_common.h"
28
29#include "llimagetga.h"
30#include "llerror.h"
31#include "llmath.h"
32
33// For expanding 5-bit pixel values to 8-bit with best rounding
34// static
35const U8 LLImageTGA::s5to8bits[32] =
36 {
37 0, 8, 16, 25, 33, 41, 49, 58,
38 66, 74, 82, 90, 99, 107, 115, 123,
39 132, 140, 148, 156, 165, 173, 181, 189,
40 197, 206, 214, 222, 230, 239, 247, 255
41 };
42
43inline void LLImageTGA::decodeTruecolorPixel15( U8* dst, const U8* src )
44{
45 // We expand 5 bit data to 8 bit sample width.
46 // The format of the 16-bit (LSB first) input word is
47 // xRRRRRGGGGGBBBBB
48 U32 t = U32(src[0]) + (U32(src[1]) << 8);
49 dst[2] = s5to8bits[t & 0x1F]; // blue
50 t >>= 5;
51 dst[1] = s5to8bits[t & 0x1F]; // green
52 t >>= 5;
53 dst[0] = s5to8bits[t & 0x1F]; // red
54}
55
56LLImageTGA::LLImageTGA()
57 : LLImageFormatted(IMG_CODEC_TGA),
58 mColorMap( NULL ),
59 mColorMapStart( 0 ),
60 mColorMapLength( 0 ),
61 mColorMapBytesPerEntry( 0 ),
62 mIs15Bit( FALSE )
63{
64}
65
66LLImageTGA::LLImageTGA(const LLString& file_name)
67 : LLImageFormatted(IMG_CODEC_TGA),
68 mColorMap( NULL ),
69 mColorMapStart( 0 ),
70 mColorMapLength( 0 ),
71 mColorMapBytesPerEntry( 0 ),
72 mIs15Bit( FALSE )
73{
74 loadFile(file_name);
75}
76
77LLImageTGA::~LLImageTGA()
78{
79 delete mColorMap;
80}
81
82BOOL LLImageTGA::updateData()
83{
84 resetLastError();
85
86 // Check to make sure that this instance has been initialized with data
87 if (!getData() || (0 == getDataSize()))
88 {
89 setLastError("LLImageTGA uninitialized");
90 return FALSE;
91 }
92
93 // Pull image information from the header...
94 U8 flags;
95 U8 junk[256];
96
97 /****************************************************************************
98 **
99 ** For more information about the original Truevision TGA(tm) file format,
100 ** or for additional information about the new extensions to the
101 ** Truevision TGA file, refer to the "Truevision TGA File Format
102 ** Specification Version 2.0" available from Truevision or your
103 ** Truevision dealer.
104 **
105 ** FILE STRUCTURE FOR THE ORIGINAL TRUEVISION TGA FILE
106 ** FIELD 1 : NUMBER OF CHARACTERS IN ID FIELD (1 BYTES)
107 ** FIELD 2 : COLOR MAP TYPE (1 BYTES)
108 ** FIELD 3 : IMAGE TYPE CODE (1 BYTES)
109 ** = 0 NO IMAGE DATA INCLUDED
110 ** = 1 UNCOMPRESSED, COLOR-MAPPED IMAGE
111 ** = 2 UNCOMPRESSED, TRUE-COLOR IMAGE
112 ** = 3 UNCOMPRESSED, BLACK AND WHITE IMAGE
113 ** = 9 RUN-LENGTH ENCODED COLOR-MAPPED IMAGE
114 ** = 10 RUN-LENGTH ENCODED TRUE-COLOR IMAGE
115 ** = 11 RUN-LENGTH ENCODED BLACK AND WHITE IMAGE
116 ** FIELD 4 : COLOR MAP SPECIFICATION (5 BYTES)
117 ** 4.1 : COLOR MAP ORIGIN (2 BYTES)
118 ** 4.2 : COLOR MAP LENGTH (2 BYTES)
119 ** 4.3 : COLOR MAP ENTRY SIZE (2 BYTES)
120 ** FIELD 5 : IMAGE SPECIFICATION (10 BYTES)
121 ** 5.1 : X-ORIGIN OF IMAGE (2 BYTES)
122 ** 5.2 : Y-ORIGIN OF IMAGE (2 BYTES)
123 ** 5.3 : WIDTH OF IMAGE (2 BYTES)
124 ** 5.4 : HEIGHT OF IMAGE (2 BYTES)
125 ** 5.5 : IMAGE PIXEL SIZE (1 BYTE)
126 ** 5.6 : IMAGE DESCRIPTOR BYTE (1 BYTE)
127 ** FIELD 6 : IMAGE ID FIELD (LENGTH SPECIFIED BY FIELD 1)
128 ** FIELD 7 : COLOR MAP DATA (BIT WIDTH SPECIFIED BY FIELD 4.3 AND
129 ** NUMBER OF COLOR MAP ENTRIES SPECIFIED IN FIELD 4.2)
130 ** FIELD 8 : IMAGE DATA FIELD (WIDTH AND HEIGHT SPECIFIED IN
131 ** FIELD 5.3 AND 5.4)
132 ****************************************************************************/
133
134 mDataOffset = 0;
135 mIDLength = *(getData()+mDataOffset++);
136 mColorMapType = *(getData()+mDataOffset++);
137 mImageType = *(getData()+mDataOffset++);
138 mColorMapIndexLo = *(getData()+mDataOffset++);
139 mColorMapIndexHi = *(getData()+mDataOffset++);
140 mColorMapLengthLo = *(getData()+mDataOffset++);
141 mColorMapLengthHi = *(getData()+mDataOffset++);
142 mColorMapDepth = *(getData()+mDataOffset++);
143 mXOffsetLo = *(getData()+mDataOffset++);
144 mXOffsetHi = *(getData()+mDataOffset++);
145 mYOffsetLo = *(getData()+mDataOffset++);
146 mYOffsetHi = *(getData()+mDataOffset++);
147 mWidthLo = *(getData()+mDataOffset++);
148 mWidthHi = *(getData()+mDataOffset++);
149 mHeightLo = *(getData()+mDataOffset++);
150 mHeightHi = *(getData()+mDataOffset++);
151 mPixelSize = *(getData()+mDataOffset++);
152 flags = *(getData()+mDataOffset++);
153 mAttributeBits = flags & 0xf;
154 mOriginRightBit = (flags & 0x10) >> 4;
155 mOriginTopBit = (flags & 0x20) >> 5;
156 mInterleave = (flags & 0xc0) >> 6;
157
158 switch( mImageType )
159 {
160 case 0:
161 // No image data included in file
162 setLastError("Unable to load file. TGA file contains no image data.");
163 return FALSE;
164 case 1:
165 // Colormapped uncompressed
166 if( 8 != mPixelSize )
167 {
168 setLastError("Unable to load file. Colormapped images must have 8 bits per pixel.");
169 return FALSE;
170 }
171 break;
172 case 2:
173 // Truecolor uncompressed
174 break;
175 case 3:
176 // Monochrome uncompressed
177 if( 8 != mPixelSize )
178 {
179 setLastError("Unable to load file. Monochrome images must have 8 bits per pixel.");
180 return FALSE;
181 }
182 break;
183 case 9:
184 // Colormapped, RLE
185 break;
186 case 10:
187 // Truecolor, RLE
188 break;
189 case 11:
190 // Monochrome, RLE
191 if( 8 != mPixelSize )
192 {
193 setLastError("Unable to load file. Monochrome images must have 8 bits per pixel.");
194 return FALSE;
195 }
196 break;
197 default:
198 setLastError("Unable to load file. Unrecoginzed TGA image type.");
199 return FALSE;
200 }
201
202 // discard the ID field, if any
203 if (mIDLength)
204 {
205 memcpy(junk, getData()+mDataOffset, mIDLength);
206 mDataOffset += mIDLength;
207 }
208
209 // check to see if there's a colormap since even rgb files can have them
210 S32 color_map_bytes = 0;
211 if( (1 == mColorMapType) && (mColorMapDepth > 0) )
212 {
213 mColorMapStart = (S32(mColorMapIndexHi) << 8) + mColorMapIndexLo;
214 mColorMapLength = (S32(mColorMapLengthHi) << 8) + mColorMapLengthLo;
215
216 if( mColorMapDepth > 24 )
217 {
218 mColorMapBytesPerEntry = 4;
219 }
220 else
221 if( mColorMapDepth > 16 )
222 {
223 mColorMapBytesPerEntry = 3;
224 }
225 else
226 if( mColorMapDepth > 8 )
227 {
228 mColorMapBytesPerEntry = 2;
229 }
230 else
231 {
232 mColorMapBytesPerEntry = 1;
233 }
234 color_map_bytes = mColorMapLength * mColorMapBytesPerEntry;
235
236 // Note: although it's legal for TGA files to have color maps and not use them
237 // (some programs actually do this and use the color map for other ends), we'll
238 // only allocate memory for one if _we_ intend to use it.
239 if ( (1 == mImageType) || (9 == mImageType) )
240 {
241 mColorMap = new U8[ color_map_bytes ];
242 memcpy( mColorMap, getData() + mDataOffset, color_map_bytes );
243 }
244
245 mDataOffset += color_map_bytes;
246 }
247
248 // heights are read as bytes to prevent endian problems
249 S32 height = (S32(mHeightHi) << 8) + mHeightLo;
250 S32 width = (S32(mWidthHi) << 8) + mWidthLo;
251
252 // make sure that it's a pixel format that we understand
253 S32 bits_per_pixel;
254 if( mColorMap )
255 {
256 bits_per_pixel = mColorMapDepth;
257 }
258 else
259 {
260 bits_per_pixel = mPixelSize;
261 }
262
263 S32 components;
264 switch(bits_per_pixel)
265 {
266 case 24:
267 components = 3;
268 break;
269 case 32:
270 components = 4;
271// Don't enforce this. ACDSee doesn't bother to set the attributes bits correctly. Arrgh!
272// if( mAttributeBits != 8 )
273// {
274// setLastError("Unable to load file. 32 bit TGA image does not have 8 bits of alpha.");
275// return FALSE;
276// }
277 mAttributeBits = 8;
278 break;
279 case 15:
280 case 16:
281 components = 3;
282 mIs15Bit = TRUE; // 16th bit is used for Targa hardware interupts and is ignored.
283 break;
284 case 8:
285 components = 1;
286 break;
287 default:
288 setLastError("Unable to load file. Unknown pixel size.");
289 return FALSE;
290 }
291 setSize(width, height, components);
292
293 return TRUE;
294}
295
296BOOL LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
297{
298 llassert_always(raw_image);
299
300 // Check to make sure that this instance has been initialized with data
301 if (!getData() || (0 == getDataSize()))
302 {
303 setLastError("LLImageTGA trying to decode an image with no data!");
304 return FALSE;
305 }
306
307 // Copy everything after the header.
308
309 raw_image->resize(getWidth(), getHeight(), getComponents());
310
311 if( (getComponents() != 1) &&
312 (getComponents() != 3) &&
313 (getComponents() != 4) )
314 {
315 setLastError("TGA images with a number of components other than 1, 3, and 4 are not supported.");
316 return FALSE;
317 }
318
319
320 if( mOriginRightBit )
321 {
322 setLastError("TGA images with origin on right side are not supported.");
323 return FALSE;
324 }
325
326 BOOL flipped = (mOriginTopBit != 0);
327 BOOL rle_compressed = ((mImageType & 0x08) != 0);
328
329 if( mColorMap )
330 {
331 return decodeColorMap( raw_image, rle_compressed, flipped );
332 }
333 else
334 {
335 return decodeTruecolor( raw_image, rle_compressed, flipped );
336 }
337}
338
339BOOL LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
340{
341 BOOL success = FALSE;
342 BOOL alpha_opaque = FALSE;
343 if( rle )
344 {
345
346 switch( getComponents() )
347 {
348 case 1:
349 success = decodeTruecolorRle8( raw_image );
350 break;
351 case 3:
352 if( mIs15Bit )
353 {
354 success = decodeTruecolorRle15( raw_image );
355 }
356 else
357 {
358 success = decodeTruecolorRle24( raw_image );
359 }
360 break;
361 case 4:
362 success = decodeTruecolorRle32( raw_image, alpha_opaque );
363 if (alpha_opaque)
364 {
365 // alpha was entirely opaque
366 // convert to 24 bit image
367 LLPointer<LLImageRaw> compacted_image = new LLImageRaw(raw_image->getWidth(), raw_image->getHeight(), 3);
368 compacted_image->copy(raw_image);
369 raw_image->resize(raw_image->getWidth(), raw_image->getHeight(), 3);
370 raw_image->copy(compacted_image);
371 }
372 break;
373 }
374 }
375 else
376 {
377 BOOL alpha_opaque;
378 success = decodeTruecolorNonRle( raw_image, alpha_opaque );
379 if (alpha_opaque && raw_image->getComponents() == 4)
380 {
381 // alpha was entirely opaque
382 // convert to 24 bit image
383 LLPointer<LLImageRaw> compacted_image = new LLImageRaw(raw_image->getWidth(), raw_image->getHeight(), 3);
384 compacted_image->copy(raw_image);
385 raw_image->resize(raw_image->getWidth(), raw_image->getHeight(), 3);
386 raw_image->copy(compacted_image);
387 }
388 }
389
390 if( success && flipped )
391 {
392 // This works because the Targa definition requires that RLE blocks never
393 // encode pixels from more than one scanline.
394 // (On the other hand, it's not as fast as writing separate flipped versions as
395 // we did with TruecolorNonRle.)
396 raw_image->verticalFlip();
397 }
398
399 return success;
400}
401
402
403BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaque )
404{
405 alpha_opaque = TRUE;
406
407 // Origin is the bottom left
408 U8* dst = raw_image->getData();
409 U8* src = getData() + mDataOffset;
410 S32 pixels = getWidth() * getHeight();
411
412 if (getComponents() == 4)
413 {
414 while( pixels-- )
415 {
416 // Our data is stored in RGBA. TGA stores them as BGRA (little-endian ARGB)
417 dst[0] = src[2]; // Red
418 dst[1] = src[1]; // Green
419 dst[2] = src[0]; // Blue
420 dst[3] = src[3]; // Alpha
421 if (dst[3] != 255)
422 {
423 alpha_opaque = FALSE;
424 }
425 dst += 4;
426 src += 4;
427 }
428 }
429 else if (getComponents() == 3)
430 {
431 if( mIs15Bit )
432 {
433 while( pixels-- )
434 {
435 decodeTruecolorPixel15( dst, src );
436 dst += 3;
437 src += 2;
438 }
439 }
440 else
441 {
442 while( pixels-- )
443 {
444 dst[0] = src[2]; // Red
445 dst[1] = src[1]; // Green
446 dst[2] = src[0]; // Blue
447 dst += 3;
448 src += 3;
449 }
450 }
451 }
452 else if (getComponents() == 1)
453 {
454 memcpy(dst, src, pixels);
455 }
456
457 return TRUE;
458}
459
460void LLImageTGA::decodeColorMapPixel8( U8* dst, const U8* src )
461{
462 S32 index = llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 );
463 dst[0] = mColorMap[ index ];
464}
465
466void LLImageTGA::decodeColorMapPixel15( U8* dst, const U8* src )
467{
468 S32 index = llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 );
469 decodeTruecolorPixel15( dst, mColorMap + 2 * index );
470}
471
472void LLImageTGA::decodeColorMapPixel24( U8* dst, const U8* src )
473{
474 S32 index = 3 * llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 );
475 dst[0] = mColorMap[ index + 2 ]; // Red
476 dst[1] = mColorMap[ index + 1 ]; // Green
477 dst[2] = mColorMap[ index + 0 ]; // Blue
478}
479
480void LLImageTGA::decodeColorMapPixel32( U8* dst, const U8* src )
481{
482 S32 index = 4 * llclamp( *src - mColorMapStart, 0, mColorMapLength - 1 );
483 dst[0] = mColorMap[ index + 2 ]; // Red
484 dst[1] = mColorMap[ index + 1 ]; // Green
485 dst[2] = mColorMap[ index + 0 ]; // Blue
486 dst[3] = mColorMap[ index + 3 ]; // Alpha
487}
488
489
490BOOL LLImageTGA::decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
491{
492 // If flipped, origin is the top left. Need to reverse the order of the rows.
493 // Otherwise the origin is the bottom left.
494
495 if( 8 != mPixelSize )
496 {
497 return FALSE;
498 }
499
500 U8* src = getData() + mDataOffset;
501 U8* dst = raw_image->getData(); // start from the top
502
503 void (LLImageTGA::*pixel_decoder)( U8*, const U8* );
504
505 switch( mColorMapBytesPerEntry )
506 {
507 case 1: pixel_decoder = &LLImageTGA::decodeColorMapPixel8; break;
508 case 2: pixel_decoder = &LLImageTGA::decodeColorMapPixel15; break;
509 case 3: pixel_decoder = &LLImageTGA::decodeColorMapPixel24; break;
510 case 4: pixel_decoder = &LLImageTGA::decodeColorMapPixel32; break;
511 default: llassert(0); return FALSE;
512 }
513
514 if( rle )
515 {
516 U8* last_dst = dst + getComponents() * (getHeight() * getWidth() - 1);
517 while( dst <= last_dst )
518 {
519 // Read RLE block header
520 U8 block_header_byte = *src;
521 src++;
522
523 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
524 if( block_header_byte & 0x80 )
525 {
526 // Encoded (duplicate-pixel) block
527 do
528 {
529 (this->*pixel_decoder)( dst, src );
530 dst += getComponents();
531 block_pixel_count--;
532 }
533 while( block_pixel_count > 0 );
534 src++;
535 }
536 else
537 {
538 // Unencoded block
539 do
540 {
541 (this->*pixel_decoder)( dst, src );
542 dst += getComponents();
543 src++;
544 block_pixel_count--;
545 }
546 while( block_pixel_count > 0 );
547 }
548 }
549
550 raw_image->verticalFlip();
551 }
552 else
553 {
554 S32 src_row_bytes = getWidth();
555 S32 dst_row_bytes = getWidth() * getComponents();
556
557 if( flipped )
558 {
559 U8* src_last_row_start = src + (getHeight() - 1) * src_row_bytes;
560 src = src_last_row_start; // start from the bottom
561 src_row_bytes *= -1;
562 }
563
564
565 S32 i;
566 S32 j;
567
568 for( S32 row = 0; row < getHeight(); row++ )
569 {
570 for( i = 0, j = 0; j < getWidth(); i += getComponents(), j++ )
571 {
572 (this->*pixel_decoder)( dst + i, src + j );
573 }
574
575 dst += dst_row_bytes;
576 src += src_row_bytes;
577 }
578 }
579
580 return TRUE;
581}
582
583
584
585BOOL LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
586{
587 llassert_always(raw_image);
588
589 deleteData();
590
591 setSize(raw_image->getWidth(), raw_image->getHeight(), raw_image->getComponents());
592
593 // Data from header
594 mIDLength = 0; // Length of identifier string
595 mColorMapType = 0; // 0 = No Map
596
597 // Supported: 2 = Uncompressed true color, 3 = uncompressed monochrome without colormap
598 switch( getComponents() )
599 {
600 case 1:
601 mImageType = 3;
602 break;
603 case 2: // Interpret as intensity plus alpha
604 case 3:
605 case 4:
606 mImageType = 2;
607 break;
608 default:
609 return FALSE;
610 }
611
612 // Color map stuff (unsupported)
613 mColorMapIndexLo = 0; // First color map entry (low order byte)
614 mColorMapIndexHi = 0; // First color map entry (high order byte)
615 mColorMapLengthLo = 0; // Color map length (low order byte)
616 mColorMapLengthHi = 0; // Color map length (high order byte)
617 mColorMapDepth = 0; // Size of color map entry (15, 16, 24, or 32 bits)
618
619 // Image offset relative to origin.
620 mXOffsetLo = 0; // X offset from origin (low order byte)
621 mXOffsetHi = 0; // X offset from origin (hi order byte)
622 mYOffsetLo = 0; // Y offset from origin (low order byte)
623 mYOffsetHi = 0; // Y offset from origin (hi order byte)
624
625 // Height and width
626 mWidthLo = U8(getWidth() & 0xFF); // Width (low order byte)
627 mWidthHi = U8((getWidth() >> 8) & 0xFF); // Width (hi order byte)
628 mHeightLo = U8(getHeight() & 0xFF); // Height (low order byte)
629 mHeightHi = U8((getHeight() >> 8) & 0xFF); // Height (hi order byte)
630
631 S32 bytes_per_pixel;
632 switch( getComponents() )
633 {
634 case 1:
635 bytes_per_pixel = 1;
636 break;
637 case 3:
638 bytes_per_pixel = 3;
639 break;
640 case 2: // Interpret as intensity plus alpha. Store as RGBA.
641 case 4:
642 bytes_per_pixel = 4;
643 break;
644 default:
645 return FALSE;
646 }
647 mPixelSize = U8(bytes_per_pixel * 8); // 8, 16, 24, 32 bits per pixel
648
649 mAttributeBits = (4 == bytes_per_pixel) ? 8 : 0; // 4 bits: number of attribute bits (alpha) per pixel
650 mOriginRightBit = 0; // 1 bit: origin, 0 = left, 1 = right
651 mOriginTopBit = 0; // 1 bit: origin, 0 = bottom, 1 = top
652 mInterleave = 0; // 2 bits: interleaved flag, 0 = none, 1 = interleaved 2, 2 = interleaved 4
653
654
655 const S32 TGA_HEADER_SIZE = 18;
656 const S32 COLOR_MAP_SIZE = 0;
657 mDataOffset = TGA_HEADER_SIZE + mIDLength + COLOR_MAP_SIZE; // Offset from start of data to the actual header.
658
659 S32 pixels = getWidth() * getHeight();
660 S32 datasize = mDataOffset + bytes_per_pixel * pixels;
661 U8* dst = allocateData(datasize);
662
663 // Write header
664 *(dst++) = mIDLength;
665 *(dst++) = mColorMapType;
666 *(dst++) = mImageType;
667 *(dst++) = mColorMapIndexLo;
668 *(dst++) = mColorMapIndexHi;
669 *(dst++) = mColorMapLengthLo;
670 *(dst++) = mColorMapLengthHi;
671 *(dst++) = mColorMapDepth;
672 *(dst++) = mXOffsetLo;
673 *(dst++) = mXOffsetHi;
674 *(dst++) = mYOffsetLo;
675 *(dst++) = mYOffsetHi;
676 *(dst++) = mWidthLo;
677 *(dst++) = mWidthHi;
678 *(dst++) = mHeightLo;
679 *(dst++) = mHeightHi;
680 *(dst++) = mPixelSize;
681 *(dst++) =
682 ((mInterleave & 3) << 5) |
683 ((mOriginTopBit & 1) << 4) |
684 ((mOriginRightBit & 1) << 3) |
685 ((mAttributeBits & 0xF) << 0);
686
687 // Write pixels
688 const U8* src = raw_image->getData();
689 llassert( dst == getData() + mDataOffset );
690 S32 i = 0;
691 S32 j = 0;
692 switch( getComponents() )
693 {
694 case 1:
695 memcpy( dst, src, bytes_per_pixel * pixels );
696 break;
697
698 case 2:
699 while( pixels-- )
700 {
701 dst[i + 0] = src[j + 0]; // intensity
702 dst[i + 1] = src[j + 0]; // intensity
703 dst[i + 2] = src[j + 0]; // intensity
704 dst[i + 3] = src[j + 1]; // alpha
705 i += 4;
706 j += 2;
707 }
708 break;
709
710 case 3:
711 while( pixels-- )
712 {
713 dst[i + 0] = src[i + 2]; // blue
714 dst[i + 1] = src[i + 1]; // green
715 dst[i + 2] = src[i + 0]; // red
716 i += 3;
717 }
718 break;
719
720 case 4:
721 while( pixels-- )
722 {
723 dst[i + 0] = src[i + 2]; // blue
724 dst[i + 1] = src[i + 1]; // green
725 dst[i + 2] = src[i + 0]; // red
726 dst[i + 3] = src[i + 3]; // alpha
727 i += 4;
728 }
729 break;
730 }
731
732 return TRUE;
733}
734
735BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque )
736{
737 llassert( getComponents() == 4 );
738 alpha_opaque = TRUE;
739
740 U8* dst = raw_image->getData();
741 U32* dst_pixels = (U32*) dst;
742
743 U8* src = getData() + mDataOffset;
744
745 U32 rgba;
746 U8* rgba_byte_p = (U8*) &rgba;
747
748 U32* last_dst_pixel = dst_pixels + getHeight() * getWidth() - 1;
749 while( dst_pixels <= last_dst_pixel )
750 {
751 // Read RLE block header
752 U8 block_header_byte = *src;
753 src++;
754
755 U32 block_pixel_count = (block_header_byte & 0x7F) + 1;
756 if( block_header_byte & 0x80 )
757 {
758 // Encoded (duplicate-pixel) block
759 rgba_byte_p[0] = src[2];
760 rgba_byte_p[1] = src[1];
761 rgba_byte_p[2] = src[0];
762 rgba_byte_p[3] = src[3];
763 if (rgba_byte_p[3] != 255)
764 {
765 alpha_opaque = FALSE;
766 }
767
768 src += 4;
769 register U32 value = rgba;
770 do
771 {
772 *dst_pixels = value;
773 dst_pixels++;
774 block_pixel_count--;
775 }
776 while( block_pixel_count > 0 );
777 }
778 else
779 {
780 // Unencoded block
781 do
782 {
783 ((U8*)dst_pixels)[0] = src[2];
784 ((U8*)dst_pixels)[1] = src[1];
785 ((U8*)dst_pixels)[2] = src[0];
786 ((U8*)dst_pixels)[3] = src[3];
787 if (src[3] != 255)
788 {
789 alpha_opaque = FALSE;
790 }
791 src += 4;
792 dst_pixels++;
793 block_pixel_count--;
794 }
795 while( block_pixel_count > 0 );
796 }
797 }
798
799 return TRUE;
800}
801
802BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
803{
804 llassert( getComponents() == 3 );
805 llassert( mIs15Bit );
806
807 U8* dst = raw_image->getData();
808 U8* src = getData() + mDataOffset;
809
810 U8* last_dst = dst + getComponents() * (getHeight() * getWidth() - 1);
811 while( dst <= last_dst )
812 {
813 // Read RLE block header
814 U8 block_header_byte = *src;
815 src++;
816
817 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
818 if( block_header_byte & 0x80 )
819 {
820 // Encoded (duplicate-pixel) block
821 do
822 {
823 decodeTruecolorPixel15( dst, src ); // slow
824 dst += 3;
825 block_pixel_count--;
826 }
827 while( block_pixel_count > 0 );
828 src += 2;
829 }
830 else
831 {
832 // Unencoded block
833 do
834 {
835 decodeTruecolorPixel15( dst, src );
836 dst += 3;
837 src += 2;
838 block_pixel_count--;
839 }
840 while( block_pixel_count > 0 );
841 }
842 }
843
844 return TRUE;
845}
846
847
848
849BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
850{
851 llassert( getComponents() == 3 );
852
853 U8* dst = raw_image->getData();
854 U8* src = getData() + mDataOffset;
855
856 U8* last_dst = dst + getComponents() * (getHeight() * getWidth() - 1);
857 while( dst <= last_dst )
858 {
859 // Read RLE block header
860 U8 block_header_byte = *src;
861 src++;
862
863 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
864 if( block_header_byte & 0x80 )
865 {
866 // Encoded (duplicate-pixel) block
867 do
868 {
869 dst[0] = src[2];
870 dst[1] = src[1];
871 dst[2] = src[0];
872 dst += 3;
873 block_pixel_count--;
874 }
875 while( block_pixel_count > 0 );
876 src += 3;
877 }
878 else
879 {
880 // Unencoded block
881 do
882 {
883 dst[0] = src[2];
884 dst[1] = src[1];
885 dst[2] = src[0];
886 dst += 3;
887 src += 3;
888 block_pixel_count--;
889 }
890 while( block_pixel_count > 0 );
891 }
892 }
893
894 return TRUE;
895}
896
897
898BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
899{
900 llassert( getComponents() == 1 );
901
902 U8* dst = raw_image->getData();
903 U8* src = getData() + mDataOffset;
904
905 U8* last_dst = dst + getHeight() * getWidth() - 1;
906 while( dst <= last_dst )
907 {
908 // Read RLE block header
909 U8 block_header_byte = *src;
910 src++;
911
912 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
913 if( block_header_byte & 0x80 )
914 {
915 // Encoded (duplicate-pixel) block
916 memset( dst, *src, block_pixel_count );
917 dst += block_pixel_count;
918 src++;
919 }
920 else
921 {
922 // Unencoded block
923 do
924 {
925 *dst = *src;
926 dst++;
927 src++;
928 block_pixel_count--;
929 }
930 while( block_pixel_count > 0 );
931 }
932 }
933
934 return TRUE;
935}
936
937
938// Decoded and process the image for use in avatar gradient masks.
939// Processing happens during the decode for speed.
940BOOL LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight )
941{
942 llassert_always(raw_image);
943
944 // "Domain" isn't really the right word. It refers to the width of the
945 // ramp portion of the function that relates input and output pixel values.
946 // A domain of 0 gives a step function.
947 //
948 // | /----------------
949 // O| / |
950 // u| / |
951 // t| / |
952 // p|------------------/ |
953 // u| | |
954 // t|<---------------->|<-->|
955 // | "offset" "domain"
956 // |
957 // --+---Input--------------------------------
958 // |
959
960 if (!getData() || (0 == getDataSize()))
961 {
962 setLastError("LLImageTGA trying to decode an image with no data!");
963 return FALSE;
964 }
965
966 // Only works for unflipped monochrome RLE images
967 if( (getComponents() != 1) || (mImageType != 11) || mOriginTopBit || mOriginRightBit )
968 {
969 llerrs << "LLImageTGA trying to alpha-gradient process an image that's not a standard RLE, one component image" << llendl;
970 return FALSE;
971 }
972
973 raw_image->resize(getWidth(), getHeight(), getComponents());
974
975 U8* dst = raw_image->getData();
976 U8* src = getData() + mDataOffset;
977 U8* last_dst = dst + getHeight() * getWidth() - 1;
978
979 if( domain > 0 )
980 {
981 // Process using a look-up table (lut)
982 const S32 LUT_LEN = 256;
983 U8 lut[LUT_LEN];
984 S32 i;
985
986 F32 scale = 1.f / domain;
987 F32 offset = (1.f - domain) * llclampf( 1.f - weight );
988 F32 bias = -(scale * offset);
989
990 for( i = 0; i < LUT_LEN; i++ )
991 {
992 lut[i] = (U8)llclampb( 255.f * ( i/255.f * scale + bias ) );
993 }
994
995 while( dst <= last_dst )
996 {
997 // Read RLE block header
998 U8 block_header_byte = *src;
999 src++;
1000
1001 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
1002 if( block_header_byte & 0x80 )
1003 {
1004 // Encoded (duplicate-pixel) block
1005 memset( dst, lut[ *src ], block_pixel_count );
1006 dst += block_pixel_count;
1007 src++;
1008 }
1009 else
1010 {
1011 // Unencoded block
1012 do
1013 {
1014 *dst = lut[ *src ];
1015 dst++;
1016 src++;
1017 block_pixel_count--;
1018 }
1019 while( block_pixel_count > 0 );
1020 }
1021 }
1022 }
1023 else
1024 {
1025 // Process using a simple comparison agains a threshold
1026 const U8 threshold = (U8)(0xFF * llclampf( 1.f - weight ));
1027
1028 while( dst <= last_dst )
1029 {
1030 // Read RLE block header
1031 U8 block_header_byte = *src;
1032 src++;
1033
1034 U8 block_pixel_count = (block_header_byte & 0x7F) + 1;
1035 if( block_header_byte & 0x80 )
1036 {
1037 // Encoded (duplicate-pixel) block
1038 memset( dst, ((*src >= threshold) ? 0xFF : 0), block_pixel_count );
1039 dst += block_pixel_count;
1040 src++;
1041 }
1042 else
1043 {
1044 // Unencoded block
1045 do
1046 {
1047 *dst = (*src >= threshold) ? 0xFF : 0;
1048 dst++;
1049 src++;
1050 block_pixel_count--;
1051 }
1052 while( block_pixel_count > 0 );
1053 }
1054 }
1055 }
1056 return TRUE;
1057}
1058
1059// Reads a .tga file and creates an LLImageTGA with its data.
1060bool LLImageTGA::loadFile( const LLString& path )
1061{
1062 S32 len = path.size();
1063 if( len < 5 )
1064 {
1065 return false;
1066 }
1067
1068 LLString extension = path.substr( len - 4, 4 );
1069 LLString::toLower(extension);
1070 if( ".tga" != extension )
1071 {
1072 return false;
1073 }
1074
1075 FILE *file = LLFile::fopen(path.c_str(), "rb");
1076 if( !file )
1077 {
1078 llwarns << "Couldn't open file " << path << llendl;
1079 return false;
1080 }
1081
1082 S32 file_size = 0;
1083 if (!fseek(file, 0, SEEK_END))
1084 {
1085 file_size = ftell(file);
1086 fseek(file, 0, SEEK_SET);
1087 }
1088
1089 U8* buffer = allocateData(file_size);
1090 S32 bytes_read = fread(buffer, 1, file_size, file);
1091 if( bytes_read != file_size )
1092 {
1093 deleteData();
1094 llwarns << "Couldn't read file " << path << llendl;
1095 return false;
1096 }
1097
1098 fclose( file );
1099
1100 if( !updateData() )
1101 {
1102 llwarns << "Couldn't decode file " << path << llendl;
1103 deleteData();
1104 return false;
1105 }
1106 return true;
1107}
1108
1109
diff --git a/linden/indra/llimage/llimagetga.h b/linden/indra/llimage/llimagetga.h
new file mode 100644
index 0000000..9575b4d
--- /dev/null
+++ b/linden/indra/llimage/llimagetga.h
@@ -0,0 +1,108 @@
1/**
2 * @file llimagetga.h
3 * @brief Image implementation to compresses and decompressed TGA files.
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#ifndef LL_LLIMAGETGA_H
29#define LL_LLIMAGETGA_H
30
31#include "llimage.h"
32
33// This class compresses and decompressed TGA (targa) files
34
35class LLImageTGA : public LLImageFormatted
36{
37protected:
38 virtual ~LLImageTGA();
39
40public:
41 LLImageTGA();
42 LLImageTGA(const LLString& file_name);
43
44 /*virtual*/ BOOL updateData();
45 /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time=0.0);
46 /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time=0.0);
47
48 BOOL decodeAndProcess(LLImageRaw* raw_image, F32 domain, F32 weight);
49
50private:
51 BOOL decodeTruecolor( LLImageRaw* raw_image, BOOL rle, BOOL flipped );
52
53 BOOL decodeTruecolorRle8( LLImageRaw* raw_image );
54 BOOL decodeTruecolorRle15( LLImageRaw* raw_image );
55 BOOL decodeTruecolorRle24( LLImageRaw* raw_image );
56 BOOL decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque );
57
58 void decodeTruecolorPixel15( U8* dst, const U8* src );
59
60 BOOL decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaque );
61
62 BOOL decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped );
63
64 void decodeColorMapPixel8(U8* dst, const U8* src);
65 void decodeColorMapPixel15(U8* dst, const U8* src);
66 void decodeColorMapPixel24(U8* dst, const U8* src);
67 void decodeColorMapPixel32(U8* dst, const U8* src);
68
69 bool loadFile(const LLString& file_name);
70
71private:
72 // Class specific data
73 U32 mDataOffset; // Offset from start of data to the actual header.
74
75 // Data from header
76 U8 mIDLength; // Length of identifier string
77 U8 mColorMapType; // 0 = No Map
78 U8 mImageType; // Supported: 2 = Uncompressed true color, 3 = uncompressed monochrome without colormap
79 U8 mColorMapIndexLo; // First color map entry (low order byte)
80 U8 mColorMapIndexHi; // First color map entry (high order byte)
81 U8 mColorMapLengthLo; // Color map length (low order byte)
82 U8 mColorMapLengthHi; // Color map length (high order byte)
83 U8 mColorMapDepth; // Size of color map entry (15, 16, 24, or 32 bits)
84 U8 mXOffsetLo; // X offset of image (low order byte)
85 U8 mXOffsetHi; // X offset of image (hi order byte)
86 U8 mYOffsetLo; // Y offset of image (low order byte)
87 U8 mYOffsetHi; // Y offset of image (hi order byte)
88 U8 mWidthLo; // Width (low order byte)
89 U8 mWidthHi; // Width (hi order byte)
90 U8 mHeightLo; // Height (low order byte)
91 U8 mHeightHi; // Height (hi order byte)
92 U8 mPixelSize; // 8, 16, 24, 32 bits per pixel
93 U8 mAttributeBits; // 4 bits: number of attributes per pixel
94 U8 mOriginRightBit; // 1 bit: origin, 0 = left, 1 = right
95 U8 mOriginTopBit; // 1 bit: origin, 0 = bottom, 1 = top
96 U8 mInterleave; // 2 bits: interleaved flag, 0 = none, 1 = interleaved 2, 2 = interleaved 4
97
98 U8* mColorMap;
99 S32 mColorMapStart;
100 S32 mColorMapLength;
101 S32 mColorMapBytesPerEntry;
102
103 BOOL mIs15Bit;
104
105 static const U8 s5to8bits[32];
106};
107
108#endif
diff --git a/linden/indra/llimage/llmapimagetype.h b/linden/indra/llimage/llmapimagetype.h
new file mode 100644
index 0000000..1f83b71
--- /dev/null
+++ b/linden/indra/llimage/llmapimagetype.h
@@ -0,0 +1,41 @@
1/**
2 * @file llmapimagetype.h
3 *
4 * Copyright (c) 2003-2007, Linden Research, Inc.
5 *
6 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement
9 * ("Other License"), formally executed by you and Linden Lab. Terms of
10 * the GPL can be found in doc/GPL-license.txt in this distribution, or
11 * online at http://secondlife.com/developers/opensource/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at http://secondlife.com/developers/opensource/flossexception
17 *
18 * By copying, modifying or distributing this software, you acknowledge
19 * that you have read and understood your obligations described above,
20 * and agree to abide by those obligations.
21 *
22 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
23 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
24 * COMPLETENESS OR PERFORMANCE.
25 */
26
27#ifndef LL_LLMAPIMAGETYPE_H
28#define LL_LLMAPIMAGETYPE_H
29
30typedef enum e_map_image_type
31{
32 MIT_TERRAIN = 0,
33 MIT_POPULAR = 1,
34 MIT_OBJECTS = 2,
35 MIT_OBJECTS_FOR_SALE = 3,
36 MIT_LAND_TO_BUY = 4,
37 MIT_OBJECT_NEW = 5,
38 MIT_EOF = 6
39} EMapImageType;
40
41#endif