]> OCCT Git - occt.git/commitdiff
0032841: Visualization - add 16-bit grayscale pixel format to Image_PixMap
authorkgv <kgv@opencascade.com>
Tue, 1 Mar 2022 19:34:31 +0000 (22:34 +0300)
committersmoskvin <smoskvin@opencascade.com>
Thu, 3 Mar 2022 17:07:53 +0000 (20:07 +0300)
Added Image_Format_Gray16 pixel format definition, which could be uploaded into GL_R16 texture.
Added Image_Format_GrayF_half mapped to GL_R16F texture.

src/Image/Image_AlienPixMap.cxx
src/Image/Image_Format.hxx
src/Image/Image_PixMap.cxx
src/Image/Image_PixMap.hxx
src/Media/Media_Frame.cxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_FrameBuffer.cxx
src/OpenGl/OpenGl_GlFunctions.cxx
src/OpenGl/OpenGl_GlTypes.hxx
src/OpenGl/OpenGl_TextureFormat.cxx

index fafaf56d6cbfed135ac4d3fae9b1802815ae2c81..99b84acebda1952d1d696cc38e2f2273e0c31269 100644 (file)
@@ -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;
   }
index 6c94daa3da6f03e4dcb13ad48f630593971398c0..c087093cf4326fba9d72104a82fa751c4badacbb 100644 (file)
@@ -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
index 02d7bdad7d7ab2579a122e43ba33f4c0c78c1f3d..d1ddea2237a4789a43df9edce254cf31810e6adf 100644 (file)
@@ -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<Image_ColorBGRF> (theY, theX);
       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), 1.0f)); // opaque
     }
+    case Image_Format_GrayF_half:
+    {
+      const uint16_t& aPixel = Value<uint16_t> (theY, theX);
+      return Quantity_ColorRGBA (NCollection_Vec4<float> (ConvertFromHalfFloat (aPixel), 0.0f, 0.0f, 1.0f));
+    }
     case Image_Format_RGF_half:
     {
       const NCollection_Vec2<uint16_t>& aPixel = Value<NCollection_Vec2<uint16_t>> (theY, theX);
@@ -366,13 +373,20 @@ Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
     case Image_Format_Gray:
     {
       const Standard_Byte& aPixel = Value<Standard_Byte> (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<Standard_Byte> (theY, theX);
       return Quantity_ColorRGBA (1.0f, 1.0f, 1.0f, float(aPixel) / 255.0f);
     }
+    case Image_Format_Gray16:
+    {
+      const uint16_t& aPixel = Value<uint16_t> (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<uint16_t> (theY, theX);
+      aPixel = ConvertToHalfFloat (aColor.r());
+      return;
+    }
     case Image_Format_RGF_half:
     {
       NCollection_Vec2<uint16_t>& aPixel = ChangeValue<NCollection_Vec2<uint16_t>> (theY, theX);
@@ -585,6 +605,11 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
       ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(aColor.a() * 255.0f);
       return;
     }
+    case Image_Format_Gray16:
+    {
+      ChangeValue<uint16_t> (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<uint16_t> (aRow, aCol);
+          if (aPixel != 0)
+          {
+            aPixel = 65535;
+          }
+        }
+      }
+      break;
+    }
     case Image_Format_RGB:
     case Image_Format_BGR:
     case Image_Format_RGB32:
index f155a660abe1277a41b8c804ed9303ec8358b798..46e0dd2f7bfc5377e294b8af46527d5526cb645d 100644 (file)
@@ -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();
index 94d8843c529b97a060de132573d295299ad2528a..bcd80e596d2397a5ea436c960c3a0cac88700399 100644 (file)
@@ -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:
index 0f269886e91fefe66d10214677fbc736bf37951b..645f67265515b4967b83f9e5489d04f98c58933a 100644 (file)
@@ -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);
       }
     }
index b49f9cfcba04929f7b94c2b9b201705770bc2470..b7c3972f79f371de14cae4570302448ce002d1cb 100644 (file)
@@ -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
index 2d7d0328cbff754f1ececf9f21dda72435a12ed7..ca907ab85413600feb99e2523a33940023c64340 100644 (file)
@@ -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;
index 3eda7a2cb44ee7f3f45533716cdbda7b257b3516..e3b45a46d08d5455569ecbeff288cde5825f0b9f 100644 (file)
@@ -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");
index 165a3678480ba7d18aa64efb0d7be626d2bccbf2..25138e4fd11da2ba3d0358639936acc6d59bcfa0 100644 (file)
@@ -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
index 31f62cc39fc3ab1168a680ba623fe4136c960234..bbd24dfc7a0663a7e1e1131f507ebe47a3784dcd 100644 (file)
@@ -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