| @@ -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"); | |||