diff --git a/src/Image/Image_AlienPixMap.cxx b/src/Image/Image_AlienPixMap.cxx index fafaf56d6c..99b84acebd 100644 --- a/src/Image/Image_AlienPixMap.cxx +++ b/src/Image/Image_AlienPixMap.cxx @@ -66,6 +66,8 @@ namespace case FIT_RGBF: return Image_Format_RGBF; case FIT_RGBAF: return Image_Format_RGBAF; case FIT_FLOAT: return Image_Format_GrayF; + case FIT_INT16: + case FIT_UINT16: return Image_Format_Gray16; case FIT_BITMAP: { switch (theColorTypeFI) @@ -118,6 +120,8 @@ namespace case Image_Format_Gray: case Image_Format_Alpha: return FIT_BITMAP; + case Image_Format_Gray16: + return FIT_UINT16; default: return FIT_UNKNOWN; } @@ -304,6 +308,10 @@ namespace { return Image_Format_Gray; } + else if (theFormat == GUID_WICPixelFormat16bppGray) + { + return Image_Format_Gray16; + } return Image_Format_UNKNOWN; } @@ -318,6 +326,7 @@ namespace case Image_Format_BGR: return GUID_WICPixelFormat24bppBGR; case Image_Format_Gray: return GUID_WICPixelFormat8bppGray; case Image_Format_Alpha: return GUID_WICPixelFormat8bppGray; // GUID_WICPixelFormat8bppAlpha + case Image_Format_Gray16: return GUID_WICPixelFormat16bppGray; case Image_Format_GrayF: // GUID_WICPixelFormat32bppGrayFloat case Image_Format_AlphaF: case Image_Format_RGBAF: // GUID_WICPixelFormat128bppRGBAFloat @@ -1081,7 +1090,8 @@ bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName) { aFileFormat = GUID_ContainerFormatJpeg; } - else if (aFileNameLower.EndsWith (".tiff")) + else if (aFileNameLower.EndsWith (".tiff") + || aFileNameLower.EndsWith (".tif")) { aFileFormat = GUID_ContainerFormatTiff; } diff --git a/src/Image/Image_Format.hxx b/src/Image/Image_Format.hxx index 6c94daa3da..c087093cf4 100644 --- a/src/Image/Image_Format.hxx +++ b/src/Image/Image_Format.hxx @@ -33,9 +33,11 @@ enum Image_Format Image_Format_BGRF, //!< same as RGBF but with different components order Image_Format_RGBAF, //!< 4 floats (16-bytes) RGBA image plane Image_Format_BGRAF, //!< same as RGBAF but with different components order - Image_Format_RGF_half, //!< 2 half-floats (4-bytes) RG image plane + Image_Format_GrayF_half, //!< 1 half-float (2-bytes) intensity of color + Image_Format_RGF_half, //!< 2 half-floats (4-bytes) RG image plane Image_Format_RGBAF_half, //!< 4 half-floats (8-bytes) RGBA image plane + Image_Format_Gray16, //!< 2 bytes per pixel (unsigned short integer), intensity of the color }; -enum { Image_Format_NB = Image_Format_RGBAF_half + 1 }; +enum { Image_Format_NB = Image_Format_Gray16 + 1 }; #endif // _Image_Format_HeaderFile diff --git a/src/Image/Image_PixMap.cxx b/src/Image/Image_PixMap.cxx index 02d7bdad7d..d1ddea2237 100644 --- a/src/Image/Image_PixMap.cxx +++ b/src/Image/Image_PixMap.cxx @@ -62,8 +62,10 @@ namespace ImageFormatInfo(BGRF, 3, sizeof(float) * 3), ImageFormatInfo(RGBAF, 4, sizeof(float) * 4), ImageFormatInfo(BGRAF, 4, sizeof(float) * 4), + ImageFormatInfo(GrayF_half, 1, sizeof(uint16_t) * 1), ImageFormatInfo(RGF_half, 2, sizeof(uint16_t) * 2), ImageFormatInfo(RGBAF_half, 4, sizeof(uint16_t) * 4), + ImageFormatInfo(Gray16, 1, 2), CompressedImageFormatInfo(RGB_S3TC_DXT1, 3, 1), // DXT1 uses circa half a byte per pixel (64 bits per 4x4 block) CompressedImageFormatInfo(RGBA_S3TC_DXT1, 4, 1), CompressedImageFormatInfo(RGBA_S3TC_DXT3, 4, 1), // DXT3/5 uses circa 1 byte per pixel (128 bits per 4x4 block) @@ -296,6 +298,11 @@ Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX, const Image_ColorBGRF& aPixel = Value (theY, theX); return Quantity_ColorRGBA (NCollection_Vec4 (aPixel.r(), aPixel.g(), aPixel.b(), 1.0f)); // opaque } + case Image_Format_GrayF_half: + { + const uint16_t& aPixel = Value (theY, theX); + return Quantity_ColorRGBA (NCollection_Vec4 (ConvertFromHalfFloat (aPixel), 0.0f, 0.0f, 1.0f)); + } case Image_Format_RGF_half: { const NCollection_Vec2& aPixel = Value> (theY, theX); @@ -366,13 +373,20 @@ Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX, case Image_Format_Gray: { const Standard_Byte& aPixel = Value (theY, theX); - return Quantity_ColorRGBA (float(aPixel) / 255.0f, float(aPixel) / 255.0f, float(aPixel) / 255.0f, 1.0f); // opaque + const float anIntensity = float(aPixel) / 255.0f; + return Quantity_ColorRGBA (anIntensity, anIntensity, anIntensity, 1.0f); // opaque } case Image_Format_Alpha: { const Standard_Byte& aPixel = Value (theY, theX); return Quantity_ColorRGBA (1.0f, 1.0f, 1.0f, float(aPixel) / 255.0f); } + case Image_Format_Gray16: + { + const uint16_t& aPixel = Value (theY, theX); + const float anIntensity = float(aPixel) / 65535.0f; + return Quantity_ColorRGBA (anIntensity, anIntensity, anIntensity, 1.0f); // opaque + } case Image_Format_UNKNOWN: { break; @@ -453,6 +467,12 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX, aPixel.b() = aColor.b(); return; } + case Image_Format_GrayF_half: + { + uint16_t& aPixel = ChangeValue (theY, theX); + aPixel = ConvertToHalfFloat (aColor.r()); + return; + } case Image_Format_RGF_half: { NCollection_Vec2& aPixel = ChangeValue> (theY, theX); @@ -585,6 +605,11 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX, ChangeValue (theY, theX) = Standard_Byte(aColor.a() * 255.0f); return; } + case Image_Format_Gray16: + { + ChangeValue (theY, theX) = uint16_t(aColor.r() * 65535.0f); + return; + } case Image_Format_UNKNOWN: { return; @@ -686,6 +711,21 @@ void Image_PixMap::ToBlackWhite (Image_PixMap& theImage) } break; } + case Image_Format_Gray16: + { + for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow) + { + for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol) + { + uint16_t& aPixel = theImage.ChangeValue (aRow, aCol); + if (aPixel != 0) + { + aPixel = 65535; + } + } + } + break; + } case Image_Format_RGB: case Image_Format_BGR: case Image_Format_RGB32: diff --git a/src/Image/Image_PixMap.hxx b/src/Image/Image_PixMap.hxx index f155a660ab..46e0dd2f7b 100644 --- a/src/Image/Image_PixMap.hxx +++ b/src/Image/Image_PixMap.hxx @@ -62,6 +62,7 @@ public: public: // high-level API + //! Return pixel format. Image_Format Format() const { return myImgFormat; } //! Override pixel format specified by InitXXX() methods. @@ -70,41 +71,26 @@ public: // high-level API //! (e.g. ImgGray and ImgAlpha). Standard_EXPORT void SetFormat (const Image_Format thePixelFormat); - //! @return image width in pixels - inline Standard_Size Width() const - { - return myData.SizeX; - } + //! Return image width in pixels + Standard_Size Width() const { return myData.SizeX; } - //! @return image height in pixels - inline Standard_Size Height() const - { - return myData.SizeY; - } + //! Return image height in pixels + Standard_Size Height() const { return myData.SizeY; } - //! @return image width in pixels - inline Standard_Size SizeX() const - { - return myData.SizeX; - } + //! Return image width in pixels + Standard_Size SizeX() const { return myData.SizeX; } - //! @return image height in pixels - inline Standard_Size SizeY() const - { - return myData.SizeY; - } + //! Return image height in pixels + Standard_Size SizeY() const { return myData.SizeY; } - //! @return width / height. - inline Standard_Real Ratio() const + //! Return width / height. + Standard_Real Ratio() const { return (SizeY() > 0) ? (Standard_Real(SizeX()) / Standard_Real(SizeY())) : 1.0; } - //! @return true if data is NULL. - bool IsEmpty() const - { - return myData.IsEmpty(); - } + //! Return true if data is NULL. + bool IsEmpty() const { return myData.IsEmpty(); } //! Empty constructor. Initialize the NULL image plane. Standard_EXPORT Image_PixMap(); diff --git a/src/Media/Media_Frame.cxx b/src/Media/Media_Frame.cxx index 94d8843c52..bcd80e596d 100644 --- a/src/Media/Media_Frame.cxx +++ b/src/Media/Media_Frame.cxx @@ -56,6 +56,8 @@ Image_Format Media_Frame::FormatFFmpeg2Occt (int theFormat) return Image_Format_BGR; case AV_PIX_FMT_GRAY8: return Image_Format_Gray; + case AV_PIX_FMT_GRAY16: + return Image_Format_Gray16; default: return Image_Format_UNKNOWN; } @@ -90,6 +92,8 @@ int Media_Frame::FormatOcct2FFmpeg (Image_Format theFormat) return AV_PIX_FMT_GRAY8; case Image_Format_Alpha: return AV_PIX_FMT_GRAY8; + case Image_Format_Gray16: + return AV_PIX_FMT_GRAY16; case Image_Format_GrayF: case Image_Format_AlphaF: case Image_Format_RGF: @@ -97,6 +101,7 @@ int Media_Frame::FormatOcct2FFmpeg (Image_Format theFormat) case Image_Format_RGBF: case Image_Format_BGRAF: case Image_Format_BGRF: + case Image_Format_GrayF_half: case Image_Format_RGF_half: case Image_Format_RGBAF_half: case Image_Format_UNKNOWN: diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 0f269886e9..645f672655 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -176,6 +176,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) extDrawBuffers (Standard_False), extGS (NULL), extBgra(Standard_False), + extTexR16(Standard_False), extAnis(Standard_False), extPDS (Standard_False), atiMem (Standard_False), @@ -1552,6 +1553,10 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) mySupportedFormats->Add (Image_Format_BGR32); mySupportedFormats->Add (Image_Format_BGRA); } + if (extTexR16) + { + mySupportedFormats->Add (Image_Format_Gray16); + } if (arbTexFloat) { mySupportedFormats->Add (Image_Format_GrayF); @@ -1567,6 +1572,7 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) mySupportedFormats->Add (Image_Format_RGF); if (hasHalfFloatBuffer != OpenGl_FeatureNotAvailable) { + mySupportedFormats->Add (Image_Format_GrayF_half); mySupportedFormats->Add (Image_Format_RGF_half); } } diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index b49f9cfcba..b7c3972f79 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -1069,6 +1069,7 @@ public: //! @name extensions Standard_Boolean extDrawBuffers; //!< GL_EXT_draw_buffers OpenGl_ExtGS* extGS; //!< GL_EXT_geometry_shader4 Standard_Boolean extBgra; //!< GL_EXT_bgra or GL_EXT_texture_format_BGRA8888 on OpenGL ES + Standard_Boolean extTexR16; //!< GL_EXT_texture_norm16 on OpenGL ES; always available on desktop Standard_Boolean extAnis; //!< GL_EXT_texture_filter_anisotropic Standard_Boolean extPDS; //!< GL_EXT_packed_depth_stencil Standard_Boolean atiMem; //!< GL_ATI_meminfo diff --git a/src/OpenGl/OpenGl_FrameBuffer.cxx b/src/OpenGl/OpenGl_FrameBuffer.cxx index 2d7d0328cb..ca907ab854 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.cxx +++ b/src/OpenGl/OpenGl_FrameBuffer.cxx @@ -983,6 +983,17 @@ Standard_Boolean OpenGl_FrameBuffer::BufferDump (const Handle(OpenGl_Context)& t aType = GL_UNSIGNED_BYTE; break; } + case Image_Format_Gray16: + { + if (theGlCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES) + { + return false; + } + + aFormat = theBufferType == Graphic3d_BT_Depth ? GL_DEPTH_COMPONENT : GL_RED; + aType = GL_UNSIGNED_SHORT; + break; + } case Image_Format_GrayF: { if (theGlCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES) @@ -1090,6 +1101,7 @@ Standard_Boolean OpenGl_FrameBuffer::BufferDump (const Handle(OpenGl_Context)& t case Image_Format_Alpha: case Image_Format_AlphaF: return Standard_False; // GL_ALPHA is no more supported in core context + case Image_Format_GrayF_half: case Image_Format_RGF_half: case Image_Format_UNKNOWN: return Standard_False; diff --git a/src/OpenGl/OpenGl_GlFunctions.cxx b/src/OpenGl/OpenGl_GlFunctions.cxx index 3eda7a2cb4..e3b45a46d0 100644 --- a/src/OpenGl/OpenGl_GlFunctions.cxx +++ b/src/OpenGl/OpenGl_GlFunctions.cxx @@ -1733,6 +1733,7 @@ void OpenGl_GlFunctions::load (OpenGl_Context& theCtx, theCtx.arbTexRG = isGlGreaterEqualShort (3, 0) || checkExtensionShort ("GL_EXT_texture_rg"); theCtx.extBgra = checkExtensionShort ("GL_EXT_texture_format_BGRA8888"); + theCtx.extTexR16 = checkExtensionShort ("GL_EXT_texture_norm16"); theCtx.extAnis = checkExtensionShort ("GL_EXT_texture_filter_anisotropic"); theCtx.extPDS = isGlGreaterEqualShort (3, 0) || checkExtensionShort ("GL_OES_packed_depth_stencil"); @@ -2160,6 +2161,7 @@ void OpenGl_GlFunctions::load (OpenGl_Context& theCtx, || checkExtensionShort ("NV_depth_clamp"); theCtx.extBgra = isGlGreaterEqualShort (1, 2) || checkExtensionShort ("GL_EXT_bgra"); + theCtx.extTexR16 = true; theCtx.extAnis = checkExtensionShort ("GL_EXT_texture_filter_anisotropic"); theCtx.extPDS = checkExtensionShort ("GL_EXT_packed_depth_stencil"); theCtx.atiMem = checkExtensionShort ("GL_ATI_meminfo"); diff --git a/src/OpenGl/OpenGl_GlTypes.hxx b/src/OpenGl/OpenGl_GlTypes.hxx index 165a367848..25138e4fd1 100644 --- a/src/OpenGl/OpenGl_GlTypes.hxx +++ b/src/OpenGl/OpenGl_GlTypes.hxx @@ -333,6 +333,9 @@ typedef double GLclampd; #define GL_RGB8 0x8051 #define GL_RGBA8 0x8058 +// only in desktop OpenGL +#define GL_LUMINANCE16 0x8042 + // in core since OpenGL ES 3.0, extension GL_OES_rgb8_rgba8 #define GL_LUMINANCE8 0x8040 // GL_EXT_texture_format_BGRA8888 diff --git a/src/OpenGl/OpenGl_TextureFormat.cxx b/src/OpenGl/OpenGl_TextureFormat.cxx index 31f62cc39f..bbd24dfc7a 100644 --- a/src/OpenGl/OpenGl_TextureFormat.cxx +++ b/src/OpenGl/OpenGl_TextureFormat.cxx @@ -72,6 +72,7 @@ TCollection_AsciiString OpenGl_TextureFormat::FormatFormat (GLint theInternalFor case 0x803C: return "GL_ALPHA8"; case 0x803E: return "GL_ALPHA16"; case GL_LUMINANCE: return "GL_LUMINANCE"; + case GL_LUMINANCE16: return "GL_LUMINANCE16"; case GL_LUMINANCE_ALPHA: return "GL_LUMINANCE_ALPHA"; // case GL_DEPTH_COMPONENT: return "GL_DEPTH_COMPONENT"; @@ -219,6 +220,19 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte aFormat.SetDataType (GL_FLOAT); return aFormat; } + case Image_Format_GrayF_half: + { + aFormat.SetNbComponents (1); + aFormat.SetInternalFormat (GL_R16F); + aFormat.SetPixelFormat (GL_RED); + aFormat.SetDataType (GL_HALF_FLOAT); + if (theCtx->hasHalfFloatBuffer == OpenGl_FeatureInExtensions + && theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES) + { + aFormat.SetDataType (GL_HALF_FLOAT_OES); + } + return aFormat; + } case Image_Format_RGF_half: { aFormat.SetNbComponents (2); @@ -443,6 +457,28 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte aFormat.SetDataType (GL_UNSIGNED_BYTE); return aFormat; } + case Image_Format_Gray16: + { + if (!theCtx->extTexR16) + { + return OpenGl_TextureFormat(); + } + + aFormat.SetNbComponents (1); + if (useRedRedAlpha + || theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES) + { + aFormat.SetInternalFormat (GL_R16); + aFormat.SetPixelFormat (GL_RED); + } + else + { + aFormat.SetInternalFormat (GL_LUMINANCE16); + aFormat.SetPixelFormat (GL_LUMINANCE); + } + aFormat.SetDataType (GL_UNSIGNED_SHORT); + return aFormat; + } case Image_Format_UNKNOWN: { return OpenGl_TextureFormat(); @@ -509,7 +545,7 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindSizedFormat (const Handle(OpenGl_ aFormat.SetInternalFormat (theSizedFormat); aFormat.SetPixelFormat (GL_RED); aFormat.SetDataType (GL_HALF_FLOAT); - aFormat.SetImageFormat (Image_Format_GrayF); + aFormat.SetImageFormat (Image_Format_GrayF_half); if (theCtx->hasHalfFloatBuffer == OpenGl_FeatureInExtensions) { aFormat.SetDataType (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES