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