Browse Source

image: add plenty of colour conversions.

undefined
Sam Hocevar 10 years ago
parent
commit
5026358eef
1 changed files with 189 additions and 20 deletions
  1. +189
    -20
      src/image/pixel.cpp

+ 189
- 20
src/image/pixel.cpp View File

@@ -15,6 +15,12 @@
namespace lol
{

static float u8tof32(uint8_t pixel)
{
//return pow((float)pixel / 255.f, global_gamma);
return pixel / 255.f;
}

static vec4 u8tof32(u8vec4 pixel)
{
//vec4 ret;
@@ -24,6 +30,25 @@ static vec4 u8tof32(u8vec4 pixel)
return (vec4)pixel / 255.f;
}

static vec3 u8tof32(u8vec3 pixel)
{
//vec3 ret;
//ret.r = pow((float)pixel.r / 255.f, global_gamma);
//ret.g = pow((float)pixel.g / 255.f, global_gamma);
//ret.b = pow((float)pixel.b / 255.f, global_gamma);
return (vec3)pixel / 255.f;
}

static uint8_t f32tou8(float pixel)
{
return (uint8_t)(pixel * 255.99f);
}

static u8vec3 f32tou8(vec3 pixel)
{
return (u8vec3)(pixel * 255.99f);
}

static u8vec4 f32tou8(vec4 pixel)
{
return (u8vec4)(pixel * 255.99f);
@@ -38,6 +63,22 @@ PixelFormat Image::GetFormat() const
return m_data->m_format;
}

/* Conversion rules matrix
*
* From: To→ 1 2 3 4 5 6
* Y_8 1 . o o x x x
* RGB_8 2 ~ . o ~ x x
* RGBA_8 3 ~ o . ~ x x
* Y_F32 4 # ~ ~ . o o
* RGB_F32 5 ~ # ~ # . o
* RGBA_F32 6 ~ ~ # ~ o .
*
* . no conversion necessary
* ~ intermediate conversion to RGBA_F32 or RGB_F32
* o easy conversion (add/remove alpha and/or convert gray→color)
* x lossless conversion (u8 to float)
* # lossy conversion (dithering and/or convert color→gray)
*/
void Image::SetFormat(PixelFormat fmt)
{
PixelFormat old_fmt = m_data->m_format;
@@ -51,6 +92,20 @@ void Image::SetFormat(PixelFormat fmt)
SetFormat(PixelFormat::RGBA_F32);
else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGB_8)
SetFormat(PixelFormat::RGBA_F32);
else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::RGBA_8)
SetFormat(PixelFormat::RGBA_F32);
else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::Y_F32)
SetFormat(PixelFormat::RGB_F32);
else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::RGB_8)
SetFormat(PixelFormat::RGB_F32);
else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::Y_8)
SetFormat(PixelFormat::RGB_F32);
else if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::Y_8)
SetFormat(PixelFormat::RGB_F32);
else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::Y_8)
SetFormat(PixelFormat::Y_F32);
else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::Y_8)
SetFormat(PixelFormat::Y_F32);

old_fmt = m_data->m_format;

@@ -98,15 +153,112 @@ void Image::SetFormat(PixelFormat fmt)
if (fmt == old_fmt || old_fmt == PixelFormat::Unknown)
return;

/* Convert pixels */
if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::RGBA_F32)
/* Easy conversions: just add or remove channels */
if (old_fmt == PixelFormat::Y_8 && fmt == PixelFormat::RGB_8)
{
uint8_t *src = (uint8_t *)m_data->m_pixels[(int)old_fmt]->Data();
u8vec3 *dest = (u8vec3 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = u8vec3(src[n]);
}
else if (old_fmt == PixelFormat::Y_8 && fmt == PixelFormat::RGBA_8)
{
uint8_t *src = (uint8_t *)m_data->m_pixels[(int)old_fmt]->Data();
u8vec4 *dest = (u8vec4 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = u8vec4(u8vec3(src[n]), 255);
}
else if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::RGB_8)
{
u8vec4 *src = (u8vec4 *)m_data->m_pixels[(int)old_fmt]->Data();
u8vec3 *dest = (u8vec3 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = src[n].rgb;
}
else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::RGBA_8)
{
u8vec3 *src = (u8vec3 *)m_data->m_pixels[(int)old_fmt]->Data();
u8vec4 *dest = (u8vec4 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = u8vec4(src[n], 255);
}
else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::RGB_F32)
{
vec4 *src = (vec4 *)m_data->m_pixels[(int)old_fmt]->Data();
vec3 *dest = (vec3 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = src[n].rgb;
}
else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::RGBA_F32)
{
vec3 *src = (vec3 *)m_data->m_pixels[(int)old_fmt]->Data();
vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = vec4(src[n], 1.f);
}
else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGB_F32)
{
float *src = (float *)m_data->m_pixels[(int)old_fmt]->Data();
vec3 *dest = (vec3 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = vec3(src[n]);
}
else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGBA_F32)
{
float *src = (float *)m_data->m_pixels[(int)old_fmt]->Data();
vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = vec4(vec3(src[n]), 1.0f);
}
/* Lossless conversions: u8 to float */
else if (old_fmt == PixelFormat::Y_8 && fmt == PixelFormat::Y_F32)
{
float *src = (float *)m_data->m_pixels[(int)old_fmt]->Data();
float *dest = (float *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = u8tof32(src[n]);
}
else if (old_fmt == PixelFormat::Y_8 && fmt == PixelFormat::RGB_F32)
{
float *src = (float *)m_data->m_pixels[(int)old_fmt]->Data();
vec3 *dest = (vec3 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = u8tof32(u8vec3(src[n]));
}
else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::RGB_F32)
{
u8vec3 *src = (u8vec3 *)m_data->m_pixels[(int)old_fmt]->Data();
vec3 *dest = (vec3 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = u8tof32(src[n]);
}
else if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::RGB_F32)
{
u8vec4 *src = (u8vec4 *)m_data->m_pixels[(int)old_fmt]->Data();
vec3 *dest = (vec3 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = u8tof32(src[n].rgb);
}
else if (old_fmt == PixelFormat::Y_8 && fmt == PixelFormat::RGBA_F32)
{
float *src = (float *)m_data->m_pixels[(int)old_fmt]->Data();
vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = u8tof32(u8vec4(u8vec3(src[n]), 255));
}
else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::RGBA_F32)
{
u8vec3 *src = (u8vec3 *)m_data->m_pixels[(int)old_fmt]->Data();
@@ -115,6 +267,41 @@ void Image::SetFormat(PixelFormat fmt)
for (int n = 0; n < count; ++n)
dest[n] = u8tof32(u8vec4(src[n], 255));
}
else if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::RGBA_F32)
{
u8vec4 *src = (u8vec4 *)m_data->m_pixels[(int)old_fmt]->Data();
vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = u8tof32(src[n]);
}
/* Other conversions */
else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::Y_F32)
{
vec4 *src = (vec4 *)m_data->m_pixels[(int)old_fmt]->Data();
float *dest = (float *)m_data->m_pixels[(int)fmt]->Data();

vec3 const coeff(0.299f, 0.587f, 0.114f);

for (int n = 0; n < count; ++n)
dest[n] = dot(coeff, src[n].rgb);
}
else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::Y_8)
{
float *src = (float *)m_data->m_pixels[(int)old_fmt]->Data();
uint8_t *dest = (uint8_t *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = f32tou8(src[n]);
}
else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::RGB_8)
{
vec3 *src = (vec3 *)m_data->m_pixels[(int)old_fmt]->Data();
u8vec3 *dest = (u8vec3 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = f32tou8(src[n]);
}
else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::RGBA_8)
{
vec4 *src = (vec4 *)m_data->m_pixels[(int)old_fmt]->Data();
@@ -154,24 +341,6 @@ void Image::SetFormat(PixelFormat fmt)
}
#endif
}
else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGBA_F32)
{
float *src = (float *)m_data->m_pixels[(int)old_fmt]->Data();
vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->Data();

for (int n = 0; n < count; ++n)
dest[n] = vec4(vec3(src[n]), 1.0f);
}
else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::Y_F32)
{
vec4 *src = (vec4 *)m_data->m_pixels[(int)old_fmt]->Data();
float *dest = (float *)m_data->m_pixels[(int)fmt]->Data();

vec3 const coeff(0.299f, 0.587f, 0.114f);

for (int n = 0; n < count; ++n)
dest[n] = dot(coeff, src[n].rgb);
}
else
{
ASSERT(false, "Unable to find proper conversion");


Loading…
Cancel
Save