0023272: Image comparison algorithm
[occt.git] / src / Image / Image_PixMap.cxx
index 3065861..14b3f2a 100644 (file)
@@ -1,6 +1,6 @@
-// Created on: 2010-09-16
-// Created by: KGV
-// Copyright (c) 2010-2012 OPEN CASCADE SAS
+// Created on: 2012-07-18
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2012 OPEN CASCADE SAS
 //
 // The content of this file is subject to the Open CASCADE Technology Public
 // License Version 6.5 (the "License"). You may not use the content of this file
 // purpose or non-infringement. Please see the License for the specific terms
 // and conditions governing the rights and limitations under the License.
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
+#include <Image_PixMap.hxx>
+
+#ifndef _MSC_VER
+  #include <mm_malloc.h>
 #endif
 
-#ifdef HAVE_FREEIMAGE
-  #include <FreeImagePlus.h>
-  #include <Image_PixMap.ixx>
-  /* OCC22216 NOTE: linker dependency can be switched off by undefining macro */ 
-  #ifdef _MSC_VER
-  #pragma comment( lib, "FreeImage.lib" )
-  #pragma comment( lib, "FreeImagePlus.lib" )
-  #endif
+template<typename TypePtr>
+inline TypePtr MemAllocAligned (const Standard_Size& theBytesCount,
+                                const Standard_Size& theAlign = 16)
+{
+#if defined(_MSC_VER)
+  return (TypePtr )_aligned_malloc (theBytesCount, theAlign);
 #else
-  #include <Image_PixMap.ixx>
-  #include <fstream>
-
-  #if (defined(BYTE_ORDER)   && BYTE_ORDER==BIG_ENDIAN) || \
-      (defined(__BYTE_ORDER) && __BYTE_ORDER==__BIG_ENDIAN) || \
-       defined(__BIG_ENDIAN__)
-    #define THE_BIGENDIAN
-  #endif
-
-  // dummy class which can only dump to PPM format
-  class fipImage
-  {
-  public:
-
-    typedef struct tagRGBQuad {
-    #ifndef THE_BIGENDIAN
-      Standard_Byte rgbBlue;
-      Standard_Byte rgbGreen;
-      Standard_Byte rgbRed;
-    #else
-      Standard_Byte rgbRed;
-      Standard_Byte rgbGreen;
-      Standard_Byte rgbBlue;
-    #endif
-      Standard_Byte rgbReserved;
-    } RGBQuad_t;
-
-  public:
-
-    fipImage()
-    : myDataPtr(NULL),
-      mySizeX(0),
-      mySizeY(0),
-      myBytesPerLine(0),
-      myBytesPerPixel(3)
-    {
-      //
-    }
-
-    fipImage (const Standard_Integer theSizeX, const Standard_Integer theSizeY,
-              const Standard_Integer theBytesPerLine = 0, const Standard_Integer theBytesPerPixel = 3)
-    : myDataPtr(NULL),
-      mySizeX (theSizeX),
-      mySizeY (theSizeY),
-      myBytesPerLine (theBytesPerLine),
-      myBytesPerPixel (theBytesPerPixel)
-    {
-      if (myBytesPerLine == 0)
-      {
-        myBytesPerLine = mySizeX * myBytesPerPixel;
-      }
-      myDataPtr = new Standard_Byte[myBytesPerLine * mySizeY];
-    }
-
-    ~fipImage()
-    {
-      delete[] myDataPtr;
-    }
-
-    Standard_Integer getHeight() const
-    {
-      return mySizeY;
-    }
-
-    Standard_Integer getWidth() const
-    {
-      return mySizeX;
-    }
-
-    Standard_Integer getBytesPerPixel() const
-    {
-      return myBytesPerPixel;
-    }
-
-    Standard_Integer getBytesPerLine() const
-    {
-      return myBytesPerLine;
-    }
-
-    Standard_Byte* getData() const
-    {
-      return myDataPtr;
-    }
-
-    Standard_Byte* getScanLine (const Standard_Integer theRow) const
-    {
-      return &myDataPtr[theRow * myBytesPerLine];
-    }
-
-    Quantity_Color getPixelColor (const Standard_Integer theCol,
-                                  const Standard_Integer theRow,
-                                  Quantity_Parameter&    theAlpha) const
-    {
-      RGBQuad_t* aPixel = (RGBQuad_t* )&getScanLine (theRow)[theCol * myBytesPerPixel];
-      theAlpha = (myBytesPerPixel > 3) ? (Standard_Real (aPixel->rgbReserved) / 255.0) : 1.0;
-      return Quantity_Color (Standard_Real (aPixel->rgbRed)   / 255.0,
-                             Standard_Real (aPixel->rgbGreen) / 255.0,
-                             Standard_Real (aPixel->rgbBlue)  / 255.0,
-                             Quantity_TOC_RGB);
-    }
-
-    Standard_Boolean savePPM (const Standard_CString theFileName) const
-    {
-      // Open file
-      FILE* pFile = fopen (theFileName, "wb");
-      if (pFile == NULL)
-      {
-        return Standard_False;
-      }
-
-      // Write header
-      fprintf (pFile, "P6\n%d %d\n255\n", mySizeX, mySizeY);
-
-      // Write pixel data
-      Standard_Byte* aScanLine;
-      RGBQuad_t* aPixel;
-      // image stored upside-down
-      for (Standard_Integer aRow = mySizeY - 1; aRow >= 0; --aRow)
-      {
-        aScanLine = getScanLine (aRow);
-        for (Standard_Integer aCol = 0; aCol < mySizeX; ++aCol)
-        {
-          aPixel = (RGBQuad_t* )&aScanLine[aCol * myBytesPerPixel];
-          fwrite (&aPixel->rgbRed,   1, 1, pFile);
-          fwrite (&aPixel->rgbGreen, 1, 1, pFile);
-          fwrite (&aPixel->rgbBlue,  1, 1, pFile);
-        }
-      }
-
-      // Close file
-      fclose (pFile);
-      return Standard_True;
-    }
-
-    Standard_Integer getMaxRowAligmentBytes() const
-    {
-      Standard_Integer aDeltaBytes = myBytesPerLine - myBytesPerPixel * mySizeX;
-      for (Standard_Integer anAligment = 16; anAligment > 1; anAligment /= 2)
-      {
-        if (isRowAlignedTo (anAligment, aDeltaBytes))
-        {
-          return anAligment;
-        }
-      }
-      return 1;
-    }
-
-  private:
-
-    Standard_Boolean isRowAlignedTo (const Standard_Integer theAligmentBytes,
-                                     const Standard_Integer theDeltaBytes) const
-    {
-      return (theDeltaBytes < theAligmentBytes) &&
-             ((myBytesPerLine % theAligmentBytes) == 0);
-    }
+  return (TypePtr )     _mm_malloc (theBytesCount, theAlign);
+#endif
+}
 
-  private:
+inline void MemFreeAligned (void* thePtrAligned)
+{
+#if defined(_MSC_VER)
+  _aligned_free (thePtrAligned);
+#else
+  _mm_free (thePtrAligned);
+#endif
+}
 
-    Standard_Byte* myDataPtr;
-    Standard_Integer mySizeX;
-    Standard_Integer mySizeY;
-    Standard_Integer myBytesPerLine;
-    Standard_Integer myBytesPerPixel;
+IMPLEMENT_STANDARD_HANDLE (Image_PixMap, Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap, Standard_Transient)
 
-  };
-#endif
+// =======================================================================
+// function : Image_PixMap
+// purpose  :
+// =======================================================================
+Image_PixMap::Image_PixMap()
+: myImgFormat (Image_PixMap::ImgGray),
+  myIsOwnPointer (true)
+{
+  memset (&myData, 0, sizeof(myData));
+  myData.mySizeBPP   = 1;
+  myData.myTopToDown = 1;
+  setFormat (Image_PixMap::ImgGray);
+}
 
-#include <gp.hxx>
-#include <TCollection_AsciiString.hxx>
+// =======================================================================
+// function : ~Image_PixMap
+// purpose  :
+// =======================================================================
+Image_PixMap::~Image_PixMap()
+{
+  Clear();
+}
 
-//=======================================================================
-//function : Image_PixMap
-//purpose  :
-//=======================================================================
-Image_PixMap::Image_PixMap (const Standard_Integer theWidth,
-                            const Standard_Integer theHeight,
-                            const Image_TypeOfImage theType)
-:      Aspect_PixMap (theWidth, theHeight, 1),
-       myImage()
+Standard_Size Image_PixMap::SizePixelBytes (const Image_PixMap::ImgFormat thePixelFormat)
 {
-#ifdef HAVE_FREEIMAGE
-  FREE_IMAGE_TYPE aFIType = FIT_UNKNOWN;
-  int aBitsPerPixel = 0;
-  switch (theType)
+  switch (thePixelFormat)
   {
-    case Image_TOI_RGBA:
-      aFIType = FIT_BITMAP;
-      aBitsPerPixel = 32;
-      break;
-    case Image_TOI_RGBF:
-      aFIType = FIT_RGBF;
-      aBitsPerPixel = 96;
-      break;
-    case Image_TOI_RGBAF:
-      aFIType = FIT_RGBAF;
-      aBitsPerPixel = 128;
-      break;
-    case Image_TOI_FLOAT:
-      aFIType = FIT_FLOAT;
-      aBitsPerPixel = 32;
-      break;
-    case Image_TOI_RGB:
+    case ImgGrayF:
+      return sizeof(float);
+    case ImgRGBAF:
+    case ImgBGRAF:
+      return sizeof(float) * 4;
+    case ImgRGBF:
+    case ImgBGRF:
+      return sizeof(float) * 3;
+    case ImgRGBA:
+    case ImgBGRA:
+      return 4;
+    case ImgRGB32:
+    case ImgBGR32:
+      return 4;
+    case ImgRGB:
+    case ImgBGR:
+      return 3;
+    case ImgGray:
     default:
-      aFIType = FIT_BITMAP;
-      aBitsPerPixel = 24;
-      break;
-  }
-  myImage = new fipImage (aFIType, theWidth, theHeight, aBitsPerPixel);
-#else
-  Standard_Integer aBytesPerPixel = 0;
-  switch (theType)
-  {
-    case Image_TOI_RGBAF:
-      std::cerr << "Float formats not supported\n";
-    case Image_TOI_RGBA:
-      aBytesPerPixel = 4;
-      break;
-    case Image_TOI_RGBF:
-    case Image_TOI_FLOAT:
-      std::cerr << "Float formats not supported\n";
-    case Image_TOI_RGB:
-    default:
-      aBytesPerPixel = 3;
-      break;
+      return 1;
   }
-  myImage = new fipImage (theWidth, theHeight, 0, aBytesPerPixel);
-  //
-#endif
 }
 
-//=======================================================================
-//function : Image_PixMap
-//purpose  :
-//=======================================================================
-Image_PixMap::Image_PixMap (const Standard_PByte theDataPtr,
-                            const Standard_Integer theWidth, const Standard_Integer theHeight,
-                            const Standard_Integer thePitch, const Standard_Integer theBitsPerPixel,
-                            const Standard_Boolean theIsTopDown)
-:      Aspect_PixMap (theWidth, theHeight, 1),
-       myImage (new fipImage())
+// =======================================================================
+// function : setFormat
+// purpose  :
+// =======================================================================
+void Image_PixMap::setFormat (Image_PixMap::ImgFormat thePixelFormat)
 {
-#ifdef HAVE_FREEIMAGE
-  *myImage = FreeImage_ConvertFromRawBits (theDataPtr,
-                                           theWidth, theHeight,
-                                           thePitch, theBitsPerPixel,
-                                           0, 0, 0,
-                                           theIsTopDown);
-  if (theBitsPerPixel != 24)
-  {
-    myImage->convertTo24Bits();
-  }
-#else
-  myImage = new fipImage (theWidth, theHeight, thePitch, theBitsPerPixel / 8);
-  Standard_Integer aRowStart = !theIsTopDown ? 0 : (theHeight - 1);
-  Standard_Integer aRowDelta = !theIsTopDown ? 1 : -1;
-  for (Standard_Integer aRowFrom (aRowStart), aRowTo (0);
-       aRowFrom >= 0 && aRowFrom < theHeight;
-       aRowFrom += aRowDelta, ++aRowTo)
-  {
-    memcpy (myImage->getScanLine (aRowTo),
-            &theDataPtr[aRowFrom * thePitch],
-            myImage->getBytesPerLine());
-  }
-#endif
+  myImgFormat      = thePixelFormat;
+  myData.mySizeBPP = SizePixelBytes (myImgFormat);
 }
 
-//=======================================================================
-//function : Destroy
-//purpose  :
-//=======================================================================
-void Image_PixMap::Destroy()
+// =======================================================================
+// function : setTopDown
+// purpose  :
+// =======================================================================
+void Image_PixMap::setTopDown()
 {
-  myImage = Image_HPrivateImage();
+  myData.myTopRowPtr = ((myData.myTopToDown == 1 || myData.myDataPtr == NULL)
+                     ? myData.myDataPtr : (myData.myDataPtr + myData.mySizeRowBytes * (myData.mySizeY - 1)));
 }
 
-//=======================================================================
-//function : Dump
-//purpose  :
-//=======================================================================
-Standard_Boolean Image_PixMap::Dump (const Standard_CString theFilename,
-                                     const Standard_Real theGammaCorr) const
+// =======================================================================
+// function : InitWrapper
+// purpose  :
+// =======================================================================
+bool Image_PixMap::InitWrapper (Image_PixMap::ImgFormat thePixelFormat,
+                                Standard_Byte*          theDataPtr,
+                                const Standard_Size     theSizeX,
+                                const Standard_Size     theSizeY,
+                                const Standard_Size     theSizeRowBytes)
 {
-#ifdef HAVE_FREEIMAGE
-  FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theFilename);
-  if (anImageFormat == FIF_UNKNOWN)
+  Clear (thePixelFormat);
+  if ((theSizeX == 0) || (theSizeY == 0) || (theDataPtr == NULL))
   {
-    std::cerr << "Image_PixMap, image format doesn't supported!\n";
-    return Standard_False;
+    return false;
   }
+  myData.mySizeX        = theSizeX;
+  myData.mySizeY        = theSizeY;
+  myData.mySizeRowBytes = (theSizeRowBytes != 0) ? theSizeRowBytes : (theSizeX * myData.mySizeBPP);
+  myData.myDataPtr      = theDataPtr;
+  myIsOwnPointer = false;
+  setTopDown();
+  return true;
+}
 
-  Standard_Boolean isCopied = Standard_False;
-  Image_HPrivateImage anImageToDump = myImage;
-  if (Abs (theGammaCorr - 1.0) > gp::Resolution())
+// =======================================================================
+// function : InitTrash
+// purpose  :
+// =======================================================================
+bool Image_PixMap::InitTrash (Image_PixMap::ImgFormat thePixelFormat,
+                              const Standard_Size     theSizeX,
+                              const Standard_Size     theSizeY,
+                              const Standard_Size     theSizeRowBytes)
+{
+  Clear (thePixelFormat);
+  if ((theSizeX == 0) || (theSizeY == 0))
   {
-    if (!isCopied)
-    {
-      isCopied = Standard_True;
-      anImageToDump = new fipImage (*myImage);
-    }
-    anImageToDump->adjustGamma (theGammaCorr);
+    return false;
   }
-
-  switch (anImageFormat)
+  myData.mySizeX        = theSizeX;
+  myData.mySizeY        = theSizeY;
+  myData.mySizeRowBytes = myData.mySizeX * myData.mySizeBPP;
+  if (theSizeRowBytes > myData.mySizeRowBytes)
   {
-    case FIF_GIF:
-      if (!isCopied)
-      {
-        isCopied = Standard_True;
-        anImageToDump = new fipImage (*myImage);
-      }
-      // need convertion to image with pallete
-      anImageToDump->colorQuantize (FIQ_NNQUANT);
-      break;
-    case FIF_EXR:
-      if (myImage->getImageType() == FIT_BITMAP)
-      {
-        if (!isCopied)
-        {
-          isCopied = Standard_True;
-          anImageToDump = new fipImage (*myImage);
-        }
-        anImageToDump->convertToType (FIT_RGBF);
-      }
-      break;
-    default:
-      if (myImage->getImageType() != FIT_BITMAP)
-      {
-        if (!isCopied)
-        {
-          isCopied = Standard_True;
-          anImageToDump = new fipImage (*myImage);
-        }
-        anImageToDump->convertToType (FIT_BITMAP);
-      }
-      break;
+    // use argument only if it greater
+    myData.mySizeRowBytes = theSizeRowBytes;
   }
-  return anImageToDump->save (theFilename);
-#else
-  return myImage->savePPM (theFilename);
-#endif
+  myData.myDataPtr = MemAllocAligned<Standard_Byte*> (SizeBytes());
+  myIsOwnPointer   = true;
+  setTopDown();
+  return myData.myDataPtr != NULL;
 }
 
-Aspect_Handle Image_PixMap::PixmapID() const
+// =======================================================================
+// function : InitZero
+// purpose  :
+// =======================================================================
+bool Image_PixMap::InitZero (Image_PixMap::ImgFormat thePixelFormat,
+                             const Standard_Size     theSizeX,
+                             const Standard_Size     theSizeY,
+                             const Standard_Size     theSizeRowBytes,
+                             const Standard_Byte     theValue)
 {
-  return Aspect_Handle();
+  if (!InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes))
+  {
+    return false;
+  }
+  memset (myData.myDataPtr, (int )theValue, SizeBytes());
+  return true;
 }
 
-void Image_PixMap::AccessBuffer (Image_CRawBufferData& theBuffer) const
+// =======================================================================
+// function : InitCopy
+// purpose  :
+// =======================================================================
+bool Image_PixMap::InitCopy (const Image_PixMap& theCopy)
 {
-  theBuffer.widthPx  = myImage->getWidth();
-  theBuffer.heightPx = myImage->getHeight();
-#ifdef HAVE_FREEIMAGE
-  theBuffer.rowAligmentBytes = 4; // 32 bits according to FreeImage documentation
-  switch (myImage->getImageType())
+  if (&theCopy == this)
   {
-    case FIT_FLOAT:
-      theBuffer.format = TDepthComponent;
-      theBuffer.type = TFloat;
-      break;
-    case FIT_RGBF:
-      theBuffer.format = TRGB;
-      theBuffer.type = TFloat;
-      break;
-    case FIT_RGBAF:
-      theBuffer.format = TRGBA;
-      theBuffer.type = TFloat;
-      break;
-    case FIT_BITMAP:
-    default:
-    #if defined(FREEIMAGE_BIGENDIAN)
-      theBuffer.format = (myImage->getColorType() == FIC_RGBALPHA) ? TRGBA : TRGB;
-    #else
-      theBuffer.format = (myImage->getColorType() == FIC_RGBALPHA) ? TBGRA : TBGR;
-    #endif
-      theBuffer.type = TUByte;
-      break;
+    // self-copying disallowed
+    return false;
   }
-  theBuffer.dataPtr = myImage->accessPixels();
-#else
-  theBuffer.rowAligmentBytes = myImage->getMaxRowAligmentBytes();
-  theBuffer.format = (myImage->getBytesPerPixel() == 4) ? TBGRA : TBGR;
-  theBuffer.type = TUByte;
-  theBuffer.dataPtr = myImage->getData();
-#endif
+  if (InitTrash (theCopy.myImgFormat, theCopy.myData.mySizeX, theCopy.myData.mySizeY, theCopy.myData.mySizeRowBytes))
+  {
+    memcpy (myData.myDataPtr, theCopy.myData.myDataPtr, theCopy.SizeBytes());
+    return true;
+  }
+  return false;
 }
 
 // =======================================================================
-// function : PixelColor
+// function : Clear
 // purpose  :
 // =======================================================================
-Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
-                                         const Standard_Integer theY) const
+void Image_PixMap::Clear (Image_PixMap::ImgFormat thePixelFormat)
 {
-  Quantity_Parameter aDummy;
-  return PixelColor (theX, theY, aDummy);
+  if (myIsOwnPointer && (myData.myDataPtr != NULL))
+  {
+    MemFreeAligned (myData.myDataPtr);
+  }
+  myData.myDataPtr = myData.myTopRowPtr = NULL;
+  myIsOwnPointer = true;
+  myData.mySizeX = myData.mySizeY = myData.mySizeRowBytes = 0;
+  setFormat (thePixelFormat);
+  myData.myTopToDown = 1;
 }
 
 // =======================================================================
@@ -435,64 +230,130 @@ Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
                                          const Standard_Integer theY,
                                          Quantity_Parameter&    theAlpha) const
 {
-  Standard_Integer aScanlineId = myImage->getHeight() - theY - 1;
-  if (theX < 0 || (unsigned int )theX >= (unsigned int )myImage->getWidth() ||
-      theY < 0 || (unsigned int )theY >= (unsigned int )myImage->getHeight())
+  if (IsEmpty() ||
+      theX < 0 || (Standard_Size )theX >= myData.mySizeX ||
+      theY < 0 || (Standard_Size )theY >= myData.mySizeY)
   {
     theAlpha = 0.0; // transparent
     return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
   }
-#ifdef HAVE_FREEIMAGE
-  else if (myImage->getImageType() == FIT_BITMAP)
-  {
-    RGBQUAD aValue; memset (&aValue, 0, sizeof(aValue));
-    myImage->getPixelColor (theX, aScanlineId, &aValue);
-    theAlpha = (myImage->getColorType() == FIC_RGBALPHA) ? (Standard_Real (aValue.rgbReserved) / 255.0) : 1.0;
-    return Quantity_Color (Standard_Real (aValue.rgbRed)   / 255.0,
-                           Standard_Real (aValue.rgbGreen) / 255.0,
-                           Standard_Real (aValue.rgbBlue)  / 255.0,
-                           Quantity_TOC_RGB);
-  }
-  else
+
+  switch (myImgFormat)
   {
-    switch (myImage->getImageType())
+    case ImgGrayF:
+    {
+      const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
+      theAlpha = 1.0; // opaque
+      return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel)),
+                             Quantity_Parameter (Standard_Real (aPixel)),
+                             Quantity_Parameter (Standard_Real (aPixel)),
+                             Quantity_TOC_RGB);
+      break;
+    }
+    case ImgRGBAF:
+    {
+      const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX);
+      theAlpha = aPixel.a();
+      return Quantity_Color (Quantity_Parameter (aPixel.r()),
+                             Quantity_Parameter (aPixel.g()),
+                             Quantity_Parameter (aPixel.b()),
+                             Quantity_TOC_RGB);
+    }
+    case ImgBGRAF:
+    {    
+      const Image_ColorBGRAF& aPixel = Value<Image_ColorBGRAF> (theY, theX);
+      theAlpha = aPixel.a();
+      return Quantity_Color (Quantity_Parameter (aPixel.r()),
+                             Quantity_Parameter (aPixel.g()),
+                             Quantity_Parameter (aPixel.b()),
+                             Quantity_TOC_RGB);
+    }
+    case ImgRGBF:
+    {
+      const Image_ColorRGBF& aPixel = Value<Image_ColorRGBF> (theY, theX);
+      theAlpha =  1.0; // opaque
+      return Quantity_Color (Quantity_Parameter (aPixel.r()),
+                             Quantity_Parameter (aPixel.g()),
+                             Quantity_Parameter (aPixel.b()),
+                             Quantity_TOC_RGB);
+    }
+    case ImgBGRF:
     {
-      case FIT_FLOAT:
-      {
-        float* aScanLine = (float* )myImage->getScanLine (aScanlineId);
-        Quantity_Parameter aValue = Quantity_Parameter (aScanLine[theX]);
-        theAlpha = 1.0; // opaque
-        return Quantity_Color (aValue, aValue, aValue, Quantity_TOC_RGB);
-      }
-      case FIT_RGBF:
-      {
-        FIRGBF* aScanLine = (FIRGBF* )myImage->getScanLine (aScanlineId);
-        FIRGBF* aPixel = &aScanLine[theX];
-        theAlpha = 1.0; // opaque
-        return Quantity_Color (Quantity_Parameter (aPixel->red),
-                               Quantity_Parameter (aPixel->green),
-                               Quantity_Parameter (aPixel->blue),
-                               Quantity_TOC_RGB);
-      }
-      case FIT_RGBAF:
-      {
-        FIRGBAF* aScanLine = (FIRGBAF* )myImage->getScanLine (aScanlineId);
-        FIRGBAF* aPixel = &aScanLine[theX];
-        theAlpha = aPixel->alpha;
-        return Quantity_Color (Quantity_Parameter (aPixel->red),
-                               Quantity_Parameter (aPixel->green),
-                               Quantity_Parameter (aPixel->blue),
-                               Quantity_TOC_RGB);
-      }
-      default:
-      {
-        // not supported image type
-        theAlpha = 0.0; // transparent
-        return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
-      }
+      const Image_ColorBGRF& aPixel = Value<Image_ColorBGRF> (theY, theX);
+      theAlpha =  1.0; // opaque
+      return Quantity_Color (Quantity_Parameter (aPixel.r()),
+                             Quantity_Parameter (aPixel.g()),
+                             Quantity_Parameter (aPixel.b()),
+                             Quantity_TOC_RGB);
+    }
+    case ImgRGBA:
+    {
+      const Image_ColorRGBA& aPixel = Value<Image_ColorRGBA> (theY, theX);
+      theAlpha = Standard_Real (aPixel.a()) / 255.0;
+      return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
+                             Quantity_TOC_RGB);
+    }
+    case ImgBGRA:
+    {
+      const Image_ColorBGRA& aPixel = Value<Image_ColorBGRA> (theY, theX);
+      theAlpha = Standard_Real (aPixel.a()) / 255.0;
+      return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
+                             Quantity_TOC_RGB);
+    }
+    case ImgRGB32:
+    {
+      const Image_ColorRGB32& aPixel = Value<Image_ColorRGB32> (theY, theX);
+      theAlpha = 1.0; // opaque
+      return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
+                             Quantity_TOC_RGB);
+    }
+    case ImgBGR32:
+    {
+      const Image_ColorBGR32& aPixel = Value<Image_ColorBGR32> (theY, theX);
+      theAlpha = 1.0; // opaque
+      return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
+                             Quantity_TOC_RGB);
+    }
+    case ImgRGB:
+    {
+      const Image_ColorRGB& aPixel = Value<Image_ColorRGB> (theY, theX);
+      theAlpha = 1.0; // opaque
+      return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
+                             Quantity_TOC_RGB);
+    }
+    case ImgBGR:
+    {
+      const Image_ColorBGR& aPixel = Value<Image_ColorBGR> (theY, theX);
+      theAlpha = 1.0; // opaque
+      return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
+                             Quantity_TOC_RGB);
+    }
+    case ImgGray:
+    {
+      const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
+      theAlpha = 1.0; // opaque
+      return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel) / 255.0),
+                             Quantity_Parameter (Standard_Real (aPixel) / 255.0),
+                             Quantity_TOC_RGB);
+    }
+    default:
+    {
+      // not supported image type
+      theAlpha = 0.0; // transparent
+      return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
     }
   }
-#else
-  return myImage->getPixelColor (theX, aScanlineId, theAlpha);
-#endif
 }