summaryrefslogtreecommitdiff
path: root/indra/llimage/llimage.h
blob: 404f1c076997aa8e659292fb741b8962dc9d1c2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
/** 
 * @file llimage.h
 * @brief Object for managing images and their textures.
 *
 * $LicenseInfo:firstyear=2000&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#ifndef LL_LLIMAGE_H
#define LL_LLIMAGE_H

#include "lluuid.h"
#include "llstring.h"
#include "llthread.h"
#include "llpointer.h"

const S32 MIN_IMAGE_MIP =  2; // 4x4, only used for expand/contract power of 2
const S32 MAX_IMAGE_MIP = 11; // 2048x2048

// *TODO : Use MAX_IMAGE_MIP as max discard level and modify j2c management so that the number 
// of levels is read from the header's file, not inferred from its size.
const S32 MAX_DISCARD_LEVEL = 5;

// JPEG2000 size constraints
// Those are declared here as they are germane to other image constraints used in the viewer
// and declared right here. Some come from the JPEG2000 spec, some conventions specific to SL.
const S32 MAX_DECOMPOSITION_LEVELS = 32;	// Number of decomposition levels cannot exceed 32 according to jpeg2000 spec
const S32 MIN_DECOMPOSITION_LEVELS = 5;		// the SL viewer will *crash* trying to decode images with fewer than 5 decomposition levels (unless image is small that is)
const S32 MAX_PRECINCT_SIZE = 2048;			// No reason to be bigger than MAX_IMAGE_SIZE 
const S32 MIN_PRECINCT_SIZE = 4;			// Can't be smaller than MIN_BLOCK_SIZE
const S32 MAX_BLOCK_SIZE = 64;				// Max total block size is 4096, hence 64x64 when using square blocks
const S32 MIN_BLOCK_SIZE = 4;				// Min block dim is 4 according to jpeg2000 spec
const S32 MIN_LAYER_SIZE = 2000;			// Size of the first quality layer (after header). Must be > to FIRST_PACKET_SIZE!!
const S32 MAX_NB_LAYERS = 64;				// Max number of layers we'll entertain in SL (practical limit)

const S32 MIN_IMAGE_SIZE = (1<<MIN_IMAGE_MIP); // 4, only used for expand/contract power of 2
const S32 MAX_IMAGE_SIZE = (1<<MAX_IMAGE_MIP); // 2048
const S32 MIN_IMAGE_AREA = MIN_IMAGE_SIZE * MIN_IMAGE_SIZE;
const S32 MAX_IMAGE_AREA = MAX_IMAGE_SIZE * MAX_IMAGE_SIZE;
const S32 MAX_IMAGE_COMPONENTS = 8;
const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS; //2048 * 2048 * 8 = 16 MB

// Note!  These CANNOT be changed without modifying simulator code
// *TODO: change both to 1024 when SIM texture fetching is deprecated
const S32 FIRST_PACKET_SIZE = 600;
const S32 MAX_IMG_PACKET_SIZE = 1000;
const S32 HTTP_PACKET_SIZE = 1496;

// Base classes for images.
// There are two major parts for the image:
// The compressed representation, and the decompressed representation.

class LLImageFormatted;
class LLImageRaw;
class LLColor4U;
class LLMatrix3;
class LLPrivateMemoryPool;

typedef enum e_image_codec
{
	IMG_CODEC_INVALID  = 0,
	IMG_CODEC_RGB  = 1,
	IMG_CODEC_J2C  = 2,
	IMG_CODEC_BMP  = 3,
	IMG_CODEC_TGA  = 4,
	IMG_CODEC_JPEG = 5,
	IMG_CODEC_DXT  = 6,
	IMG_CODEC_PNG  = 7,
	IMG_CODEC_EOF  = 8
} EImageCodec;

typedef enum e_vignette_mode
{
	VIGNETTE_MODE_NONE  = 0,
	VIGNETTE_MODE_BLEND = 1,
	VIGNETTE_MODE_FADE  = 2
} EVignetteMode;

//============================================================================
// library initialization class

class LLImage
{
public:
	static void initClass(bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75);
	static void cleanupClass();

	static const std::string& getLastError();
	static void setLastError(const std::string& message);
	
	static bool useNewByteRange() { return sUseNewByteRange; }
    static S32  getReverseByteRangePercent() { return sMinimalReverseByteRangePercent; }
	
protected:
	static LLMutex* sMutex;
	static std::string sLastErrorMessage;
	static bool sUseNewByteRange;
    static S32  sMinimalReverseByteRangePercent;
};

//============================================================================
// Image base class

class LLImageBase : public LLThreadSafeRefCount
{
protected:
	virtual ~LLImageBase();
	
public:
	LLImageBase();

	enum
	{
		TYPE_NORMAL = 0,
		TYPE_AVATAR_BAKE = 1,
	};

	virtual void deleteData();
	virtual U8* allocateData(S32 size = -1);
	virtual U8* reallocateData(S32 size = -1);

	virtual void dump();
	virtual void sanityCheck();

	U16 getWidth() const		{ return mWidth; }
	U16 getHeight() const		{ return mHeight; }
	S8	getComponents() const	{ return mComponents; }
	S32 getDataSize() const		{ return mDataSize; }

	const U8 *getData() const	;
	U8 *getData()				;
	bool isBufferInvalid() ;

	void setSize(S32 width, S32 height, S32 ncomponents);
	U8* allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 size = -1); // setSize() + allocateData()
	void enableOverSize() {mAllowOverSize = true ;}
	void disableOverSize() {mAllowOverSize = false; }

protected:
	// special accessor to allow direct setting of mData and mDataSize by LLImageFormatted
	void setDataAndSize(U8 *data, S32 size);
	
    // Histograms (if we ever happen to need them)
    U32 *mHistoRed;
    U32 *mHistoGreen;
    U32 *mHistoBlue;
    U32 *mHistoBrightness;
    
    // Vignette filtering
    EVignetteMode mVignetteMode;
    S32 mVignetteCenterX;
    S32 mVignetteCenterY;
    S32 mVignetteWidth;
    F32 mVignetteGamma;
    F32 mVignetteMin;
    
public:
	static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
	
	// Function for calculating the download priority for textures
	// <= 0 priority means that there's no need for more data.
	static F32 calc_download_priority(F32 virtual_size, F32 visible_area, S32 bytes_sent);

	static EImageCodec getCodecFromExtension(const std::string& exten);
	
	static void createPrivatePool() ;
	static void destroyPrivatePool() ;
	static LLPrivateMemoryPool* getPrivatePool() {return sPrivatePoolp;}

private:
	U8 *mData;
	S32 mDataSize;

	U16 mWidth;
	U16 mHeight;

	S8 mComponents;

	bool mBadBufferAllocation ;
	bool mAllowOverSize ;

	static LLPrivateMemoryPool* sPrivatePoolp ;
};

// Raw representation of an image (used for textures, and other uncompressed formats
class LLImageRaw : public LLImageBase
{
protected:
	/*virtual*/ ~LLImageRaw();
	
public:
	LLImageRaw();
	LLImageRaw(U16 width, U16 height, S8 components);
	LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy = false);
	// Construct using createFromFile (used by tools)
	//LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false);

	/*virtual*/ void deleteData();
	/*virtual*/ U8* allocateData(S32 size = -1);
	/*virtual*/ U8* reallocateData(S32 size);
	
	BOOL resize(U16 width, U16 height, S8 components);

	//U8 * getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const;
	BOOL setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
					 const U8 *data, U32 stride = 0, BOOL reverse_y = FALSE);

	void clear(U8 r=0, U8 g=0, U8 b=0, U8 a=255);

	void verticalFlip();

	void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
	void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
	void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
	BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE );
	
	// Fill the buffer with a constant color
	void fill( const LLColor4U& color );

	// Copy operations
	
	//duplicate this raw image if refCount > 1.
	LLPointer<LLImageRaw> duplicate();

	// Src and dst can be any size.  Src and dst can each have 3 or 4 components.
	void copy( LLImageRaw* src );

	// Src and dst are same size.  Src and dst have same number of components.
	void copyUnscaled( LLImageRaw* src );
	
	// Src and dst are same size.  Src has 4 components.  Dst has 3 components.
	void copyUnscaled4onto3( LLImageRaw* src );

	// Src and dst are same size.  Src has 3 components.  Dst has 4 components.
	void copyUnscaled3onto4( LLImageRaw* src );

	// Src and dst are same size.  Src has 1 component.  Dst has 4 components.
	// Alpha component is set to source alpha mask component.
	// RGB components are set to fill color.
	void copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill);

	// Src and dst can be any size.  Src and dst have same number of components.
	void copyScaled( LLImageRaw* src );

	// Src and dst can be any size.  Src has 3 components.  Dst has 4 components.
	void copyScaled3onto4( LLImageRaw* src );

	// Src and dst can be any size.  Src has 4 components.  Dst has 3 components.
	void copyScaled4onto3( LLImageRaw* src );


	// Composite operations

	// Src and dst can be any size.  Src and dst can each have 3 or 4 components.
	void composite( LLImageRaw* src );

	// Src and dst can be any size.  Src has 4 components.  Dst has 3 components.
	void compositeScaled4onto3( LLImageRaw* src );

	// Src and dst are same size.  Src has 4 components.  Dst has 3 components.
	void compositeUnscaled4onto3( LLImageRaw* src );
    
    // Filter Operations
    void filterGrayScale();                         // Convert to grayscale
    void filterSepia();                             // Convert to sepia
    void filterSaturate(F32 saturation);            // < 1.0 desaturates, > 1.0 saturates
    void filterRotate(F32 alpha);                   // Rotates hue according to alpha, alpha in degrees
    void filterGamma(F32 gamma);                    // Apply gamma to all channels
    void filterLinearize(F32 tail);                 // Use histogram to linearize constrast between min and max values minus tail
    void filterEqualize(S32 nb_classes);            // Use histogram to equalize constrast throughout the image
    void filterColorize(const LLColor4U& color);    // Colorize with color. Alpha will be taken into account for colorization intensity.
    void filterContrast(F32 slope);                 // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast
    void filterBrightness(S32 add);                 // Change brightness according to add: > 0 brighter, < 0 darker
    
    // Filter Primitives
    void colorTransform(const LLMatrix3 &transform);
    void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
    void setVignette(EVignetteMode mode, F32 gamma, F32 min);
    U32* getBrightnessHistogram();

protected:
	// Create an image from a local file (generally used in tools)
	//bool createFromFile(const std::string& filename, bool j2c_lowest_mip_only = false);

	void copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step );
	void compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len );

	U8	fastFractionalMult(U8 a,U8 b);

	void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;

    void computeHistograms();
    F32 getVignetteAlpha(S32 i, S32 j);

public:
	static S32 sGlobalRawMemory;
	static S32 sRawImageCount;
};

// Compressed representation of image.
// Subclass from this class for the different representations (J2C, bmp)
class LLImageFormatted : public LLImageBase
{
public:
	static LLImageFormatted* createFromType(S8 codec);
	static LLImageFormatted* createFromExtension(const std::string& instring);	

protected:
	/*virtual*/ ~LLImageFormatted();
	
public:
	LLImageFormatted(S8 codec);

	// LLImageBase
	/*virtual*/ void deleteData();
	/*virtual*/ U8* allocateData(S32 size = -1);
	/*virtual*/ U8* reallocateData(S32 size);
	
	/*virtual*/ void dump();
	/*virtual*/ void sanityCheck();

	// New methods
	// subclasses must return a prefered file extension (lowercase without a leading dot)
	virtual std::string getExtension() = 0;
	// calcHeaderSize() returns the maximum size of header;
	//   0 indicates we don't have a header and have to read the entire file
	virtual S32 calcHeaderSize() { return 0; };
	// calcDataSize() returns how many bytes to read to load discard_level (including header)
	virtual S32 calcDataSize(S32 discard_level);
	// calcDiscardLevelBytes() returns the smallest valid discard level based on the number of input bytes
	virtual S32 calcDiscardLevelBytes(S32 bytes);
	// getRawDiscardLevel() by default returns mDiscardLevel, but may be overridden (LLImageJ2C)
	virtual S8  getRawDiscardLevel() { return mDiscardLevel; }
	
	BOOL load(const std::string& filename, int load_size = 0);
	BOOL save(const std::string& filename);

	virtual BOOL updateData() = 0; // pure virtual
 	void setData(U8 *data, S32 size);
 	void appendData(U8 *data, S32 size);

	// Loads first 4 channels.
	virtual BOOL decode(LLImageRaw* raw_image, F32 decode_time) = 0;  
	// Subclasses that can handle more than 4 channels should override this function.
	virtual BOOL decodeChannels(LLImageRaw* raw_image, F32 decode_time, S32 first_channel, S32 max_channel);

	virtual BOOL encode(const LLImageRaw* raw_image, F32 encode_time) = 0;

	S8 getCodec() const;
	BOOL isDecoding() const { return mDecoding ? TRUE : FALSE; }
	BOOL isDecoded()  const { return mDecoded ? TRUE : FALSE; }
	void setDiscardLevel(S8 discard_level) { mDiscardLevel = discard_level; }
	S8 getDiscardLevel() const { return mDiscardLevel; }
	S8 getLevels() const { return mLevels; }
	void setLevels(S8 nlevels) { mLevels = nlevels; }

	// setLastError needs to be deferred for J2C images since it may be called from a DLL
	virtual void resetLastError();
	virtual void setLastError(const std::string& message, const std::string& filename = std::string());
	
protected:
	BOOL copyData(U8 *data, S32 size); // calls updateData()
	
protected:
	S8 mCodec;
	S8 mDecoding;
	S8 mDecoded;  // unused, but changing LLImage layout requires recompiling static Mac/Linux libs. 2009-01-30 JC
	S8 mDiscardLevel;	// Current resolution level worked on. 0 = full res, 1 = half res, 2 = quarter res, etc...
	S8 mLevels;			// Number of resolution levels in that image. Min is 1. 0 means unknown.
	
public:
	static S32 sGlobalFormattedMemory;
};

#endif