aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/CImage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CImage.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/source/Irrlicht/CImage.cpp462
1 files changed, 462 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CImage.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CImage.cpp
new file mode 100644
index 0000000..d567732
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CImage.cpp
@@ -0,0 +1,462 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#include "CImage.h"
6#include "irrString.h"
7#include "CColorConverter.h"
8#include "CBlit.h"
9
10namespace irr
11{
12namespace video
13{
14
15//! Constructor of empty image
16CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size)
17:Data(0), Size(size), Format(format), DeleteMemory(true)
18{
19 initData();
20}
21
22
23//! Constructor from raw data
24CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size, void* data,
25 bool ownForeignMemory, bool deleteForeignMemory)
26: Data(0), Size(size), Format(format), DeleteMemory(deleteForeignMemory)
27{
28 if (ownForeignMemory)
29 {
30 Data = (u8*)0xbadf00d;
31 initData();
32 Data = (u8*)data;
33 }
34 else
35 {
36 Data = 0;
37 initData();
38 memcpy(Data, data, Size.Height * Pitch);
39 }
40}
41
42
43//! assumes format and size has been set and creates the rest
44void CImage::initData()
45{
46#ifdef _DEBUG
47 setDebugName("CImage");
48#endif
49 BytesPerPixel = getBitsPerPixelFromFormat(Format) / 8;
50
51 // Pitch should be aligned...
52 Pitch = BytesPerPixel * Size.Width;
53
54 if (!Data)
55 {
56 DeleteMemory=true;
57 Data = new u8[Size.Height * Pitch];
58 }
59}
60
61
62//! destructor
63CImage::~CImage()
64{
65 if ( DeleteMemory )
66 delete [] Data;
67}
68
69
70//! Returns width and height of image data.
71const core::dimension2d<u32>& CImage::getDimension() const
72{
73 return Size;
74}
75
76
77//! Returns bits per pixel.
78u32 CImage::getBitsPerPixel() const
79{
80 return getBitsPerPixelFromFormat(Format);
81}
82
83
84//! Returns bytes per pixel
85u32 CImage::getBytesPerPixel() const
86{
87 return BytesPerPixel;
88}
89
90
91//! Returns image data size in bytes
92u32 CImage::getImageDataSizeInBytes() const
93{
94 return Pitch * Size.Height;
95}
96
97
98//! Returns image data size in pixels
99u32 CImage::getImageDataSizeInPixels() const
100{
101 return Size.Width * Size.Height;
102}
103
104
105//! returns mask for red value of a pixel
106u32 CImage::getRedMask() const
107{
108 switch(Format)
109 {
110 case ECF_A1R5G5B5:
111 return 0x1F<<10;
112 case ECF_R5G6B5:
113 return 0x1F<<11;
114 case ECF_R8G8B8:
115 return 0x00FF0000;
116 case ECF_A8R8G8B8:
117 return 0x00FF0000;
118 default:
119 return 0x0;
120 }
121}
122
123
124//! returns mask for green value of a pixel
125u32 CImage::getGreenMask() const
126{
127 switch(Format)
128 {
129 case ECF_A1R5G5B5:
130 return 0x1F<<5;
131 case ECF_R5G6B5:
132 return 0x3F<<5;
133 case ECF_R8G8B8:
134 return 0x0000FF00;
135 case ECF_A8R8G8B8:
136 return 0x0000FF00;
137 default:
138 return 0x0;
139 }
140}
141
142
143//! returns mask for blue value of a pixel
144u32 CImage::getBlueMask() const
145{
146 switch(Format)
147 {
148 case ECF_A1R5G5B5:
149 return 0x1F;
150 case ECF_R5G6B5:
151 return 0x1F;
152 case ECF_R8G8B8:
153 return 0x000000FF;
154 case ECF_A8R8G8B8:
155 return 0x000000FF;
156 default:
157 return 0x0;
158 }
159}
160
161
162//! returns mask for alpha value of a pixel
163u32 CImage::getAlphaMask() const
164{
165 switch(Format)
166 {
167 case ECF_A1R5G5B5:
168 return 0x1<<15;
169 case ECF_R5G6B5:
170 return 0x0;
171 case ECF_R8G8B8:
172 return 0x0;
173 case ECF_A8R8G8B8:
174 return 0xFF000000;
175 default:
176 return 0x0;
177 }
178}
179
180
181//! sets a pixel
182void CImage::setPixel(u32 x, u32 y, const SColor &color, bool blend)
183{
184 if (x >= Size.Width || y >= Size.Height)
185 return;
186
187 switch(Format)
188 {
189 case ECF_A1R5G5B5:
190 {
191 u16 * dest = (u16*) (Data + ( y * Pitch ) + ( x << 1 ));
192 *dest = video::A8R8G8B8toA1R5G5B5( color.color );
193 } break;
194
195 case ECF_R5G6B5:
196 {
197 u16 * dest = (u16*) (Data + ( y * Pitch ) + ( x << 1 ));
198 *dest = video::A8R8G8B8toR5G6B5( color.color );
199 } break;
200
201 case ECF_R8G8B8:
202 {
203 u8* dest = Data + ( y * Pitch ) + ( x * 3 );
204 dest[0] = (u8)color.getRed();
205 dest[1] = (u8)color.getGreen();
206 dest[2] = (u8)color.getBlue();
207 } break;
208
209 case ECF_A8R8G8B8:
210 {
211 u32 * dest = (u32*) (Data + ( y * Pitch ) + ( x << 2 ));
212 *dest = blend ? PixelBlend32 ( *dest, color.color ) : color.color;
213 } break;
214#ifndef _DEBUG
215 default:
216 break;
217#endif
218 }
219}
220
221
222//! returns a pixel
223SColor CImage::getPixel(u32 x, u32 y) const
224{
225 if (x >= Size.Width || y >= Size.Height)
226 return SColor(0);
227
228 switch(Format)
229 {
230 case ECF_A1R5G5B5:
231 return A1R5G5B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]);
232 case ECF_R5G6B5:
233 return R5G6B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]);
234 case ECF_A8R8G8B8:
235 return ((u32*)Data)[y*Size.Width + x];
236 case ECF_R8G8B8:
237 {
238 u8* p = Data+(y*3)*Size.Width + (x*3);
239 return SColor(255,p[0],p[1],p[2]);
240 }
241#ifndef _DEBUG
242 default:
243 break;
244#endif
245 }
246
247 return SColor(0);
248}
249
250
251//! returns the color format
252ECOLOR_FORMAT CImage::getColorFormat() const
253{
254 return Format;
255}
256
257
258//! copies this surface into another at given position
259void CImage::copyTo(IImage* target, const core::position2d<s32>& pos)
260{
261 Blit(BLITTER_TEXTURE, target, 0, &pos, this, 0, 0);
262}
263
264
265//! copies this surface partially into another at given position
266void CImage::copyTo(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect)
267{
268 Blit(BLITTER_TEXTURE, target, clipRect, &pos, this, &sourceRect, 0);
269}
270
271
272//! copies this surface into another, using the alpha mask, a cliprect and a color to add with
273void CImage::copyToWithAlpha(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const SColor &color, const core::rect<s32>* clipRect)
274{
275 // color blend only necessary on not full spectrum aka. color.color != 0xFFFFFFFF
276 Blit(color.color == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND: BLITTER_TEXTURE_ALPHA_COLOR_BLEND,
277 target, clipRect, &pos, this, &sourceRect, color.color);
278}
279
280
281//! copies this surface into another, scaling it to the target image size
282// note: this is very very slow.
283void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch)
284{
285 if (!target || !width || !height)
286 return;
287
288 const u32 bpp=getBitsPerPixelFromFormat(format)/8;
289 if (0==pitch)
290 pitch = width*bpp;
291
292 if (Format==format && Size.Width==width && Size.Height==height)
293 {
294 if (pitch==Pitch)
295 {
296 memcpy(target, Data, height*pitch);
297 return;
298 }
299 else
300 {
301 u8* tgtpos = (u8*) target;
302 u8* srcpos = Data;
303 const u32 bwidth = width*bpp;
304 const u32 rest = pitch-bwidth;
305 for (u32 y=0; y<height; ++y)
306 {
307 // copy scanline
308 memcpy(tgtpos, srcpos, bwidth);
309 // clear pitch
310 memset(tgtpos+bwidth, 0, rest);
311 tgtpos += pitch;
312 srcpos += Pitch;
313 }
314 return;
315 }
316 }
317
318 const f32 sourceXStep = (f32)Size.Width / (f32)width;
319 const f32 sourceYStep = (f32)Size.Height / (f32)height;
320 s32 yval=0, syval=0;
321 f32 sy = 0.0f;
322 for (u32 y=0; y<height; ++y)
323 {
324 f32 sx = 0.0f;
325 for (u32 x=0; x<width; ++x)
326 {
327 CColorConverter::convert_viaFormat(Data+ syval + ((s32)sx)*BytesPerPixel, Format, 1, ((u8*)target)+ yval + (x*bpp), format);
328 sx+=sourceXStep;
329 }
330 sy+=sourceYStep;
331 syval=((s32)sy)*Pitch;
332 yval+=pitch;
333 }
334}
335
336
337//! copies this surface into another, scaling it to the target image size
338// note: this is very very slow.
339void CImage::copyToScaling(IImage* target)
340{
341 if (!target)
342 return;
343
344 const core::dimension2d<u32>& targetSize = target->getDimension();
345
346 if (targetSize==Size)
347 {
348 copyTo(target);
349 return;
350 }
351
352 copyToScaling(target->lock(), targetSize.Width, targetSize.Height, target->getColorFormat());
353 target->unlock();
354}
355
356
357//! copies this surface into another, scaling it to fit it.
358void CImage::copyToScalingBoxFilter(IImage* target, s32 bias, bool blend)
359{
360 const core::dimension2d<u32> destSize = target->getDimension();
361
362 const f32 sourceXStep = (f32) Size.Width / (f32) destSize.Width;
363 const f32 sourceYStep = (f32) Size.Height / (f32) destSize.Height;
364
365 target->lock();
366
367 s32 fx = core::ceil32( sourceXStep );
368 s32 fy = core::ceil32( sourceYStep );
369 f32 sx;
370 f32 sy;
371
372 sy = 0.f;
373 for ( u32 y = 0; y != destSize.Height; ++y )
374 {
375 sx = 0.f;
376 for ( u32 x = 0; x != destSize.Width; ++x )
377 {
378 target->setPixel( x, y,
379 getPixelBox( core::floor32(sx), core::floor32(sy), fx, fy, bias ), blend );
380 sx += sourceXStep;
381 }
382 sy += sourceYStep;
383 }
384
385 target->unlock();
386}
387
388
389//! fills the surface with given color
390void CImage::fill(const SColor &color)
391{
392 u32 c;
393
394 switch ( Format )
395 {
396 case ECF_A1R5G5B5:
397 c = color.toA1R5G5B5();
398 c |= c << 16;
399 break;
400 case ECF_R5G6B5:
401 c = video::A8R8G8B8toR5G6B5( color.color );
402 c |= c << 16;
403 break;
404 case ECF_A8R8G8B8:
405 c = color.color;
406 break;
407 case ECF_R8G8B8:
408 {
409 u8 rgb[3];
410 CColorConverter::convert_A8R8G8B8toR8G8B8(&color, 1, rgb);
411 const u32 size = getImageDataSizeInBytes();
412 for (u32 i=0; i<size; i+=3)
413 {
414 memcpy(Data+i, rgb, 3);
415 }
416 return;
417 }
418 break;
419 default:
420 // TODO: Handle other formats
421 return;
422 }
423 memset32( Data, c, getImageDataSizeInBytes() );
424}
425
426
427//! get a filtered pixel
428inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const
429{
430 SColor c;
431 s32 a = 0, r = 0, g = 0, b = 0;
432
433 for ( s32 dx = 0; dx != fx; ++dx )
434 {
435 for ( s32 dy = 0; dy != fy; ++dy )
436 {
437 c = getPixel( core::s32_min ( x + dx, Size.Width - 1 ) ,
438 core::s32_min ( y + dy, Size.Height - 1 )
439 );
440
441 a += c.getAlpha();
442 r += c.getRed();
443 g += c.getGreen();
444 b += c.getBlue();
445 }
446
447 }
448
449 s32 sdiv = s32_log2_s32(fx * fy);
450
451 a = core::s32_clamp( ( a >> sdiv ) + bias, 0, 255 );
452 r = core::s32_clamp( ( r >> sdiv ) + bias, 0, 255 );
453 g = core::s32_clamp( ( g >> sdiv ) + bias, 0, 255 );
454 b = core::s32_clamp( ( b >> sdiv ) + bias, 0, 255 );
455
456 c.set( a, r, g, b );
457 return c;
458}
459
460
461} // end namespace video
462} // end namespace irr