VideoCodec/Modules/Transform/ColourSpaceConverter.cpp

#include "ColourSpaceConverter.h" namespace VideoCodec {    ColourSpaceConverter::ColourSpaceConverter() : Module(COLOUR_SPACE_CONVERTER_MODULE_ID)    {       this->outputPlanes = false;    }        ColourSpaceConverter::~ColourSpaceConverter()    {    }        ConfigurationStatus ColourSpaceConverter::Configure(ConfigurationElement* configuration)    {       if (configuration != NULL && (configuration->GetValue("outputPlanes") != NULL) && *(configuration->GetValue("outputPlanes")->GetString()) == string("true"))          this->outputPlanes = true;              return MODULE_CONFIGURATION_OK;    }        void ColourSpaceConverter::ConvertRGBToYUVRepresentation(PictureInfo* picture, Codec* codec)    {       if (picture->GetColourFormat() != COLOUR_FORMAT_RGB)          Logger::LogMessage("Warning: Non-RGB colour format input received for conversion RGB to YUV.");              if (picture->GetPixelLayout() != PIXEL_LAYOUT_SCAN)          Logger::LogMessage("Warning: Scan order pixel data is required for colour space conversion.");              UnsignedByte* componentData = picture->GetUnsignedByteData();       PixelCount imageWidth = picture->GetPixelsX();       PixelCount imageHeight = picture->GetPixelsY();              // Use fixed point approximation.       int r, g, b;       for (int y = 0, index = 0; y < imageHeight; y++)       {          for (int x = 0; x < imageWidth; x++, index += 3)          {             r = (int)componentData[index];             g = (int)componentData[index + 1];             b = (int)componentData[index + 2];             componentData[index] = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;             componentData[index + 1] = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;             componentData[index + 2] = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;          }       }              // The component values have been converted in place.       picture->SetColourFormat(COLOUR_FORMAT_YUV);       // Outputs colour planes for this image for Y, U and V components. (Or more precisely, Y, Cb and Cr planes.)       if (this->outputPlanes)       {          // Set the other two components to include only one plane for each.          PictureInfo* yPicture = picture->Clone();          PictureInfo* cbPicture = picture->Clone();          PictureInfo* crPicture = picture->Clone();          UnsignedByte* yPictureComponents = yPicture->GetUnsignedByteData();          UnsignedByte* cbPictureComponents = cbPicture->GetUnsignedByteData();          UnsignedByte* crPictureComponents = crPicture->GetUnsignedByteData();                    for (int index = 0; index < imageWidth * imageHeight * 3; index += 3)          {             yPictureComponents[index + 1] = yPictureComponents[index + 2] = 128;             cbPictureComponents[index] = 128;             cbPictureComponents[index + 2] = 128;             crPictureComponents[index] = 128;             crPictureComponents[index + 1] = 128;          }                    // Move them back to RGB.          this->ConvertYUVToRGBRepresentation(yPicture);          this->ConvertYUVToRGBRepresentation(cbPicture);          this->ConvertYUVToRGBRepresentation(crPicture);                    // Output the planes.          ((FrameOutputModule*)codec->GetModule(FRAME_OUTPUT_MODULE_ID))->WriteImage(yPicture, "yPlane.png");          ((FrameOutputModule*)codec->GetModule(FRAME_OUTPUT_MODULE_ID))->WriteImage(cbPicture, "cbPlane.png");          ((FrameOutputModule*)codec->GetModule(FRAME_OUTPUT_MODULE_ID))->WriteImage(crPicture, "crPlane.png");                    // Clean up.          delete yPicture;          delete cbPicture;          delete crPicture;       }    }        void ColourSpaceConverter::ConvertYUVToRGBRepresentation(PictureInfo* picture)    {       if (picture->GetColourFormat() != COLOUR_FORMAT_YUV)          Logger::LogMessage("Warning: Non-YUV colour format input received for conversion YUV to RGB.");              if (picture->GetPixelLayout() != PIXEL_LAYOUT_SCAN)          Logger::LogMessage("Warning: Scan order pixel data is required for colour space conversion.");              UnsignedByte* componentData = picture->GetUnsignedByteData();       int imageWidth = picture->GetPixelsX();       int imageHeight = picture->GetPixelsY();              // Use fixed point approximation.       int c, d, e;       for (int y = 0, index = 0; y < imageHeight; y++)       {          for (int x = 0; x < imageWidth; x++, index += 3)          {             c = (int)componentData[index] - 16;             d = (int)componentData[index + 1] - 128;             e = (int)componentData[index + 2] - 128;             componentData[index] = colourClip(( 298 * c + 409 * e + 128) >> 8);             componentData[index + 1] = colourClip(( 298 * c - 100 * d - 208 * e + 128) >> 8);             componentData[index + 2] = colourClip(( 298 * c + 516 * d + 128) >> 8);          }       }              picture->SetColourFormat(COLOUR_FORMAT_RGB);    }        inline unsigned char ColourSpaceConverter::colourClip(int value)    {       return value > 255 ? (unsigned char)255 :          value < 0 ? (unsigned char)0 : value;    } }