diff --git a/include/gz/rendering/PixelFormat.hh b/include/gz/rendering/PixelFormat.hh index 3617f8c43..58c6b02df 100644 --- a/include/gz/rendering/PixelFormat.hh +++ b/include/gz/rendering/PixelFormat.hh @@ -43,10 +43,10 @@ namespace gz PF_BAYER_RGGB8 = 4, /// < Bayer BGGR, 1-byte per channel PF_BAYER_BGGR8 = 5, - /// < Bayer GBGR, 1-byte per channel - PF_BAYER_GBGR8 = 6, - /// < Bayer GRGB, 1-byte per channel - PF_BAYER_GRGB8 = 7, + /// < Bayer GBRG, 1-byte per channel + PF_BAYER_GBRG8 = 6, + /// < Bayer GRBG, 1-byte per channel + PF_BAYER_GRBG8 = 7, // Float32 format one channel PF_FLOAT32_R = 8, // Float32 format and RGB diff --git a/include/gz/rendering/Utils.hh b/include/gz/rendering/Utils.hh index 61b16fb4e..4d53fe2c9 100644 --- a/include/gz/rendering/Utils.hh +++ b/include/gz/rendering/Utils.hh @@ -18,6 +18,7 @@ #define GZ_RENDERING_UTILS_HH_ #include +#include #include #include @@ -29,6 +30,7 @@ #include "gz/rendering/config.hh" #include "gz/rendering/Export.hh" #include "gz/rendering/RayQuery.hh" +#include "gz/rendering/Image.hh" namespace gz @@ -111,6 +113,13 @@ namespace gz gz::math::Matrix3d projectionToCameraIntrinsic( const gz::math::Matrix4d &_projectionMatrix, double _width, double _height); + + /// \brief convert an RGB image data into bayer image data + /// \param[in] _image Input RGB image + /// \param[in] _bayerFormat Bayer format to convert to + /// \return Image in bayer format + GZ_RENDERING_VISIBLE + Image convertRGBToBayer(const Image &_image, PixelFormat _bayerFormat); } } } diff --git a/ogre/src/OgreRenderTarget.cc b/ogre/src/OgreRenderTarget.cc index 4a8a1adcf..0b961d8c8 100644 --- a/ogre/src/OgreRenderTarget.cc +++ b/ogre/src/OgreRenderTarget.cc @@ -46,6 +46,9 @@ #include "gz/rendering/ogre/OgreScene.hh" #include "gz/rendering/ogre/OgreCamera.hh" #include "gz/rendering/ogre/OgreIncludes.hh" +#include "gz/rendering/Utils.hh" + +#include using namespace gz; using namespace rendering; @@ -71,7 +74,6 @@ void OgreRenderTarget::Copy(Image &_image) const if (nullptr == this->RenderTarget()) return; - // TODO(anyone): handle Bayer conversions // TODO(anyone): handle ogre version differences if (_image.Width() != this->width || _image.Height() != this->height) @@ -80,10 +82,30 @@ void OgreRenderTarget::Copy(Image &_image) const return; } - void* data = _image.Data(); - Ogre::PixelFormat imageFormat = OgreConversions::Convert(_image.Format()); - Ogre::PixelBox ogrePixelBox(this->width, this->height, 1, imageFormat, data); - this->RenderTarget()->copyContentsToMemory(ogrePixelBox); + Ogre::PixelFormat imageFormat; + if ((_image.Format() == PF_BAYER_RGGB8) || + (_image.Format() == PF_BAYER_BGGR8) || + (_image.Format() == PF_BAYER_GBRG8) || + (_image.Format() == PF_BAYER_GRBG8)) + { + // create tmp color image to get data from gpu + imageFormat = OgreConversions::Convert(PF_R8G8B8); + Image colorImage(this->width, this->height, PF_R8G8B8); + void *data = colorImage.Data(); + Ogre::PixelBox ogrePixelBox( + this->width, this->height, 1, imageFormat, data); + this->RenderTarget()->copyContentsToMemory(ogrePixelBox); + // convert color image to bayer image + _image = gz::rendering::convertRGBToBayer(colorImage, _image.Format()); + } + else + { + imageFormat = OgreConversions::Convert(_image.Format()); + void *data = _image.Data(); + Ogre::PixelBox ogrePixelBox( + this->width, this->height, 1, imageFormat, data); + this->RenderTarget()->copyContentsToMemory(ogrePixelBox); + } } ////////////////////////////////////////////////// @@ -361,7 +383,18 @@ void OgreRenderTexture::DestroyTarget() void OgreRenderTexture::BuildTarget() { Ogre::TextureManager &manager = Ogre::TextureManager::getSingleton(); - Ogre::PixelFormat ogreFormat = OgreConversions::Convert(this->format); + Ogre::PixelFormat ogreFormat; + if ((this->format == PF_BAYER_RGGB8) || + (this->format == PF_BAYER_BGGR8) || + (this->format == PF_BAYER_GBRG8) || + (this->format == PF_BAYER_GRBG8)) + { + ogreFormat = OgreConversions::Convert(PF_R8G8B8); + } + else + { + ogreFormat = OgreConversions::Convert(this->format); + } // check if target fsaa is supported unsigned int fsaa = 0; diff --git a/ogre2/src/Ogre2RenderTarget.cc b/ogre2/src/Ogre2RenderTarget.cc index 06d087eac..f9209e637 100644 --- a/ogre2/src/Ogre2RenderTarget.cc +++ b/ogre2/src/Ogre2RenderTarget.cc @@ -26,6 +26,9 @@ #include "gz/rendering/ogre2/Ogre2Material.hh" #include "gz/rendering/ogre2/Ogre2RenderTarget.hh" #include "gz/rendering/ogre2/Ogre2Scene.hh" +#include "gz/rendering/Utils.hh" + +#include namespace gz { @@ -360,7 +363,18 @@ void Ogre2RenderTarget::Copy(Image &_image) const return; } - Ogre::PixelFormatGpu dstOgrePf = Ogre2Conversions::Convert(_image.Format()); + Ogre::PixelFormatGpu dstOgrePf; + if ((_image.Format() == PF_BAYER_RGGB8) || + (_image.Format() == PF_BAYER_BGGR8) || + (_image.Format() == PF_BAYER_GBRG8) || + (_image.Format() == PF_BAYER_GRBG8)) + { + dstOgrePf = Ogre2Conversions::Convert(PF_R8G8B8); + } + else + { + dstOgrePf = Ogre2Conversions::Convert(_image.Format()); + } Ogre::TextureGpu *texture = this->RenderTarget(); if (Ogre::PixelFormatGpuUtils::isSRgb(dstOgrePf) != @@ -385,10 +399,26 @@ void Ogre2RenderTarget::Copy(Image &_image) const static_cast(Ogre::PixelFormatGpuUtils::getSizeBytes( texture->getInternalWidth(), texture->getInternalHeight(), 1u, 1u, dstOgrePf, 1u))); - dstBox.data = _image.Data(); - Ogre::Image2::copyContentsToMemory(texture, texture->getEmptyBox(0u), dstBox, - dstOgrePf); + if ((_image.Format() == PF_BAYER_RGGB8) || + (_image.Format() == PF_BAYER_BGGR8) || + (_image.Format() == PF_BAYER_GBRG8) || + (_image.Format() == PF_BAYER_GRBG8)) + { + // create tmp color image to get data from gpu + Image colorImage(this->width, this->height, PF_R8G8B8); + dstBox.data = colorImage.Data(); + Ogre::Image2::copyContentsToMemory( + texture, texture->getEmptyBox(0u), dstBox, dstOgrePf); + // convert color image to bayer image + _image = gz::rendering::convertRGBToBayer(colorImage, _image.Format()); + } + else + { + dstBox.data = _image.Data(); + Ogre::Image2::copyContentsToMemory( + texture, texture->getEmptyBox(0u), dstBox, dstOgrePf); + } } ////////////////////////////////////////////////// diff --git a/src/PixelFormat.cc b/src/PixelFormat.cc index 2a2275105..948f52683 100644 --- a/src/PixelFormat.cc +++ b/src/PixelFormat.cc @@ -31,8 +31,8 @@ const char *PixelUtil::names[PF_COUNT] = "B8G8R8", "BAYER_RGGB8", "BAYER_BGGR8", - "BAYER_GBGR8", - "BAYER_GRGB8", + "BAYER_GBRG8", + "BAYER_GRBG8", "FLOAT32_R", "FLOAT32_RGBA", "FLOAT32_RGB", @@ -52,13 +52,13 @@ const unsigned char PixelUtil::channelCounts[PF_COUNT] = // B8G8R8 3, // BAYER_RGGB8 - 4, + 1, // BAYER_BGGR8 - 4, - // BAYER_GBGR8 - 4, - // BAYER_GRGB8 - 4, + 1, + // BAYER_GBRG8 + 1, + // BAYER_GRBG8 + 1, // PF_FLOAT32_R 1, // PF_FLOAT32_RGBA @@ -86,9 +86,9 @@ const unsigned char PixelUtil::channelByteCounts[PF_COUNT] = 1, // BAYER_BGGR8 1, - // BAYER_GBGR8 + // BAYER_GBRG8 1, - // BAYER_GRGB8 + // BAYER_GRBG8 1, // PF_FLOAT32_R 4, diff --git a/src/Utils.cc b/src/Utils.cc index a65d6b44f..f6ddcf396 100644 --- a/src/Utils.cc +++ b/src/Utils.cc @@ -26,8 +26,10 @@ #include "gz/rendering/Camera.hh" #include "gz/rendering/RayQuery.hh" +#include "gz/rendering/PixelFormat.hh" #include "gz/rendering/Utils.hh" + namespace gz { namespace rendering @@ -248,6 +250,149 @@ gz::math::AxisAlignedBox transformAxisAlignedBox( } return gz::math::AxisAlignedBox(min, max); } + +///////////////////////////////////////////////// +Image convertRGBToBayer(const Image &_image, PixelFormat _bayerFormat) +{ + const unsigned char *sourceImageData = _image.Data(); + + unsigned int width = _image.Width(); + unsigned int height = _image.Height(); + + Image destImage(width, height, _bayerFormat); + unsigned char *destImageData = destImage.Data(); + + if (_bayerFormat == PF_BAYER_RGGB8) + { + for (unsigned int i=0; i < width; i++) + { + for (unsigned int j=0; j < height; j++) + { + if (j%2) + { + if (i%2) + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+2]; + } + else + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+1]; + } + } + else + { + if (i%2) + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+1]; + } + else + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+0]; + } + } + } + } + } + + else if (_bayerFormat == PF_BAYER_BGGR8) + { + for (unsigned int i=0; i < width; i++) + { + for (unsigned int j=0; j < height; j++) + { + if (j%2) + { + if (i%2) + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+0]; + } + else + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+1]; + } + } + else + { + if (i%2) + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+1]; + } + else + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+2]; + } + } + } + } + } + + else if (_bayerFormat == PF_BAYER_GBRG8) + { + for (unsigned int i=0; i < width; i++) + { + for (unsigned int j=0; j < height; j++) + { + if (j%2) + { + if (i%2) + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+1]; + } + else + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+2]; + } + } + else + { + if (i%2) + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+0]; + } + else + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+1]; + } + } + } + } + } + + else if (_bayerFormat == PF_BAYER_GRBG8) + { + for (unsigned int i=0; i < width; i++) + { + for (unsigned int j=0; j < height; j++) + { + if (j%2) + { + if (i%2) + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+1]; + } + else + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+0]; + } + } + else + { + if (i%2) + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+2]; + } + else + { + destImageData[i+j*width] = sourceImageData[i*3+j*width*3+1]; + } + } + } + } + } + + return destImage; +} + } } }