2023-10-03 20:37:00 +02:00
|
|
|
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
|
|
|
// This file is part of the "Irrlicht Engine".
|
|
|
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
|
|
|
|
|
|
|
#include "CColorConverter.h"
|
|
|
|
#include "SColor.h"
|
|
|
|
#include "os.h"
|
|
|
|
#include "irrString.h"
|
|
|
|
|
|
|
|
namespace irr
|
|
|
|
{
|
|
|
|
namespace video
|
|
|
|
{
|
|
|
|
|
|
|
|
//! converts a monochrome bitmap to A1R5G5B5 data
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert1BitTo16Bit(const u8 *in, s16 *out, s32 width, s32 height, s32 linepad, bool flip)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
|
|
|
if (!in || !out)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (flip)
|
|
|
|
out += width * height;
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 y = 0; y < height; ++y) {
|
2023-10-03 20:37:00 +02:00
|
|
|
s32 shift = 7;
|
|
|
|
if (flip)
|
|
|
|
out -= width;
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < width; ++x) {
|
|
|
|
out[x] = *in >> shift & 0x01 ? (s16)0xffff : (s16)0x8000;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2023-10-04 20:10:58 +02:00
|
|
|
if ((--shift) < 0) { // 8 pixel done
|
2024-03-20 19:35:52 +01:00
|
|
|
shift = 7;
|
2023-10-03 20:37:00 +02:00
|
|
|
++in;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shift != 7) // width did not fill last byte
|
|
|
|
++in;
|
|
|
|
|
|
|
|
if (!flip)
|
|
|
|
out += width;
|
|
|
|
in += linepad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! converts a 4 bit palettized image to A1R5G5B5
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert4BitTo16Bit(const u8 *in, s16 *out, s32 width, s32 height, const s32 *palette, s32 linepad, bool flip)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
|
|
|
if (!in || !out || !palette)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (flip)
|
2024-03-20 19:35:52 +01:00
|
|
|
out += width * height;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 y = 0; y < height; ++y) {
|
2023-10-03 20:37:00 +02:00
|
|
|
s32 shift = 4;
|
|
|
|
if (flip)
|
|
|
|
out -= width;
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < width; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
out[x] = X8R8G8B8toA1R5G5B5(palette[(u8)((*in >> shift) & 0xf)]);
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
if (shift == 0) {
|
2023-10-03 20:37:00 +02:00
|
|
|
shift = 4;
|
|
|
|
++in;
|
2024-03-20 19:35:52 +01:00
|
|
|
} else
|
2023-10-03 20:37:00 +02:00
|
|
|
shift = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shift == 0) // odd width
|
|
|
|
++in;
|
|
|
|
|
|
|
|
if (!flip)
|
|
|
|
out += width;
|
|
|
|
in += linepad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! converts a 8 bit palettized image into A1R5G5B5
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert8BitTo16Bit(const u8 *in, s16 *out, s32 width, s32 height, const s32 *palette, s32 linepad, bool flip)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
|
|
|
if (!in || !out || !palette)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (flip)
|
|
|
|
out += width * height;
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 y = 0; y < height; ++y) {
|
2023-10-03 20:37:00 +02:00
|
|
|
if (flip)
|
|
|
|
out -= width; // one line back
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < width; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
out[x] = X8R8G8B8toA1R5G5B5(palette[(u8)(*in)]);
|
|
|
|
++in;
|
|
|
|
}
|
|
|
|
if (!flip)
|
|
|
|
out += width;
|
|
|
|
in += linepad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert8BitTo24Bit(const u8 *in, u8 *out, s32 width, s32 height, const u8 *palette, s32 linepad, bool flip)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
if (!in || !out)
|
2023-10-03 20:37:00 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
const s32 lineWidth = 3 * width;
|
|
|
|
if (flip)
|
|
|
|
out += lineWidth * height;
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 y = 0; y < height; ++y) {
|
2023-10-03 20:37:00 +02:00
|
|
|
if (flip)
|
|
|
|
out -= lineWidth; // one line back
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < lineWidth; x += 3) {
|
|
|
|
if (palette) {
|
2023-10-03 20:37:00 +02:00
|
|
|
#ifdef __BIG_ENDIAN__
|
2024-03-20 19:35:52 +01:00
|
|
|
out[x + 0] = palette[(in[0] << 2) + 0];
|
|
|
|
out[x + 1] = palette[(in[0] << 2) + 1];
|
|
|
|
out[x + 2] = palette[(in[0] << 2) + 2];
|
2023-10-03 20:37:00 +02:00
|
|
|
#else
|
2024-03-20 19:35:52 +01:00
|
|
|
out[x + 0] = palette[(in[0] << 2) + 2];
|
|
|
|
out[x + 1] = palette[(in[0] << 2) + 1];
|
|
|
|
out[x + 2] = palette[(in[0] << 2) + 0];
|
2023-10-03 20:37:00 +02:00
|
|
|
#endif
|
2024-03-20 19:35:52 +01:00
|
|
|
} else {
|
|
|
|
out[x + 0] = in[0];
|
|
|
|
out[x + 1] = in[0];
|
|
|
|
out[x + 2] = in[0];
|
2023-10-03 20:37:00 +02:00
|
|
|
}
|
|
|
|
++in;
|
|
|
|
}
|
|
|
|
if (!flip)
|
|
|
|
out += lineWidth;
|
|
|
|
in += linepad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert8BitTo32Bit(const u8 *in, u8 *out, s32 width, s32 height, const u8 *palette, s32 linepad, bool flip)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
if (!in || !out)
|
2023-10-03 20:37:00 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
const u32 lineWidth = 4 * width;
|
|
|
|
if (flip)
|
|
|
|
out += lineWidth * height;
|
|
|
|
|
|
|
|
u32 x;
|
|
|
|
u32 c;
|
2024-03-20 19:35:52 +01:00
|
|
|
for (u32 y = 0; y < (u32)height; ++y) {
|
2023-10-03 20:37:00 +02:00
|
|
|
if (flip)
|
|
|
|
out -= lineWidth; // one line back
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
if (palette) {
|
|
|
|
for (x = 0; x < (u32)width; x += 1) {
|
2023-10-03 20:37:00 +02:00
|
|
|
c = in[x];
|
2024-03-20 19:35:52 +01:00
|
|
|
((u32 *)out)[x] = ((u32 *)palette)[c];
|
2023-10-03 20:37:00 +02:00
|
|
|
}
|
2024-03-20 19:35:52 +01:00
|
|
|
} else {
|
|
|
|
for (x = 0; x < (u32)width; x += 1) {
|
2023-10-03 20:37:00 +02:00
|
|
|
c = in[x];
|
|
|
|
#ifdef __BIG_ENDIAN__
|
2024-03-20 19:35:52 +01:00
|
|
|
((u32 *)out)[x] = c << 24 | c << 16 | c << 8 | 0x000000FF;
|
2023-10-03 20:37:00 +02:00
|
|
|
#else
|
2024-03-20 19:35:52 +01:00
|
|
|
((u32 *)out)[x] = 0xFF000000 | c << 16 | c << 8 | c;
|
2023-10-03 20:37:00 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!flip)
|
|
|
|
out += lineWidth;
|
|
|
|
in += width + linepad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! converts 16bit data to 16bit data
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert16BitTo16Bit(const s16 *in, s16 *out, s32 width, s32 height, s32 linepad, bool flip)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
|
|
|
if (!in || !out)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (flip)
|
|
|
|
out += width * height;
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 y = 0; y < height; ++y) {
|
2023-10-03 20:37:00 +02:00
|
|
|
if (flip)
|
|
|
|
out -= width;
|
|
|
|
#ifdef __BIG_ENDIAN__
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < width; ++x)
|
|
|
|
out[x] = os::Byteswap::byteswap(in[x]);
|
2023-10-03 20:37:00 +02:00
|
|
|
#else
|
2024-03-20 19:35:52 +01:00
|
|
|
memcpy(out, in, width * sizeof(s16));
|
2023-10-03 20:37:00 +02:00
|
|
|
#endif
|
|
|
|
if (!flip)
|
|
|
|
out += width;
|
|
|
|
in += width;
|
|
|
|
in += linepad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! copies R8G8B8 24bit data to 24bit data
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert24BitTo24Bit(const u8 *in, u8 *out, s32 width, s32 height, s32 linepad, bool flip, bool bgr)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
|
|
|
if (!in || !out)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const s32 lineWidth = 3 * width;
|
|
|
|
if (flip)
|
|
|
|
out += lineWidth * height;
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 y = 0; y < height; ++y) {
|
2023-10-03 20:37:00 +02:00
|
|
|
if (flip)
|
|
|
|
out -= lineWidth;
|
2024-03-20 19:35:52 +01:00
|
|
|
if (bgr) {
|
|
|
|
for (s32 x = 0; x < lineWidth; x += 3) {
|
|
|
|
out[x + 0] = in[x + 2];
|
|
|
|
out[x + 1] = in[x + 1];
|
|
|
|
out[x + 2] = in[x + 0];
|
2023-10-03 20:37:00 +02:00
|
|
|
}
|
2024-03-20 19:35:52 +01:00
|
|
|
} else {
|
|
|
|
memcpy(out, in, lineWidth);
|
2023-10-03 20:37:00 +02:00
|
|
|
}
|
|
|
|
if (!flip)
|
|
|
|
out += lineWidth;
|
|
|
|
in += lineWidth;
|
|
|
|
in += linepad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Resizes the surface to a new size and converts it at the same time
|
|
|
|
//! to an A8R8G8B8 format, returning the pointer to the new buffer.
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert16bitToA8R8G8B8andResize(const s16 *in, s32 *out, s32 newWidth, s32 newHeight, s32 currentWidth, s32 currentHeight)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
|
|
|
if (!newWidth || !newHeight)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// note: this is very very slow. (i didn't want to write a fast version.
|
|
|
|
// but hopefully, nobody wants to convert surfaces every frame.
|
|
|
|
|
|
|
|
f32 sourceXStep = (f32)currentWidth / (f32)newWidth;
|
|
|
|
f32 sourceYStep = (f32)currentHeight / (f32)newHeight;
|
|
|
|
f32 sy;
|
|
|
|
s32 t;
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < newWidth; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
sy = 0.0f;
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 y = 0; y < newHeight; ++y) {
|
|
|
|
t = in[(s32)(((s32)sy) * currentWidth + x * sourceXStep)];
|
|
|
|
t = (((t >> 15) & 0x1) << 31) | (((t >> 10) & 0x1F) << 19) |
|
|
|
|
(((t >> 5) & 0x1F) << 11) | (t & 0x1F) << 3;
|
|
|
|
out[(s32)(y * newWidth + x)] = t;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
sy += sourceYStep;
|
2023-10-03 20:37:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! copies X8R8G8B8 32 bit data
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert32BitTo32Bit(const s32 *in, s32 *out, s32 width, s32 height, s32 linepad, bool flip)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
|
|
|
if (!in || !out)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (flip)
|
|
|
|
out += width * height;
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 y = 0; y < height; ++y) {
|
2023-10-03 20:37:00 +02:00
|
|
|
if (flip)
|
|
|
|
out -= width;
|
|
|
|
#ifdef __BIG_ENDIAN__
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < width; ++x)
|
|
|
|
out[x] = os::Byteswap::byteswap(in[x]);
|
2023-10-03 20:37:00 +02:00
|
|
|
#else
|
2024-03-20 19:35:52 +01:00
|
|
|
memcpy(out, in, width * sizeof(s32));
|
2023-10-03 20:37:00 +02:00
|
|
|
#endif
|
|
|
|
if (!flip)
|
|
|
|
out += width;
|
|
|
|
in += width;
|
|
|
|
in += linepad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A1R5G5B5toR8G8B8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u16 *sB = (u16 *)sP;
|
|
|
|
u8 *dB = (u8 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
dB[2] = (*sB & 0x7c00) >> 7;
|
|
|
|
dB[1] = (*sB & 0x03e0) >> 2;
|
|
|
|
dB[0] = (*sB & 0x1f) << 3;
|
|
|
|
|
|
|
|
sB += 1;
|
|
|
|
dB += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A1R5G5B5toB8G8R8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u16 *sB = (u16 *)sP;
|
|
|
|
u8 *dB = (u8 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
dB[0] = (*sB & 0x7c00) >> 7;
|
|
|
|
dB[1] = (*sB & 0x03e0) >> 2;
|
|
|
|
dB[2] = (*sB & 0x1f) << 3;
|
|
|
|
|
|
|
|
sB += 1;
|
|
|
|
dB += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A1R5G5B5toR5G5B5A1(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
const u16 *sB = (const u16 *)sP;
|
|
|
|
u16 *dB = (u16 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
|
|
|
*dB = (*sB << 1) | (*sB >> 15);
|
|
|
|
++sB;
|
|
|
|
++dB;
|
2023-10-03 20:37:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A1R5G5B5toA8R8G8B8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u16 *sB = (u16 *)sP;
|
|
|
|
u32 *dB = (u32 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
|
|
|
for (s32 x = 0; x < sN; ++x)
|
|
|
|
*dB++ = A1R5G5B5toA8R8G8B8(*sB++);
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A1R5G5B5toA1R5G5B5(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
|
|
|
memcpy(dP, sP, sN * 2);
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A1R5G5B5toR5G6B5(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u16 *sB = (u16 *)sP;
|
|
|
|
u16 *dB = (u16 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
|
|
|
for (s32 x = 0; x < sN; ++x)
|
|
|
|
*dB++ = A1R5G5B5toR5G6B5(*sB++);
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A8R8G8B8toR8G8B8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u8 *sB = (u8 *)sP;
|
|
|
|
u8 *dB = (u8 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
// sB[3] is alpha
|
|
|
|
dB[0] = sB[2];
|
|
|
|
dB[1] = sB[1];
|
|
|
|
dB[2] = sB[0];
|
|
|
|
|
|
|
|
sB += 4;
|
|
|
|
dB += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A8R8G8B8toB8G8R8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u8 *sB = (u8 *)sP;
|
|
|
|
u8 *dB = (u8 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
// sB[3] is alpha
|
|
|
|
dB[0] = sB[0];
|
|
|
|
dB[1] = sB[1];
|
|
|
|
dB[2] = sB[2];
|
|
|
|
|
|
|
|
sB += 4;
|
|
|
|
dB += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A8R8G8B8toA8R8G8B8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
|
|
|
memcpy(dP, sP, sN * 4);
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A8R8G8B8toA1R5G5B5(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u32 *sB = (u32 *)sP;
|
|
|
|
u16 *dB = (u16 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
|
|
|
for (s32 x = 0; x < sN; ++x)
|
|
|
|
*dB++ = A8R8G8B8toA1R5G5B5(*sB++);
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A8R8G8B8toA1B5G5R5(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u8 *sB = (u8 *)sP;
|
|
|
|
u16 *dB = (u16 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
s32 r = sB[0] >> 3;
|
|
|
|
s32 g = sB[1] >> 3;
|
|
|
|
s32 b = sB[2] >> 3;
|
|
|
|
s32 a = sB[3] >> 3;
|
|
|
|
|
|
|
|
dB[0] = (a << 15) | (r << 10) | (g << 5) | (b);
|
|
|
|
|
|
|
|
sB += 4;
|
|
|
|
dB += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A8R8G8B8toR5G6B5(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u8 *sB = (u8 *)sP;
|
|
|
|
u16 *dB = (u16 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
s32 r = sB[2] >> 3;
|
|
|
|
s32 g = sB[1] >> 2;
|
|
|
|
s32 b = sB[0] >> 3;
|
|
|
|
|
|
|
|
dB[0] = (r << 11) | (g << 5) | (b);
|
|
|
|
|
|
|
|
sB += 4;
|
|
|
|
dB += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A8R8G8B8toR3G3B2(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u8 *sB = (u8 *)sP;
|
|
|
|
u8 *dB = (u8 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
u8 r = sB[2] & 0xe0;
|
|
|
|
u8 g = (sB[1] & 0xe0) >> 3;
|
|
|
|
u8 b = (sB[0] & 0xc0) >> 6;
|
|
|
|
|
|
|
|
dB[0] = (r | g | b);
|
|
|
|
|
|
|
|
sB += 4;
|
|
|
|
dB += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_R8G8B8toR8G8B8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
|
|
|
memcpy(dP, sP, sN * 3);
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_R8G8B8toA8R8G8B8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u8 *sB = (u8 *)sP;
|
|
|
|
u32 *dB = (u32 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
|
|
|
*dB = 0xff000000 | (sB[0] << 16) | (sB[1] << 8) | sB[2];
|
2023-10-03 20:37:00 +02:00
|
|
|
|
|
|
|
sB += 3;
|
|
|
|
++dB;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_R8G8B8toA1R5G5B5(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u8 *sB = (u8 *)sP;
|
|
|
|
u16 *dB = (u16 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
s32 r = sB[0] >> 3;
|
|
|
|
s32 g = sB[1] >> 3;
|
|
|
|
s32 b = sB[2] >> 3;
|
|
|
|
|
|
|
|
dB[0] = (0x8000) | (r << 10) | (g << 5) | (b);
|
|
|
|
|
|
|
|
sB += 3;
|
|
|
|
dB += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_B8G8R8toA8R8G8B8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u8 *sB = (u8 *)sP;
|
|
|
|
u32 *dB = (u32 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
|
|
|
*dB = 0xff000000 | (sB[2] << 16) | (sB[1] << 8) | sB[0];
|
2023-10-03 20:37:00 +02:00
|
|
|
|
|
|
|
sB += 3;
|
|
|
|
++dB;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A8R8G8B8toR8G8B8A8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
const u32 *sB = (const u32 *)sP;
|
|
|
|
u32 *dB = (u32 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
|
|
|
*dB++ = (*sB << 8) | (*sB >> 24);
|
2023-10-03 20:37:00 +02:00
|
|
|
++sB;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_A8R8G8B8toA8B8G8R8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
const u32 *sB = (const u32 *)sP;
|
|
|
|
u32 *dB = (u32 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
|
|
|
*dB++ = (*sB & 0xff00ff00) | ((*sB & 0x00ff0000) >> 16) | ((*sB & 0x000000ff) << 16);
|
2023-10-03 20:37:00 +02:00
|
|
|
++sB;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_B8G8R8A8toA8R8G8B8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u8 *sB = (u8 *)sP;
|
|
|
|
u8 *dB = (u8 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
dB[0] = sB[3];
|
|
|
|
dB[1] = sB[2];
|
|
|
|
dB[2] = sB[1];
|
|
|
|
dB[3] = sB[0];
|
|
|
|
|
|
|
|
sB += 4;
|
|
|
|
dB += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_R8G8B8toB8G8R8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u8 *sB = (u8 *)sP;
|
|
|
|
u8 *dB = (u8 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
dB[2] = sB[0];
|
|
|
|
dB[1] = sB[1];
|
|
|
|
dB[0] = sB[2];
|
|
|
|
|
|
|
|
sB += 3;
|
|
|
|
dB += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_R8G8B8toR5G6B5(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u8 *sB = (u8 *)sP;
|
|
|
|
u16 *dB = (u16 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
s32 r = sB[0] >> 3;
|
|
|
|
s32 g = sB[1] >> 2;
|
|
|
|
s32 b = sB[2] >> 3;
|
|
|
|
|
|
|
|
dB[0] = (r << 11) | (g << 5) | (b);
|
|
|
|
|
|
|
|
sB += 3;
|
|
|
|
dB += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_R5G6B5toR5G6B5(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
|
|
|
memcpy(dP, sP, sN * 2);
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_R5G6B5toR8G8B8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u16 *sB = (u16 *)sP;
|
|
|
|
u8 *dB = (u8 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
dB[0] = (*sB & 0xf800) >> 8;
|
|
|
|
dB[1] = (*sB & 0x07e0) >> 3;
|
|
|
|
dB[2] = (*sB & 0x001f) << 3;
|
|
|
|
|
|
|
|
sB += 1;
|
|
|
|
dB += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_R5G6B5toB8G8R8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u16 *sB = (u16 *)sP;
|
|
|
|
u8 *dB = (u8 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
for (s32 x = 0; x < sN; ++x) {
|
2023-10-03 20:37:00 +02:00
|
|
|
dB[2] = (*sB & 0xf800) >> 8;
|
|
|
|
dB[1] = (*sB & 0x07e0) >> 3;
|
|
|
|
dB[0] = (*sB & 0x001f) << 3;
|
|
|
|
|
|
|
|
sB += 1;
|
|
|
|
dB += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_R5G6B5toA8R8G8B8(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u16 *sB = (u16 *)sP;
|
|
|
|
u32 *dB = (u32 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
|
|
|
for (s32 x = 0; x < sN; ++x)
|
|
|
|
*dB++ = R5G6B5toA8R8G8B8(*sB++);
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_R5G6B5toA1R5G5B5(const void *sP, s32 sN, void *dP)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
u16 *sB = (u16 *)sP;
|
|
|
|
u16 *dB = (u16 *)dP;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
|
|
|
for (s32 x = 0; x < sN; ++x)
|
|
|
|
*dB++ = R5G6B5toA1R5G5B5(*sB++);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CColorConverter::canConvertFormat(ECOLOR_FORMAT sourceFormat, ECOLOR_FORMAT destFormat)
|
|
|
|
{
|
2024-03-20 19:35:52 +01:00
|
|
|
switch (sourceFormat) {
|
|
|
|
case ECF_A1R5G5B5:
|
|
|
|
switch (destFormat) {
|
2023-10-03 20:37:00 +02:00
|
|
|
case ECF_A1R5G5B5:
|
|
|
|
case ECF_R5G6B5:
|
2024-03-20 19:35:52 +01:00
|
|
|
case ECF_A8R8G8B8:
|
|
|
|
case ECF_R8G8B8:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2023-10-03 20:37:00 +02:00
|
|
|
break;
|
2024-03-20 19:35:52 +01:00
|
|
|
case ECF_R5G6B5:
|
|
|
|
switch (destFormat) {
|
|
|
|
case ECF_A1R5G5B5:
|
|
|
|
case ECF_R5G6B5:
|
2023-10-03 20:37:00 +02:00
|
|
|
case ECF_A8R8G8B8:
|
2024-03-20 19:35:52 +01:00
|
|
|
case ECF_R8G8B8:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2023-10-03 20:37:00 +02:00
|
|
|
break;
|
2024-03-20 19:35:52 +01:00
|
|
|
case ECF_A8R8G8B8:
|
|
|
|
switch (destFormat) {
|
|
|
|
case ECF_A1R5G5B5:
|
|
|
|
case ECF_R5G6B5:
|
|
|
|
case ECF_A8R8G8B8:
|
2023-10-03 20:37:00 +02:00
|
|
|
case ECF_R8G8B8:
|
2024-03-20 19:35:52 +01:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2023-10-03 20:37:00 +02:00
|
|
|
break;
|
2024-03-20 19:35:52 +01:00
|
|
|
case ECF_R8G8B8:
|
|
|
|
switch (destFormat) {
|
|
|
|
case ECF_A1R5G5B5:
|
|
|
|
case ECF_R5G6B5:
|
|
|
|
case ECF_A8R8G8B8:
|
|
|
|
case ECF_R8G8B8:
|
|
|
|
return true;
|
2023-10-03 20:37:00 +02:00
|
|
|
default:
|
|
|
|
break;
|
2024-03-20 19:35:52 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2023-10-03 20:37:00 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-03-20 19:35:52 +01:00
|
|
|
void CColorConverter::convert_viaFormat(const void *sP, ECOLOR_FORMAT sF, s32 sN,
|
|
|
|
void *dP, ECOLOR_FORMAT dF)
|
2023-10-03 20:37:00 +02:00
|
|
|
{
|
|
|
|
// please also update can_convert_viaFormat when adding new conversions
|
2024-03-20 19:35:52 +01:00
|
|
|
switch (sF) {
|
|
|
|
case ECF_A1R5G5B5:
|
|
|
|
switch (dF) {
|
2023-10-03 20:37:00 +02:00
|
|
|
case ECF_A1R5G5B5:
|
2024-03-20 19:35:52 +01:00
|
|
|
convert_A1R5G5B5toA1R5G5B5(sP, sN, dP);
|
|
|
|
break;
|
2023-10-03 20:37:00 +02:00
|
|
|
case ECF_R5G6B5:
|
2024-03-20 19:35:52 +01:00
|
|
|
convert_A1R5G5B5toR5G6B5(sP, sN, dP);
|
|
|
|
break;
|
|
|
|
case ECF_A8R8G8B8:
|
|
|
|
convert_A1R5G5B5toA8R8G8B8(sP, sN, dP);
|
|
|
|
break;
|
|
|
|
case ECF_R8G8B8:
|
|
|
|
convert_A1R5G5B5toR8G8B8(sP, sN, dP);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2023-10-03 20:37:00 +02:00
|
|
|
break;
|
2024-03-20 19:35:52 +01:00
|
|
|
case ECF_R5G6B5:
|
|
|
|
switch (dF) {
|
|
|
|
case ECF_A1R5G5B5:
|
|
|
|
convert_R5G6B5toA1R5G5B5(sP, sN, dP);
|
|
|
|
break;
|
|
|
|
case ECF_R5G6B5:
|
|
|
|
convert_R5G6B5toR5G6B5(sP, sN, dP);
|
|
|
|
break;
|
2023-10-03 20:37:00 +02:00
|
|
|
case ECF_A8R8G8B8:
|
2024-03-20 19:35:52 +01:00
|
|
|
convert_R5G6B5toA8R8G8B8(sP, sN, dP);
|
|
|
|
break;
|
|
|
|
case ECF_R8G8B8:
|
|
|
|
convert_R5G6B5toR8G8B8(sP, sN, dP);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2023-10-03 20:37:00 +02:00
|
|
|
break;
|
2024-03-20 19:35:52 +01:00
|
|
|
case ECF_A8R8G8B8:
|
|
|
|
switch (dF) {
|
|
|
|
case ECF_A1R5G5B5:
|
|
|
|
convert_A8R8G8B8toA1R5G5B5(sP, sN, dP);
|
|
|
|
break;
|
|
|
|
case ECF_R5G6B5:
|
|
|
|
convert_A8R8G8B8toR5G6B5(sP, sN, dP);
|
|
|
|
break;
|
|
|
|
case ECF_A8R8G8B8:
|
|
|
|
convert_A8R8G8B8toA8R8G8B8(sP, sN, dP);
|
|
|
|
break;
|
2023-10-03 20:37:00 +02:00
|
|
|
case ECF_R8G8B8:
|
2024-03-20 19:35:52 +01:00
|
|
|
convert_A8R8G8B8toR8G8B8(sP, sN, dP);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2023-10-03 20:37:00 +02:00
|
|
|
break;
|
2024-03-20 19:35:52 +01:00
|
|
|
case ECF_R8G8B8:
|
|
|
|
switch (dF) {
|
|
|
|
case ECF_A1R5G5B5:
|
|
|
|
convert_R8G8B8toA1R5G5B5(sP, sN, dP);
|
|
|
|
break;
|
|
|
|
case ECF_R5G6B5:
|
|
|
|
convert_R8G8B8toR5G6B5(sP, sN, dP);
|
|
|
|
break;
|
|
|
|
case ECF_A8R8G8B8:
|
|
|
|
convert_R8G8B8toA8R8G8B8(sP, sN, dP);
|
|
|
|
break;
|
|
|
|
case ECF_R8G8B8:
|
|
|
|
convert_R8G8B8toR8G8B8(sP, sN, dP);
|
|
|
|
break;
|
2023-10-03 20:37:00 +02:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2024-03-20 19:35:52 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2023-10-03 20:37:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end namespace video
|
|
|
|
} // end namespace irr
|