0025544: Visualization, TKOpenGl - support grayscale textures
authorkgv <kgv@opencascade.com>
Thu, 4 Dec 2014 12:31:31 +0000 (15:31 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 11 Dec 2014 12:37:15 +0000 (15:37 +0300)
Image_PixMap::ImgFormat - extend enumeration by ImgAlpha and ImgAlphaF.
OpenGl_Workspace::setTextureParams() - specify GL_REPLACE for 1-component textures with disabled modulation.
OpenGl_Texture::GetDataFormat() - return GL_LUMINANCE format for ImgGray format and GL_ALPHA for ImgAlpha.

vmarkerstest - override pixel format for grayscale images to ImgAlpha.

Add test case bugs/vis/bug25544_graytexture.

13 files changed:
src/Font/Font_FTFont.cxx
src/Graphic3d/Graphic3d_MarkerImage.cxx
src/Image/Image_AlienPixMap.cxx
src/Image/Image_PixMap.cxx
src/Image/Image_PixMap.hxx
src/OpenGl/OpenGl_AspectMarker.cxx
src/OpenGl/OpenGl_Font.cxx
src/OpenGl/OpenGl_GraphicDriver_7.cxx
src/OpenGl/OpenGl_PointSprite.cxx
src/OpenGl/OpenGl_Texture.cxx
src/OpenGl/OpenGl_Workspace.cxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx
tests/bugs/vis/bug25544_graytexture [new file with mode: 0644]

index 213f6b6..f4d203b 100755 (executable)
@@ -164,7 +164,7 @@ bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
   {
     return false;
   }
-  if (!myGlyphImg.InitWrapper (Image_PixMap::ImgGray, aBitmap.buffer,
+  if (!myGlyphImg.InitWrapper (Image_PixMap::ImgAlpha, aBitmap.buffer,
                                aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
   {
     return false;
index ceb1eac..2236590 100755 (executable)
@@ -98,7 +98,11 @@ Handle(TColStd_HArray1OfByte) Graphic3d_MarkerImage::GetBitMapArray (const Stand
       Quantity_Color aColor = myImage->PixelColor (aColumn, aRow, anAlphaValue);
       Standard_Boolean aBitOn = Standard_False;
 
-      if (myImage->Format() == Image_PixMap::ImgGray)
+      if (myImage->Format() == Image_PixMap::ImgAlpha)
+      {
+        aBitOn = anAlphaValue > theAlphaValue;
+      }
+      else if (myImage->Format() == Image_PixMap::ImgGray)
       {
         aBitOn = aColor.Red() > theAlphaValue;
       }
@@ -142,7 +146,7 @@ const Handle(Image_PixMap)& Graphic3d_MarkerImage::GetImage()
   const Standard_Integer aLowerIndex      = myBitMap->Lower();
 
   myImage = new Image_PixMap();
-  myImage->InitZero (Image_PixMap::ImgGray, aSize + myMargin * 2, aSize + myMargin * 2);
+  myImage->InitZero (Image_PixMap::ImgAlpha, aSize + myMargin * 2, aSize + myMargin * 2);
   for (Standard_Integer aRowIter = 0; aRowIter < myHeight; aRowIter++)
   {
     Standard_Byte* anImageRow = myImage->ChangeRow (aRowIter + aRowOffset);
@@ -169,14 +173,15 @@ const Handle(Image_PixMap)& Graphic3d_MarkerImage::GetImageAlpha()
 
   if (!myImage.IsNull())
   {
-    if (myImage->Format() == Image_PixMap::ImgGray)
+    if (myImage->Format() == Image_PixMap::ImgGray
+     || myImage->Format() == Image_PixMap::ImgAlpha)
     {
       myImageAlpha = myImage;
     }
     else
     {
       myImageAlpha = new Image_PixMap();
-      myImageAlpha->InitZero (Image_PixMap::ImgGray, myImage->Width(), myImage->Height());
+      myImageAlpha->InitZero (Image_PixMap::ImgAlpha, myImage->Width(), myImage->Height());
       myImageAlpha->SetTopDown (Standard_False);
       Quantity_Parameter anAlpha;
       for (Standard_Size aRowIter = 0; aRowIter < myImage->Height(); aRowIter++)
index a264254..76a9a0e 100644 (file)
@@ -78,6 +78,7 @@ namespace
     switch (theFormat)
     {
       case Image_PixMap::ImgGrayF:
+      case Image_PixMap::ImgAlphaF:
         return FIT_FLOAT;
       case Image_PixMap::ImgRGBAF:
         return FIT_RGBAF;
@@ -90,6 +91,7 @@ namespace
       case Image_PixMap::ImgRGB:
       case Image_PixMap::ImgBGR:
       case Image_PixMap::ImgGray:
+      case Image_PixMap::ImgAlpha:
         return FIT_BITMAP;
       default:
         return FIT_UNKNOWN;
@@ -448,7 +450,8 @@ bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
     }
     case FIF_EXR:
     {
-      if (Format() == Image_PixMap::ImgGray)
+      if (Format() == Image_PixMap::ImgGray
+       || Format() == Image_PixMap::ImgAlpha)
       {
         anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_FLOAT);
       }
index 61cac86..0cb8815 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <Image_PixMap.hxx>
 #include <NCollection_AlignedAllocator.hxx>
+#include <Standard_ProgramError.hxx>
 
 #include <algorithm>
 
@@ -48,6 +49,7 @@ Standard_Size Image_PixMap::SizePixelBytes (const Image_PixMap::ImgFormat thePix
   switch (thePixelFormat)
   {
     case ImgGrayF:
+    case ImgAlphaF:
       return sizeof(float);
     case ImgRGBAF:
     case ImgBGRAF:
@@ -65,17 +67,32 @@ Standard_Size Image_PixMap::SizePixelBytes (const Image_PixMap::ImgFormat thePix
     case ImgBGR:
       return 3;
     case ImgGray:
-    default:
+    case ImgAlpha:
+      return 1;
+    case ImgUNKNOWN:
       return 1;
   }
+  return 1;
 }
 
 // =======================================================================
-// function : setFormat
+// function : SetFormat
 // purpose  :
 // =======================================================================
-void Image_PixMap::setFormat (Image_PixMap::ImgFormat thePixelFormat)
+void Image_PixMap::SetFormat (Image_PixMap::ImgFormat thePixelFormat)
 {
+  if (myImgFormat == thePixelFormat)
+  {
+    return;
+  }
+
+  if (!IsEmpty()
+    && SizePixelBytes (myImgFormat) != SizePixelBytes (thePixelFormat))
+  {
+    Standard_ProgramError::Raise ("Image_PixMap::SetFormat() - incompatible pixel format");
+    return;
+  }
+
   myImgFormat = thePixelFormat;
 }
 
@@ -201,6 +218,12 @@ Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
                              Quantity_Parameter (Standard_Real (aPixel)),
                              Quantity_TOC_RGB);
     }
+    case ImgAlphaF:
+    {
+      const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
+      theAlpha = aPixel;
+      return Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB);
+    }
     case ImgRGBAF:
     {
       const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX);
@@ -300,11 +323,19 @@ Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
                              Quantity_Parameter (Standard_Real (aPixel) / 255.0),
                              Quantity_TOC_RGB);
     }
-    default:
+    case ImgAlpha:
     {
-      // not supported image type
-      theAlpha = 0.0; // transparent
-      return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
+      const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
+      theAlpha = Standard_Real (aPixel) / 255.0;
+      return Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB);
+    }
+    case ImgUNKNOWN:
+    {
+      break;
     }
   }
+
+  // unsupported image type
+  theAlpha = 0.0; // transparent
+  return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
 }
index fe64ff3..9cf87fc 100644 (file)
@@ -30,14 +30,16 @@ public:
   //! This enumeration define packed image plane formats
   typedef enum tagFormat {
       ImgUNKNOWN = 0, //!< unsupported or unknown format
-      ImgGray    = 1, //!< 1 byte per pixel
+      ImgGray    = 1, //!< 1 byte per pixel, intensity of the color
+      ImgAlpha,       //!< 1 byte per pixel, transparency
       ImgRGB,         //!< 3 bytes packed RGB image plane
       ImgBGR,         //!< same as RGB but with different components order
       ImgRGB32,       //!< 4 bytes packed RGB image plane (1 extra byte for alignment, may have undefined value)
       ImgBGR32,       //!< same as RGB but with different components order
       ImgRGBA,        //!< 4 bytes packed RGBA image plane
       ImgBGRA,        //!< same as RGBA but with different components order
-      ImgGrayF,       //!< 1 float  (4-bytes) per pixel (1-component plane)
+      ImgGrayF,       //!< 1 float  (4-bytes) per pixel (1-component plane), intensity of the color
+      ImgAlphaF,      //!< 1 float  (4-bytes) per pixel (1-component plane), transparency
       ImgRGBF,        //!< 3 floats (12-bytes) RGB image plane
       ImgBGRF,        //!< same as RGBF but with different components order
       ImgRGBAF,       //!< 4 floats (16-bytes) RGBA image plane
@@ -59,6 +61,12 @@ public: // high-level API
     return myImgFormat;
   }
 
+  //! Override pixel format specified by InitXXX() methods.
+  //! Will throw exception if pixel size of new format is not equal to currently initialized format.
+  //! Intended to switch formats indicating different interpretation of the same data
+  //! (e.g. ImgGray and ImgAlpha).
+  Standard_EXPORT void SetFormat (const ImgFormat thePixelFormat);
+
   //! @return image width in pixels
   inline Standard_Size Width() const
   {
@@ -260,11 +268,6 @@ public: //! @name low-level API for batch-processing (pixels reading / compariso
 
 protected:
 
-  //! Setup pixel format
-  Standard_EXPORT void setFormat (ImgFormat thePixelFormat);
-
-protected:
-
   Image_PixMapData myData;      //!< data buffer
   ImgFormat        myImgFormat; //!< pixel format
 
index c679aea..4eecb22 100644 (file)
@@ -1421,7 +1421,7 @@ Handle(Image_PixMap) MergeImages (const Handle(Image_PixMap)& theImage1,
   const Standard_Integer aMaxHeight = Max (aHeight1,  aHeight2);
   const Standard_Integer aSize      = Max (aMaxWidth, aMaxHeight);
 
-  aResultImage->InitZero (Image_PixMap::ImgGray, aSize, aSize);
+  aResultImage->InitZero (Image_PixMap::ImgAlpha, aSize, aSize);
 
   if (!theImage1.IsNull())
   {
@@ -1714,8 +1714,8 @@ void OpenGl_AspectMarker::Resources::BuildSprites (const Handle(OpenGl_Context)&
           const Standard_Integer aSize = Max (aWidth + 2, aHeight + 2); // includes extra margin
           anImage  = new Image_PixMap();
           anImageA = new Image_PixMap();
-          anImage ->InitZero (Image_PixMap::ImgBGRA, aSize, aSize);
-          anImageA->InitZero (Image_PixMap::ImgGray, aSize, aSize);
+          anImage ->InitZero (Image_PixMap::ImgBGRA,  aSize, aSize);
+          anImageA->InitZero (Image_PixMap::ImgAlpha, aSize, aSize);
 
           // we draw a set of circles
           Image_ColorBGRA aColor32;
index 2b888b6..c29f3c7 100755 (executable)
@@ -117,7 +117,7 @@ bool OpenGl_Font::createTexture (const Handle(OpenGl_Context)& theCtx)
   Handle(OpenGl_Texture)& aTexture = myTextures.ChangeLast();
 
   Image_PixMap aBlackImg;
-  if (!aBlackImg.InitZero (Image_PixMap::ImgGray, Standard_Size(aTextureSizeX), Standard_Size(aTextureSizeY))
+  if (!aBlackImg.InitZero (Image_PixMap::ImgAlpha, Standard_Size(aTextureSizeX), Standard_Size(aTextureSizeY))
    || !aTexture->Init (theCtx, aBlackImg, Graphic3d_TOT_2D)) // myTextureFormat
   {
     TCollection_ExtendedString aMsg;
index 5f40749..6340198 100644 (file)
@@ -266,6 +266,15 @@ inline bool getDataFormat (const Image_PixMap& theData,
       thePixelFormat = GL_BGRA;
       theDataType    = GL_FLOAT;
       return true;
+  #else
+    case Image_PixMap::ImgGray:
+    case Image_PixMap::ImgGrayF:
+    case Image_PixMap::ImgBGR:
+    case Image_PixMap::ImgBGRA:
+    case Image_PixMap::ImgBGR32:
+    case Image_PixMap::ImgBGRF:
+    case Image_PixMap::ImgBGRAF:
+      return false;
   #endif
     case Image_PixMap::ImgRGB:
       thePixelFormat = GL_RGB;
@@ -284,9 +293,13 @@ inline bool getDataFormat (const Image_PixMap& theData,
       thePixelFormat = GL_RGBA;
       theDataType    = GL_FLOAT;
       return true;
-    default:
+    case Image_PixMap::ImgAlpha:
+    case Image_PixMap::ImgAlphaF:
+      return false; // GL_ALPHA is no more supported in core context
+    case Image_PixMap::ImgUNKNOWN:
       return false;
   }
+  return false;
 }
 
 Standard_Boolean OpenGl_GraphicDriver::BufferDump (const Graphic3d_CView&      theCView,
index 181f5f4..1f6023c 100755 (executable)
@@ -31,6 +31,7 @@ OpenGl_PointSprite::OpenGl_PointSprite()
   myBitmapList (0)
 {
   //myParams->SetFilter (Graphic3d_TOTF_NEAREST);
+  myParams->SetModulate (Standard_False);
   myParams->SetGenMode (Graphic3d_TOTM_SPRITE,
                         Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f),
                         Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
index 72aafc4..e5b4287 100644 (file)
@@ -181,14 +181,37 @@ bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx,
   {
     case Image_PixMap::ImgGrayF:
     {
-      theTextFormat = GL_ALPHA8; // GL_R8, GL_R32F
-      thePixelFormat = GL_ALPHA; // GL_RED
-      theDataType    = GL_FLOAT;
+      if (theCtx->core11 == NULL)
+      {
+        theTextFormat  = GL_R8;  // GL_R32F
+        thePixelFormat = GL_RED;
+      }
+      else
+      {
+        theTextFormat  = GL_LUMINANCE8;
+        thePixelFormat = GL_LUMINANCE;
+      }
+      theDataType = GL_FLOAT;
+      return true;
+    }
+    case Image_PixMap::ImgAlphaF:
+    {
+      if (theCtx->core11 == NULL)
+      {
+        theTextFormat  = GL_R8;  // GL_R32F
+        thePixelFormat = GL_RED;
+      }
+      else
+      {
+        theTextFormat  = GL_ALPHA8;
+        thePixelFormat = GL_ALPHA;
+      }
+      theDataType = GL_FLOAT;
       return true;
     }
     case Image_PixMap::ImgRGBAF:
     {
-      theTextFormat = GL_RGBA8; // GL_RGBA32F
+      theTextFormat  = GL_RGBA8; // GL_RGBA32F
       thePixelFormat = GL_RGBA;
       theDataType    = GL_FLOAT;
       return true;
@@ -206,7 +229,7 @@ bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx,
     }
     case Image_PixMap::ImgRGBF:
     {
-      theTextFormat = GL_RGB8; // GL_RGB32F
+      theTextFormat  = GL_RGB8; // GL_RGB32F
       thePixelFormat = GL_RGB;
       theDataType    = GL_FLOAT;
       return true;
@@ -282,16 +305,40 @@ bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx,
     }
     case Image_PixMap::ImgGray:
     {
-      theTextFormat = GL_ALPHA8; // GL_R8
-      thePixelFormat = GL_ALPHA; // GL_RED
-      theDataType    = GL_UNSIGNED_BYTE;
+      if (theCtx->core11 == NULL)
+      {
+        theTextFormat  = GL_R8;
+        thePixelFormat = GL_RED;
+      }
+      else
+      {
+        theTextFormat  = GL_LUMINANCE8;
+        thePixelFormat = GL_LUMINANCE;
+      }
+      theDataType = GL_UNSIGNED_BYTE;
       return true;
     }
-    default:
+    case Image_PixMap::ImgAlpha:
+    {
+      if (theCtx->core11 == NULL)
+      {
+        theTextFormat  = GL_R8;
+        thePixelFormat = GL_RED;
+      }
+      else
+      {
+        theTextFormat  = GL_ALPHA8;
+        thePixelFormat = GL_ALPHA;
+      }
+      theDataType = GL_UNSIGNED_BYTE;
+      return true;
+    }
+    case Image_PixMap::ImgUNKNOWN:
     {
       return false;
     }
   }
+  return false;
 }
 
 // =======================================================================
index ad95d7d..75afc33 100644 (file)
@@ -367,6 +367,17 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&
   OpenGl_Utils::Rotate    (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f);
   glLoadMatrixf (aTextureMat);
 
+  GLint anEnvMode = GL_MODULATE; // lighting mode
+  if (!aParams->IsModulate())
+  {
+    anEnvMode = GL_DECAL;
+    if (theTexture->GetFormat() == GL_ALPHA
+     || theTexture->GetFormat() == GL_LUMINANCE)
+    {
+      anEnvMode = GL_REPLACE;
+    }
+  }
+
   // setup generation of texture coordinates
   switch (aParams->GenMode())
   {
@@ -416,7 +427,7 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&
       {
         glEnable  (GL_POINT_SPRITE);
         glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
-        glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+        anEnvMode = GL_REPLACE;
         GetGlContext()->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
       }
       break;
@@ -426,10 +437,7 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&
   }
 
   // setup lighting
-  if (aParams->GenMode() != Graphic3d_TOTM_SPRITE)
-  {
-    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aParams->IsModulate() ? GL_MODULATE : GL_DECAL);
-  }
+  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
 #endif
 
   // get active sampler object to override default texture parameters
index ef27aac..9a3c184 100644 (file)
@@ -5051,6 +5051,14 @@ static Standard_Integer VMarkersTest (Draw_Interpretor&,
       std::cerr << "Could not load image from file '" << aFileName << "'!\n";
       return 1;
     }
+    if (anImage->Format() == Image_PixMap::ImgGray)
+    {
+      anImage->SetFormat (Image_PixMap::ImgAlpha);
+    }
+    else if (anImage->Format() == Image_PixMap::ImgGrayF)
+    {
+      anImage->SetFormat (Image_PixMap::ImgAlphaF);
+    }
     anAspect = new Graphic3d_AspectMarker3d (anImage);
   }
   else
diff --git a/tests/bugs/vis/bug25544_graytexture b/tests/bugs/vis/bug25544_graytexture
new file mode 100644 (file)
index 0000000..1f07e8f
--- /dev/null
@@ -0,0 +1,28 @@
+puts "============"
+puts "0025544: Visualization, TKOpenGl - support grayscale textures"
+puts "============"
+puts ""
+
+vinit View1
+vclear
+
+box b 1 2 3
+vaxo
+vsetdispmode 1
+vdisplay b
+vtexture b 1 -modulate on
+vfit
+
+set aColorMod [vreadpixel 290 180 rgb name]
+vdump $imagedir/${casename}_modulated.png
+
+vtexture b 1 -modulate off
+set aColorDec [vreadpixel 290 180 rgb name]
+vdump $imagedir/${casename}_decal.png
+
+if {"$aColorMod" != "GOLDENROD4"} {
+  puts "Error: wrong color with modulation ON"
+}
+if {"$aColorDec" != "GRAY80"} {
+  puts "Error: wrong color with modulation OFF"
+}