diff --git a/project/vc8/nvimage/nvimage.vcproj b/project/vc8/nvimage/nvimage.vcproj index 1b5d677..db24118 100644 --- a/project/vc8/nvimage/nvimage.vcproj +++ b/project/vc8/nvimage/nvimage.vcproj @@ -82,11 +82,12 @@ /> + + @@ -327,6 +331,10 @@ RelativePath="..\..\..\src\nvimage\ColorBlock.h" > + + diff --git a/src/nvimage/CMakeLists.txt b/src/nvimage/CMakeLists.txt index 3f66b00..6222262 100644 --- a/src/nvimage/CMakeLists.txt +++ b/src/nvimage/CMakeLists.txt @@ -25,7 +25,9 @@ SET(IMAGE_SRCS NormalMipmap.h NormalMipmap.cpp PsdFile.h - TgaFile.h) + TgaFile.h + ColorSpace.h + ColorSpace.cpp) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/nvimage/ColorSpace.cpp b/src/nvimage/ColorSpace.cpp new file mode 100644 index 0000000..6ee87c5 --- /dev/null +++ b/src/nvimage/ColorSpace.cpp @@ -0,0 +1,66 @@ +#include "ColorSpace.h" +#include +#include +#include + +namespace nv +{ + void ColorSpace::RGBtoYCoCg_R(Image* img) + { + const uint w = img->width(); + const uint h = img->height(); + + for( uint y=0; y < h; y++ ) + { + for( uint x=0; x < w; x++ ) + { + Color32 pixel = img->pixel(x, y); + + const int r = pixel.r; + const int g = pixel.g; + const int b = pixel.b; + + const int Co = r - b; + const int t = b + Co/2; + const int Cg = g - t; + const int Y = t + Cg/2; + + // Just saturate the chroma here (we loose out of one bit in each channel) + // this just means that we won't have as high dynamic range. Perhaps a better option + // is to loose the least significant bit instead? + pixel.r = clamp(Co + 128, 0, 255); + pixel.g = clamp(Cg + 128, 0, 255); + pixel.b = 0; + pixel.a = Y; + } + } + } + + void ColorSpace::YCoCg_RtoRGB(Image* img) + { + const uint w = img->width(); + const uint h = img->height(); + + for( uint y=0; y < h; y++ ) + { + for( uint x=0; x < w; x++ ) + { + Color32 pixel = img->pixel(x, y); + + const int Co = (int)pixel.r - 128; + const int Cg = (int)pixel.g - 128; + const int Y = pixel.a; + + const int t = Y - Cg/2; + const int g = Cg + t; + const int b = t - Co/2; + const int r = b + Co; + + pixel.r = r; + pixel.g = g; + pixel.b = b; + pixel.a = 1; + } + } + } +} \ No newline at end of file diff --git a/src/nvimage/ColorSpace.h b/src/nvimage/ColorSpace.h new file mode 100644 index 0000000..1451b98 --- /dev/null +++ b/src/nvimage/ColorSpace.h @@ -0,0 +1,20 @@ + +#ifndef NV_IMAGE_COLORSPACE_H +#define NV_IMAGE_COLORSPACE_H + +namespace nv +{ + class Image; + + // Defines simple mappings between different color spaces and encodes them in the + // input image. + namespace ColorSpace + { + void RGBtoYCoCg_R(Image* img); + void YCoCg_RtoRGB(Image* img); + } +} + + + +#endif diff --git a/src/nvtt/Compressor.cpp b/src/nvtt/Compressor.cpp index 788724f..5bdb014 100644 --- a/src/nvtt/Compressor.cpp +++ b/src/nvtt/Compressor.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include "Compressor.h" #include "InputOptions.h" @@ -482,6 +483,17 @@ bool Compressor::Private::initMipmap(Mipmap & mipmap, const InputOptions::Privat premultiplyAlphaMipmap(mipmap, inputOptions); } + // Apply gamma space color transforms: + if (inputOptions.colorTransform == ColorTransform_YCoCg) + { + ColorSpace::RGBtoYCoCg_R(mipmap.asMutableFixedImage()); + } + else if (inputOptions.colorTransform == ColorTransform_ScaledYCoCg) + { + // @@ TODO + //ColorSpace::RGBtoYCoCg_R(mipmap.asMutableFixedImage()); + } + return true; } diff --git a/src/nvtt/nvtt.h b/src/nvtt/nvtt.h index 12fcc71..be4e72e 100644 --- a/src/nvtt/nvtt.h +++ b/src/nvtt/nvtt.h @@ -156,8 +156,10 @@ namespace nvtt enum ColorTransform { ColorTransform_None, - ColorTransform_Linear, - ColorTransform_Swizzle + ColorTransform_Linear, ///< Not implemented. + ColorTransform_Swizzle, ///< Not implemented. + ColorTransform_YCoCg, ///< Transform into r=Co, g=Cg, b=0, a=Y + ColorTransform_ScaledYCoCg, ///< Not implemented. }; /// Extents rounding mode.