1 #ifndef _IMAGE_H_
2 #define _IMAGE_H_
3
4 #include "base.h"
5 #include "Rect.h"
6 #include "Log.h"
7 #include "SmartPtr.h"
8 #include "AlignedBuffer.h"
9
10 #ifdef LINUX_GNU
11 #include <sys/endian.h>
12 #if __BYTE_ORDER == __LITTLE_ENDIAN
13 #define __LITTLE_ENDIAN__ __LITTLE_ENDIAN
14 #undef __BIG_ENDIAN__
15 #else
16 #undef __LITTLE_ENDIAN__
17 #define __BIG_ENDIAN__ __BIG_ENDIAN
18 #endif
19 #endif
20
21 namespace DisplayOutput
22 {
23
24 /*
25 The imageformats are NOT flexible or changeable!
26 If they are for some reason changed in any way, it¥s extremely important that the renderers conversion-tables are uptodate!
27 */
28
29 enum eImageFormat {
30
31 eImage_None = 0,
32
33 // Plain formats.
34 eImage_I8,
35 eImage_IA8,
36 eImage_RGB8,
37 eImage_RGBA8,
38
39 eImage_I16,
40 eImage_RG16,
41 eImage_RGB16,
42 eImage_RGBA16,
43
44 eImage_I16F,
45 eImage_RG16F,
46 eImage_RGB16F,
47 eImage_RGBA16F,
48
49 eImage_I32F,
50 eImage_RG32F,
51 eImage_RGB32F,
52 eImage_RGBA32F,
53
54 // Packed formats.
55 eImage_RGBA4,
56 eImage_RGB565,
57
58 // Compressed formats.
59 eImage_DXT1,
60 eImage_DXT3,
61 eImage_DXT5,
62
63 // Depth formats.
64 eImage_D16,
65 eImage_D24,
66 };
67
68
69 enum eScaleFilters {
70 eImage_Nearest = 0,
71 eImage_Bilinear,
72 eImage_Bicubic,
73 };
74
75 /*
76 */
77 class CImageFormat {
78
79 public:
80 eImageFormat m_Format;
81
CImageFormat()82 CImageFormat() : m_Format( eImage_None ) {};
CImageFormat(eImageFormat _format)83 CImageFormat( eImageFormat _format ) : m_Format( _format ) {};
CImageFormat(const CImageFormat & _image)84 CImageFormat( const CImageFormat &_image ) : m_Format( _image.m_Format ) {};
85
86 //
GetDescription(void)87 inline std::string GetDescription( void ) const
88 {
89 std::string desc = "";
90
91 switch( m_Format )
92 {
93 case eImage_I8: desc = "I8"; break;
94 case eImage_I16: desc = "I16"; break;
95 case eImage_I16F: desc = "I16F"; break;
96 case eImage_I32F: desc = "I32F"; break;
97 case eImage_D16: desc = "D16"; break;
98 case eImage_D24: desc = "D24"; break;
99 case eImage_IA8: desc = "IA8"; break;
100 case eImage_RG16: desc = "RG16"; break;
101 case eImage_RG16F: desc = "RG16F"; break;
102 case eImage_RG32F: desc = "RG32F"; break;
103 case eImage_RGB8: desc = "RGB8"; break;
104 case eImage_RGB16: desc = "RGB16"; break;
105 case eImage_RGB16F: desc = "RGB16F"; break;
106 case eImage_RGB32F: desc = "RGB32F"; break;
107 case eImage_RGBA4: desc = "RGBA4"; break;
108 case eImage_RGB565: desc = "RGB565"; break;
109 case eImage_DXT1: desc = "DXT1"; break;
110 case eImage_RGBA8: desc = "RGBA8"; break;
111 case eImage_RGBA16: desc = "RGBA16"; break;
112 case eImage_RGBA16F: desc = "RGBA16F"; break;
113 case eImage_RGBA32F: desc = "RGBA32F"; break;
114 case eImage_DXT3: desc = "DXT3"; break;
115 case eImage_DXT5: desc = "DXT5"; break;
116 default:
117 desc = "Unknown"; break;
118 }
119
120 return( desc );
121 }
122
123 //
GetChannels(void)124 inline uint32 GetChannels( void ) const
125 {
126 switch( m_Format )
127 {
128 case eImage_I8:
129 case eImage_I16:
130 case eImage_I16F:
131 case eImage_I32F:
132 case eImage_D16:
133 case eImage_D24:
134 return( 1 );
135 case eImage_IA8:
136 case eImage_RG16:
137 case eImage_RG16F:
138 case eImage_RG32F:
139 case eImage_RGBA4:
140 return( 2 );
141 case eImage_RGB8:
142 case eImage_RGB16:
143 case eImage_RGB16F:
144 case eImage_RGB32F:
145 case eImage_RGB565:
146 case eImage_DXT1:
147 return( 3 );
148 case eImage_RGBA8:
149 case eImage_RGBA16:
150 case eImage_RGBA16F:
151 case eImage_RGBA32F:
152 case eImage_DXT3:
153 case eImage_DXT5:
154 return( 4 );
155 default:
156 g_Log->Error( "CImageFormat::GetChannels = fubar" );
157 return( 0 );
158 }
159 }
160
161 // Bytes per block.
getBPBlock(void)162 inline uint32 getBPBlock( void ) const
163 {
164 return( (m_Format == eImage_DXT1 ) ? 8 : 16 );
165 }
166
167 // Bytes per pixel.
getBPPixel(void)168 inline uint32 getBPPixel( void ) const
169 {
170 switch( m_Format )
171 {
172 case eImage_I8:
173 return( 1 );
174 case eImage_IA8:
175 case eImage_I16:
176 case eImage_I16F:
177 case eImage_RGB565:
178 case eImage_D16:
179 case eImage_RGBA4:
180 return( 2 );
181 case eImage_RGB8:
182 case eImage_D24:
183 return( 3 );
184 case eImage_RGBA8:
185 case eImage_RG16:
186 case eImage_RG16F:
187 case eImage_I32F:
188 return( 4 );
189 case eImage_RGB16:
190 case eImage_RGB16F:
191 return( 6 );
192 case eImage_RG32F:
193 return( 8 );
194 case eImage_RGBA16:
195 case eImage_RGBA16F:
196 case eImage_RGB32F:
197 return( 12 );
198 case eImage_RGBA32F:
199 return( 16 );
200 default:
201 return(0);
202 }
203 }
204
205 //
is(const eImageFormat _format)206 inline bool is( const eImageFormat _format ) const { return( m_Format == _format ); };
207
getFormatEnum(void)208 inline eImageFormat getFormatEnum( void ) const { return( m_Format ); }
209
isPlain(void)210 inline bool isPlain( void ) const { return( m_Format <= eImage_RGBA32F ); }
isPacked(void)211 inline bool isPacked( void ) const { return( m_Format == eImage_RGB565 ); }
isCompressed(void)212 inline bool isCompressed(void) const { return( (m_Format >= eImage_DXT1) && ( m_Format <= eImage_DXT5 ) ); }
isFloat(void)213 inline bool isFloat(void) const { return( (m_Format >= eImage_I16F) && ( m_Format <= eImage_RGBA32F) ); }
isDepth(void)214 inline bool isDepth(void) const { return( (m_Format >= eImage_D16) && (m_Format <= eImage_D24) ); }
215 };
216
217 MakeSmartPointers( CImageFormat );
218
219
220 //
flipChannels(uint8 * _pData,uint32 _nPixels,const uint32 _nChannels)221 inline void flipChannels( uint8 *_pData, uint32 _nPixels, const uint32 _nChannels )
222 {
223 uint8 tmp;
224
225 do {
226 tmp = _pData[_nChannels - 1];
227
228 for ( uint32 i = _nChannels - 1; i > 0; i-- )
229 {
230 _pData[i] = _pData[i - 1];
231 }
232
233 _pData[0] = tmp;
234
235 _pData += _nChannels;
236 } while (--_nPixels);
237 }
238
flipChannelsRB(uint8 * _pData,uint32 _nPixels,const uint32 _nChannels)239 inline void flipChannelsRB( uint8 *_pData, uint32 _nPixels, const uint32 _nChannels )
240 {
241 uint8 tmp;
242
243 do {
244 tmp = _pData[0];
245 _pData[0] = _pData[2];
246 _pData[2] = tmp;
247 _pData += _nChannels;
248 } while (--_nPixels);
249 }
250
251 #if (defined(MAC) || defined(LINUX_GNU))
252 #ifdef __LITTLE_ENDIAN__
253 #define MCHAR4(a, b, c, d) (a | (b << 8) | (c << 16) | (d << 24))
254 #else
255 #define MCHAR4(a, b, c, d) (d | (c << 8) | (b << 16) | (a << 24))
256 #endif
257 #else
258 #define MCHAR4(a, b, c, d) (a | (b << 8) | (c << 16) | (d << 24))
259 #endif
260
261 #define MAX_MIPMAP (sizeof(uint32) * 8)
262
263 /*
264 CImage.
265 Image class.
266 */
267 class CImage {
268
269 uint32 getNumberOfMipMapsFromDimesions( void ) const;
270 uint32 getMipMappedSize( const uint32 _firstMipMapLevel, const uint32 _nMipMapLevels, const CImageFormat &_format ) const;
271 uint32 getNumPixels( const uint32 _firstMipMapLevel, const uint32 _nMipMapLevels ) const;
272 bool createMipMaps( void );
273
274 // Image loaders.
275 bool LoadDDS( const std::string &_fileName, const bool _wantMipMaps = true );
276 //bool LoadTGA( const std::string &_fileName, const bool _wantMipMaps = true );
277 bool LoadPNG( const std::string &_fileName, const bool _wantMipMaps = true );
278 //bool LoadJPG( const std::string &_fileName, const bool _wantMipMaps = true );
279
280 // Image savers.
281 bool SaveDDS( const std::string &_fileName );
282
283 protected:
284
285 CImageFormat m_Format;
286
287 Base::spCAlignedBuffer m_spData;
288
289 uint32 m_Width;
290 uint32 m_Height;
291
292 uint32 m_nMipMaps;
293
294 bool m_bRef;
295
296 public:
297 CImage();
298 ~CImage();
299
300 //
301 void Create( const uint32 _w, const uint32 _h, const eImageFormat _format, const bool _bMipmaps = false, const bool _bRef = false );
302 void Copy( const CImage &_image, const uint32 _mipLevel );
303
304 bool Load( const std::string &_filename, const bool _calcMimaps = true );
305 bool Save( const std::string &_filename );
306
GetStorageBuffer(void)307 Base::spCAlignedBuffer& GetStorageBuffer( void ) { return m_spData; }
SetStorageBuffer(Base::spCAlignedBuffer & buffer)308 void SetStorageBuffer( Base::spCAlignedBuffer &buffer ) { m_spData = buffer; }
309
310 uint8 *GetData( const uint32 _mipLevel ) const;
311 void SetData( uint8 *_pData );
312
313 uint32 GetPitch( const uint32 _mipMapLevel = 0 ) const;
314
315 //
316 bool Scale( const uint32 _newWidth, const uint32 _newHeight, const eScaleFilters _eFilter );
317 bool Convert( const eImageFormat _newFormat );
318
319 //
320 bool GenerateMipmaps( void );
321
322 //
isReference(void)323 inline bool isReference( void ) const { return( m_bRef ); };
324 inline uint32 GetWidth( const uint32 _mipMapLevel = 0 ) const { uint32 a = m_Width >> _mipMapLevel; return( (a == 0)? 1 : a ); }
325 inline uint32 GetHeight( const uint32 _mipMapLevel = 0 ) const { uint32 a = m_Height >> _mipMapLevel; return( (a == 0)? 1 : a ); }
GetRect(void)326 inline Base::Math::CRect GetRect( void ) const { return( Base::Math::CRect( (fp4)m_Width, (fp4)m_Height ) ); };
GetNumMipMaps(void)327 inline uint32 GetNumMipMaps( void ) const { return( m_nMipMaps ); };
328 uint32 getMipMappedSize( const uint32 _firstMipMapLevel = 0, const uint32 _nMipMapLevels = 0x7FFFFFFF ) const;
GetFormat(void)329 inline const CImageFormat &GetFormat( void ) const { return( m_Format ); };
330
331 //
332 void GetPixel( const int32 _x, const int32 _y, fp4 &_r, fp4 &_g, fp4 &_b, fp4 &_a );
333 void PutPixel( const int32 _x, const int32 _y, const fp4 _r, const fp4 _g, const fp4 _b, const fp4 _a );
334 };
335
336 MakeSmartPointers( CImage );
337
338 };
339
340 #endif
341