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