1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #include "CColorConverter.h"
\r
8 #include "irrString.h"
\r
15 //! converts a monochrome bitmap to A1R5G5B5 data
\r
16 void CColorConverter::convert1BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, s32 linepad, bool flip)
\r
22 out += width * height;
\r
24 for (s32 y=0; y<height; ++y)
\r
30 for (s32 x=0; x<width; ++x)
\r
32 out[x] = *in>>shift & 0x01 ? (s16)0xffff : (s16)0x8000;
\r
34 if ((--shift)<0) // 8 pixel done
\r
41 if (shift != 7) // width did not fill last byte
\r
52 //! converts a 4 bit palettized image to A1R5G5B5
\r
53 void CColorConverter::convert4BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad, bool flip)
\r
55 if (!in || !out || !palette)
\r
59 out += width*height;
\r
61 for (s32 y=0; y<height; ++y)
\r
67 for (s32 x=0; x<width; ++x)
\r
69 out[x] = X8R8G8B8toA1R5G5B5(palette[(u8)((*in >> shift) & 0xf)]);
\r
80 if (shift == 0) // odd width
\r
91 //! converts a 8 bit palettized image into A1R5G5B5
\r
92 void CColorConverter::convert8BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad, bool flip)
\r
94 if (!in || !out || !palette)
\r
98 out += width * height;
\r
100 for (s32 y=0; y<height; ++y)
\r
103 out -= width; // one line back
\r
104 for (s32 x=0; x<width; ++x)
\r
106 out[x] = X8R8G8B8toA1R5G5B5(palette[(u8)(*in)]);
\r
115 //! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
\r
116 void CColorConverter::convert8BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad, bool flip)
\r
121 const s32 lineWidth = 3 * width;
\r
123 out += lineWidth * height;
\r
125 for (s32 y=0; y<height; ++y)
\r
128 out -= lineWidth; // one line back
\r
129 for (s32 x=0; x< lineWidth; x += 3)
\r
133 #ifdef __BIG_ENDIAN__
\r
134 out[x+0] = palette[ (in[0] << 2 ) + 0];
\r
135 out[x+1] = palette[ (in[0] << 2 ) + 1];
\r
136 out[x+2] = palette[ (in[0] << 2 ) + 2];
\r
138 out[x+0] = palette[ (in[0] << 2 ) + 2];
\r
139 out[x+1] = palette[ (in[0] << 2 ) + 1];
\r
140 out[x+2] = palette[ (in[0] << 2 ) + 0];
\r
157 //! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
\r
158 void CColorConverter::convert8BitTo32Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad, bool flip)
\r
163 const u32 lineWidth = 4 * width;
\r
165 out += lineWidth * height;
\r
169 for (u32 y=0; y < (u32) height; ++y)
\r
172 out -= lineWidth; // one line back
\r
176 for (x=0; x < (u32) width; x += 1)
\r
179 ((u32*)out)[x] = ((u32*)palette)[ c ];
\r
184 for (x=0; x < (u32) width; x += 1)
\r
187 #ifdef __BIG_ENDIAN__
\r
188 ((u32*)out)[x] = c << 24 | c << 16 | c << 8 | 0x000000FF;
\r
190 ((u32*)out)[x] = 0xFF000000 | c << 16 | c << 8 | c;
\r
198 in += width + linepad;
\r
204 //! converts 16bit data to 16bit data
\r
205 void CColorConverter::convert16BitTo16Bit(const s16* in, s16* out, s32 width, s32 height, s32 linepad, bool flip)
\r
211 out += width * height;
\r
213 for (s32 y=0; y<height; ++y)
\r
217 #ifdef __BIG_ENDIAN__
\r
218 for (s32 x=0; x<width; ++x)
\r
219 out[x]=os::Byteswap::byteswap(in[x]);
\r
221 memcpy(out, in, width*sizeof(s16));
\r
232 //! copies R8G8B8 24bit data to 24bit data
\r
233 void CColorConverter::convert24BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, s32 linepad, bool flip, bool bgr)
\r
238 const s32 lineWidth = 3 * width;
\r
240 out += lineWidth * height;
\r
242 for (s32 y=0; y<height; ++y)
\r
248 for (s32 x=0; x<lineWidth; x+=3)
\r
250 out[x+0] = in[x+2];
\r
251 out[x+1] = in[x+1];
\r
252 out[x+2] = in[x+0];
\r
257 memcpy(out,in,lineWidth);
\r
268 //! Resizes the surface to a new size and converts it at the same time
\r
269 //! to an A8R8G8B8 format, returning the pointer to the new buffer.
\r
270 void CColorConverter::convert16bitToA8R8G8B8andResize(const s16* in, s32* out, s32 newWidth, s32 newHeight, s32 currentWidth, s32 currentHeight)
\r
272 if (!newWidth || !newHeight)
\r
275 // note: this is very very slow. (i didn't want to write a fast version.
\r
276 // but hopefully, nobody wants to convert surfaces every frame.
\r
278 f32 sourceXStep = (f32)currentWidth / (f32)newWidth;
\r
279 f32 sourceYStep = (f32)currentHeight / (f32)newHeight;
\r
283 for (s32 x=0; x<newWidth; ++x)
\r
287 for (s32 y=0; y<newHeight; ++y)
\r
289 t = in[(s32)(((s32)sy)*currentWidth + x*sourceXStep)];
\r
290 t = (((t >> 15)&0x1)<<31) | (((t >> 10)&0x1F)<<19) |
\r
291 (((t >> 5)&0x1F)<<11) | (t&0x1F)<<3;
\r
292 out[(s32)(y*newWidth + x)] = t;
\r
301 //! copies X8R8G8B8 32 bit data
\r
302 void CColorConverter::convert32BitTo32Bit(const s32* in, s32* out, s32 width, s32 height, s32 linepad, bool flip)
\r
308 out += width * height;
\r
310 for (s32 y=0; y<height; ++y)
\r
314 #ifdef __BIG_ENDIAN__
\r
315 for (s32 x=0; x<width; ++x)
\r
316 out[x]=os::Byteswap::byteswap(in[x]);
\r
318 memcpy(out, in, width*sizeof(s32));
\r
329 void CColorConverter::convert_A1R5G5B5toR8G8B8(const void* sP, s32 sN, void* dP)
\r
331 u16* sB = (u16*)sP;
\r
332 u8 * dB = (u8 *)dP;
\r
334 for (s32 x = 0; x < sN; ++x)
\r
336 dB[2] = (*sB & 0x7c00) >> 7;
\r
337 dB[1] = (*sB & 0x03e0) >> 2;
\r
338 dB[0] = (*sB & 0x1f) << 3;
\r
345 void CColorConverter::convert_A1R5G5B5toB8G8R8(const void* sP, s32 sN, void* dP)
\r
347 u16* sB = (u16*)sP;
\r
348 u8 * dB = (u8 *)dP;
\r
350 for (s32 x = 0; x < sN; ++x)
\r
352 dB[0] = (*sB & 0x7c00) >> 7;
\r
353 dB[1] = (*sB & 0x03e0) >> 2;
\r
354 dB[2] = (*sB & 0x1f) << 3;
\r
361 void CColorConverter::convert_A1R5G5B5toR5G5B5A1(const void* sP, s32 sN, void* dP)
\r
363 const u16* sB = (const u16*)sP;
\r
364 u16* dB = (u16*)dP;
\r
366 for (s32 x = 0; x < sN; ++x)
\r
368 *dB = (*sB<<1)|(*sB>>15);
\r
373 void CColorConverter::convert_A1R5G5B5toA8R8G8B8(const void* sP, s32 sN, void* dP)
\r
375 u16* sB = (u16*)sP;
\r
376 u32* dB = (u32*)dP;
\r
378 for (s32 x = 0; x < sN; ++x)
\r
379 *dB++ = A1R5G5B5toA8R8G8B8(*sB++);
\r
382 void CColorConverter::convert_A1R5G5B5toA1R5G5B5(const void* sP, s32 sN, void* dP)
\r
384 memcpy(dP, sP, sN * 2);
\r
387 void CColorConverter::convert_A1R5G5B5toR5G6B5(const void* sP, s32 sN, void* dP)
\r
389 u16* sB = (u16*)sP;
\r
390 u16* dB = (u16*)dP;
\r
392 for (s32 x = 0; x < sN; ++x)
\r
393 *dB++ = A1R5G5B5toR5G6B5(*sB++);
\r
396 void CColorConverter::convert_A8R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP)
\r
401 for (s32 x = 0; x < sN; ++x)
\r
413 void CColorConverter::convert_A8R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP)
\r
418 for (s32 x = 0; x < sN; ++x)
\r
430 void CColorConverter::convert_A8R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP)
\r
432 memcpy(dP, sP, sN * 4);
\r
435 void CColorConverter::convert_A8R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP)
\r
437 u32* sB = (u32*)sP;
\r
438 u16* dB = (u16*)dP;
\r
440 for (s32 x = 0; x < sN; ++x)
\r
441 *dB++ = A8R8G8B8toA1R5G5B5(*sB++);
\r
444 void CColorConverter::convert_A8R8G8B8toA1B5G5R5(const void* sP, s32 sN, void* dP)
\r
446 u8 * sB = (u8 *)sP;
\r
447 u16* dB = (u16*)dP;
\r
449 for (s32 x = 0; x < sN; ++x)
\r
451 s32 r = sB[0] >> 3;
\r
452 s32 g = sB[1] >> 3;
\r
453 s32 b = sB[2] >> 3;
\r
454 s32 a = sB[3] >> 3;
\r
456 dB[0] = (a << 15) | (r << 10) | (g << 5) | (b);
\r
463 void CColorConverter::convert_A8R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP)
\r
465 u8 * sB = (u8 *)sP;
\r
466 u16* dB = (u16*)dP;
\r
468 for (s32 x = 0; x < sN; ++x)
\r
470 s32 r = sB[2] >> 3;
\r
471 s32 g = sB[1] >> 2;
\r
472 s32 b = sB[0] >> 3;
\r
474 dB[0] = (r << 11) | (g << 5) | (b);
\r
481 void CColorConverter::convert_A8R8G8B8toR3G3B2(const void* sP, s32 sN, void* dP)
\r
486 for (s32 x = 0; x < sN; ++x)
\r
488 u8 r = sB[2] & 0xe0;
\r
489 u8 g = (sB[1] & 0xe0) >> 3;
\r
490 u8 b = (sB[0] & 0xc0) >> 6;
\r
492 dB[0] = (r | g | b);
\r
499 void CColorConverter::convert_R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP)
\r
501 memcpy(dP, sP, sN * 3);
\r
504 void CColorConverter::convert_R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP)
\r
507 u32* dB = (u32*)dP;
\r
509 for (s32 x = 0; x < sN; ++x)
\r
511 *dB = 0xff000000 | (sB[0]<<16) | (sB[1]<<8) | sB[2];
\r
518 void CColorConverter::convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP)
\r
520 u8 * sB = (u8 *)sP;
\r
521 u16* dB = (u16*)dP;
\r
523 for (s32 x = 0; x < sN; ++x)
\r
525 s32 r = sB[0] >> 3;
\r
526 s32 g = sB[1] >> 3;
\r
527 s32 b = sB[2] >> 3;
\r
529 dB[0] = (0x8000) | (r << 10) | (g << 5) | (b);
\r
536 void CColorConverter::convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP)
\r
539 u32* dB = (u32*)dP;
\r
541 for (s32 x = 0; x < sN; ++x)
\r
543 *dB = 0xff000000 | (sB[2]<<16) | (sB[1]<<8) | sB[0];
\r
550 void CColorConverter::convert_A8R8G8B8toR8G8B8A8(const void* sP, s32 sN, void* dP)
\r
552 const u32* sB = (const u32*)sP;
\r
553 u32* dB = (u32*)dP;
\r
555 for (s32 x = 0; x < sN; ++x)
\r
557 *dB++ = (*sB<<8) | (*sB>>24);
\r
562 void CColorConverter::convert_A8R8G8B8toA8B8G8R8(const void* sP, s32 sN, void* dP)
\r
564 const u32* sB = (const u32*)sP;
\r
565 u32* dB = (u32*)dP;
\r
567 for (s32 x = 0; x < sN; ++x)
\r
569 *dB++ = (*sB&0xff00ff00)|((*sB&0x00ff0000)>>16)|((*sB&0x000000ff)<<16);
\r
574 void CColorConverter::convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP)
\r
579 for (s32 x = 0; x < sN; ++x)
\r
592 void CColorConverter::convert_R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP)
\r
597 for (s32 x = 0; x < sN; ++x)
\r
608 void CColorConverter::convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP)
\r
610 u8 * sB = (u8 *)sP;
\r
611 u16* dB = (u16*)dP;
\r
613 for (s32 x = 0; x < sN; ++x)
\r
615 s32 r = sB[0] >> 3;
\r
616 s32 g = sB[1] >> 2;
\r
617 s32 b = sB[2] >> 3;
\r
619 dB[0] = (r << 11) | (g << 5) | (b);
\r
626 void CColorConverter::convert_R5G6B5toR5G6B5(const void* sP, s32 sN, void* dP)
\r
628 memcpy(dP, sP, sN * 2);
\r
631 void CColorConverter::convert_R5G6B5toR8G8B8(const void* sP, s32 sN, void* dP)
\r
633 u16* sB = (u16*)sP;
\r
634 u8 * dB = (u8 *)dP;
\r
636 for (s32 x = 0; x < sN; ++x)
\r
638 dB[0] = (*sB & 0xf800) >> 8;
\r
639 dB[1] = (*sB & 0x07e0) >> 3;
\r
640 dB[2] = (*sB & 0x001f) << 3;
\r
647 void CColorConverter::convert_R5G6B5toB8G8R8(const void* sP, s32 sN, void* dP)
\r
649 u16* sB = (u16*)sP;
\r
650 u8 * dB = (u8 *)dP;
\r
652 for (s32 x = 0; x < sN; ++x)
\r
654 dB[2] = (*sB & 0xf800) >> 8;
\r
655 dB[1] = (*sB & 0x07e0) >> 3;
\r
656 dB[0] = (*sB & 0x001f) << 3;
\r
663 void CColorConverter::convert_R5G6B5toA8R8G8B8(const void* sP, s32 sN, void* dP)
\r
665 u16* sB = (u16*)sP;
\r
666 u32* dB = (u32*)dP;
\r
668 for (s32 x = 0; x < sN; ++x)
\r
669 *dB++ = R5G6B5toA8R8G8B8(*sB++);
\r
672 void CColorConverter::convert_R5G6B5toA1R5G5B5(const void* sP, s32 sN, void* dP)
\r
674 u16* sB = (u16*)sP;
\r
675 u16* dB = (u16*)dP;
\r
677 for (s32 x = 0; x < sN; ++x)
\r
678 *dB++ = R5G6B5toA1R5G5B5(*sB++);
\r
681 bool CColorConverter::canConvertFormat(ECOLOR_FORMAT sourceFormat, ECOLOR_FORMAT destFormat)
\r
683 switch (sourceFormat)
\r
686 switch (destFormat)
\r
698 switch (destFormat)
\r
710 switch (destFormat)
\r
722 switch (destFormat)
\r
739 void CColorConverter::convert_viaFormat(const void* sP, ECOLOR_FORMAT sF, s32 sN,
\r
740 void* dP, ECOLOR_FORMAT dF)
\r
742 // please also update can_convert_viaFormat when adding new conversions
\r
749 convert_A1R5G5B5toA1R5G5B5(sP, sN, dP);
\r
752 convert_A1R5G5B5toR5G6B5(sP, sN, dP);
\r
755 convert_A1R5G5B5toA8R8G8B8(sP, sN, dP);
\r
758 convert_A1R5G5B5toR8G8B8(sP, sN, dP);
\r
760 IRR_CASE_IIMAGE_COMPRESSED_FORMAT
\r
761 os::Printer::log("CColorConverter::convert_viaFormat method doesn't support compressed images.", ELL_WARNING);
\r
772 convert_R5G6B5toA1R5G5B5(sP, sN, dP);
\r
775 convert_R5G6B5toR5G6B5(sP, sN, dP);
\r
778 convert_R5G6B5toA8R8G8B8(sP, sN, dP);
\r
781 convert_R5G6B5toR8G8B8(sP, sN, dP);
\r
783 IRR_CASE_IIMAGE_COMPRESSED_FORMAT
\r
784 os::Printer::log("CColorConverter::convert_viaFormat method doesn't support compressed images.", ELL_WARNING);
\r
795 convert_A8R8G8B8toA1R5G5B5(sP, sN, dP);
\r
798 convert_A8R8G8B8toR5G6B5(sP, sN, dP);
\r
801 convert_A8R8G8B8toA8R8G8B8(sP, sN, dP);
\r
804 convert_A8R8G8B8toR8G8B8(sP, sN, dP);
\r
806 IRR_CASE_IIMAGE_COMPRESSED_FORMAT
\r
807 os::Printer::log("CColorConverter::convert_viaFormat method doesn't support compressed images.", ELL_WARNING);
\r
818 convert_R8G8B8toA1R5G5B5(sP, sN, dP);
\r
821 convert_R8G8B8toR5G6B5(sP, sN, dP);
\r
824 convert_R8G8B8toA8R8G8B8(sP, sN, dP);
\r
827 convert_R8G8B8toR8G8B8(sP, sN, dP);
\r
829 IRR_CASE_IIMAGE_COMPRESSED_FORMAT
\r
830 os::Printer::log("CColorConverter::convert_viaFormat method doesn't support compressed images.", ELL_WARNING);
\r
837 IRR_CASE_IIMAGE_COMPRESSED_FORMAT
\r
838 os::Printer::log("CColorConverter::convert_viaFormat method doesn't support compressed images.", ELL_WARNING);
\r
847 } // end namespace video
\r
848 } // end namespace irr
\r