| @@ -15,6 +15,12 @@ | |||||
| namespace lol | 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) | static vec4 u8tof32(u8vec4 pixel) | ||||
| { | { | ||||
| //vec4 ret; | //vec4 ret; | ||||
| @@ -24,6 +30,25 @@ static vec4 u8tof32(u8vec4 pixel) | |||||
| return (vec4)pixel / 255.f; | 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) | static u8vec4 f32tou8(vec4 pixel) | ||||
| { | { | ||||
| return (u8vec4)(pixel * 255.99f); | return (u8vec4)(pixel * 255.99f); | ||||
| @@ -38,6 +63,22 @@ PixelFormat Image::GetFormat() const | |||||
| return m_data->m_format; | 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) | void Image::SetFormat(PixelFormat fmt) | ||||
| { | { | ||||
| PixelFormat old_fmt = m_data->m_format; | PixelFormat old_fmt = m_data->m_format; | ||||
| @@ -51,6 +92,20 @@ void Image::SetFormat(PixelFormat fmt) | |||||
| SetFormat(PixelFormat::RGBA_F32); | SetFormat(PixelFormat::RGBA_F32); | ||||
| else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGB_8) | else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGB_8) | ||||
| SetFormat(PixelFormat::RGBA_F32); | 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; | old_fmt = m_data->m_format; | ||||
| @@ -98,15 +153,112 @@ void Image::SetFormat(PixelFormat fmt) | |||||
| if (fmt == old_fmt || old_fmt == PixelFormat::Unknown) | if (fmt == old_fmt || old_fmt == PixelFormat::Unknown) | ||||
| return; | 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(); | 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(); | 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) | for (int n = 0; n < count; ++n) | ||||
| dest[n] = u8tof32(src[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) | else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::RGBA_F32) | ||||
| { | { | ||||
| u8vec3 *src = (u8vec3 *)m_data->m_pixels[(int)old_fmt]->Data(); | 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) | for (int n = 0; n < count; ++n) | ||||
| dest[n] = u8tof32(u8vec4(src[n], 255)); | 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) | else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::RGBA_8) | ||||
| { | { | ||||
| vec4 *src = (vec4 *)m_data->m_pixels[(int)old_fmt]->Data(); | vec4 *src = (vec4 *)m_data->m_pixels[(int)old_fmt]->Data(); | ||||
| @@ -154,24 +341,6 @@ void Image::SetFormat(PixelFormat fmt) | |||||
| } | } | ||||
| #endif | #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 | else | ||||
| { | { | ||||
| ASSERT(false, "Unable to find proper conversion"); | ASSERT(false, "Unable to find proper conversion"); | ||||