0032862: Visualization, Graphic3d_TextureMap - add 3D texture definition
[occt.git] / src / Image / Image_PixMap.cxx
index d1ddea2..c99971a 100644 (file)
@@ -73,7 +73,8 @@ namespace
   };
 }
 
-IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap,Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(Image_PixMapData, NCollection_Buffer)
+IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap,     Standard_Transient)
 
 // =======================================================================
 // function : DefaultAllocator
@@ -153,64 +154,101 @@ void Image_PixMap::SetFormat (Image_Format thePixelFormat)
 }
 
 // =======================================================================
-// function : InitWrapper
+// function : InitWrapper3D
 // purpose  :
 // =======================================================================
-bool Image_PixMap::InitWrapper (Image_Format        thePixelFormat,
-                                Standard_Byte*      theDataPtr,
-                                const Standard_Size theSizeX,
-                                const Standard_Size theSizeY,
-                                const Standard_Size theSizeRowBytes)
+bool Image_PixMap::InitWrapper3D (Image_Format thePixelFormat,
+                                  Standard_Byte* theDataPtr,
+                                  const NCollection_Vec3<Standard_Size>& theSizeXYZ,
+                                  const Standard_Size theSizeRowBytes)
 {
   Clear();
   myImgFormat = thePixelFormat;
-  if ((theSizeX == 0) || (theSizeY == 0) || (theDataPtr == NULL))
+  if (theSizeXYZ.x() == 0
+   || theSizeXYZ.y() == 0
+   || theSizeXYZ.z() == 0
+   || theDataPtr == nullptr)
   {
     return false;
   }
 
   Handle(NCollection_BaseAllocator) anEmptyAlloc;
   myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (thePixelFormat),
-               theSizeX, theSizeY, theSizeRowBytes, theDataPtr);
+               theSizeXYZ, theSizeRowBytes, theDataPtr);
   return true;
 }
 
 // =======================================================================
-// function : InitTrash
+// function : InitWrapper
 // purpose  :
 // =======================================================================
-bool Image_PixMap::InitTrash (Image_Format        thePixelFormat,
-                              const Standard_Size theSizeX,
-                              const Standard_Size theSizeY,
-                              const Standard_Size theSizeRowBytes)
+bool Image_PixMap::InitWrapper (Image_Format        thePixelFormat,
+                                Standard_Byte*      theDataPtr,
+                                const Standard_Size theSizeX,
+                                const Standard_Size theSizeY,
+                                const Standard_Size theSizeRowBytes)
+{
+  return InitWrapper3D (thePixelFormat, theDataPtr, NCollection_Vec3<Standard_Size> (theSizeX, theSizeY, 1), theSizeRowBytes);
+}
+
+// =======================================================================
+// function : InitTrash3D
+// purpose  :
+// =======================================================================
+bool Image_PixMap::InitTrash3D (Image_Format thePixelFormat,
+                                const NCollection_Vec3<Standard_Size>& theSizeXYZ,
+                                const Standard_Size theSizeRowBytes)
 {
   Clear();
   myImgFormat = thePixelFormat;
-  if ((theSizeX == 0) || (theSizeY == 0))
+  if (theSizeXYZ.x() == 0
+   || theSizeXYZ.y() == 0
+   || theSizeXYZ.z() == 0)
   {
     return false;
   }
 
   // use argument only if it greater
-  const Standard_Size aSizeRowBytes = std::max (theSizeRowBytes, theSizeX * SizePixelBytes (thePixelFormat));
+  const Standard_Size aSizeRowBytes = std::max (theSizeRowBytes, theSizeXYZ.x() * SizePixelBytes (thePixelFormat));
   myData.Init (DefaultAllocator(), Image_PixMap::SizePixelBytes (thePixelFormat),
-               theSizeX, theSizeY, aSizeRowBytes, NULL);
+               theSizeXYZ, aSizeRowBytes, NULL);
   return !myData.IsEmpty();
 }
 
 // =======================================================================
-// function : InitZero
+// function : InitTrash
 // purpose  :
 // =======================================================================
-bool Image_PixMap::InitZero (Image_Format        thePixelFormat,
-                             const Standard_Size theSizeX,
-                             const Standard_Size theSizeY,
-                             const Standard_Size theSizeRowBytes,
-                             const Standard_Byte theValue)
+bool Image_PixMap::InitTrash (Image_Format        thePixelFormat,
+                              const Standard_Size theSizeX,
+                              const Standard_Size theSizeY,
+                              const Standard_Size theSizeRowBytes)
 {
-  if (!InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes))
+  return InitTrash3D (thePixelFormat, NCollection_Vec3<Standard_Size> (theSizeX, theSizeY, 1), theSizeRowBytes);
+}
+
+// =======================================================================
+// function : InitZero3D
+// purpose  :
+// =======================================================================
+bool Image_PixMap::InitZero3D (Image_Format thePixelFormat,
+                               const NCollection_Vec3<Standard_Size>& theSizeXYZ,
+                               const Standard_Size theSizeRowBytes,
+                               const Standard_Byte theValue)
+{
+  if (theSizeXYZ.z() > 1)
   {
-    return false;
+    if (!InitTrash3D (thePixelFormat, theSizeXYZ, theSizeRowBytes))
+    {
+      return false;
+    }
+  }
+  else
+  {
+    if (!InitTrash (thePixelFormat, theSizeXYZ.x(), theSizeXYZ.y(), theSizeRowBytes))
+    {
+      return false;
+    }
   }
   memset (myData.ChangeData(), (int )theValue, SizeBytes());
   return true;
@@ -227,12 +265,24 @@ bool Image_PixMap::InitCopy (const Image_PixMap& theCopy)
     // self-copying disallowed
     return false;
   }
-  if (InitTrash (theCopy.myImgFormat, theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
+
+  if (theCopy.SizeZ() > 1)
+  {
+    if (!InitTrash3D (theCopy.myImgFormat, theCopy.SizeXYZ(), theCopy.SizeRowBytes()))
+    {
+      return false;
+    }
+  }
+  else
   {
-    memcpy (myData.ChangeData(), theCopy.myData.Data(), theCopy.SizeBytes());
-    return true;
+    if (!InitTrash (theCopy.myImgFormat, theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
+    {
+      return false;
+    }
   }
-  return false;
+
+  memcpy (myData.ChangeData(), theCopy.myData.Data(), theCopy.SizeBytes());
+  return true;
 }
 
 // =======================================================================
@@ -243,80 +293,73 @@ void Image_PixMap::Clear()
 {
   Handle(NCollection_BaseAllocator) anEmptyAlloc;
   myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (myImgFormat),
-               0, 0, 0, NULL);
+               NCollection_Vec3<Standard_Size> (0), 0, nullptr);
 }
 
 // =======================================================================
-// function : PixelColor
+// function : ColorFromRawPixel
 // purpose  :
 // =======================================================================
-Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
-                                             const Standard_Integer theY,
-                                             const Standard_Boolean theToLinearize) const
+Quantity_ColorRGBA Image_PixMap::ColorFromRawPixel (const Standard_Byte* theRawValue,
+                                                    const Image_Format theFormat,
+                                                    const Standard_Boolean theToLinearize)
 {
-  if (IsEmpty()
-   || theX < 0 || (Standard_Size )theX >= SizeX()
-   || theY < 0 || (Standard_Size )theY >= SizeY())
-  {
-    return Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 0.0f); // transparent
-  }
-
-  switch (myImgFormat)
+  switch (theFormat)
   {
     case Image_Format_GrayF:
     {
-      const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
+      const Standard_ShortReal& aPixel = *reinterpret_cast<const Standard_ShortReal*> (theRawValue);
       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel, aPixel, aPixel, 1.0f)); // opaque
     }
     case Image_Format_AlphaF:
     {
-      const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
+      const Standard_ShortReal& aPixel = *reinterpret_cast<const Standard_ShortReal*> (theRawValue);
       return Quantity_ColorRGBA (NCollection_Vec4<float> (1.0f, 1.0f, 1.0f, aPixel));
     }
     case Image_Format_RGF:
     {
-      const Image_ColorRGF& aPixel = Value<Image_ColorRGF> (theY, theX);
+      const Image_ColorRGF& aPixel = *reinterpret_cast<const Image_ColorRGF*> (theRawValue);
       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), 0.0f, 1.0f));
     }
     case Image_Format_RGBAF:
     {
-      const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX);
+      const Image_ColorRGBAF& aPixel = *reinterpret_cast<const Image_ColorRGBAF*> (theRawValue);
       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), aPixel.a()));
     }
     case Image_Format_BGRAF:
     {    
-      const Image_ColorBGRAF& aPixel = Value<Image_ColorBGRAF> (theY, theX);
+      const Image_ColorBGRAF& aPixel = *reinterpret_cast<const Image_ColorBGRAF*> (theRawValue);
       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), aPixel.a()));
     }
     case Image_Format_RGBF:
     {
-      const Image_ColorRGBF& aPixel = Value<Image_ColorRGBF> (theY, theX);
+      const Image_ColorRGBF& aPixel = *reinterpret_cast<const Image_ColorRGBF*> (theRawValue);
       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), 1.0f)); // opaque
     }
     case Image_Format_BGRF:
     {
-      const Image_ColorBGRF& aPixel = Value<Image_ColorBGRF> (theY, theX);
+      const Image_ColorBGRF& aPixel = *reinterpret_cast<const Image_ColorBGRF*> (theRawValue);
       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);
+      const uint16_t& aPixel = *reinterpret_cast<const uint16_t*> (theRawValue);
       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);
+      const NCollection_Vec2<uint16_t>& aPixel = *reinterpret_cast<const NCollection_Vec2<uint16_t>*> (theRawValue);
       return Quantity_ColorRGBA (NCollection_Vec4<float> (ConvertFromHalfFloat (aPixel.x()), ConvertFromHalfFloat (aPixel.y()), 0.0f, 1.0f));
     }
     case Image_Format_RGBAF_half:
     {
-      const NCollection_Vec4<uint16_t>& aPixel = Value<NCollection_Vec4<uint16_t>> (theY, theX);
+      const NCollection_Vec4<uint16_t>& aPixel = *reinterpret_cast<const NCollection_Vec4<uint16_t>*> (theRawValue);
       return Quantity_ColorRGBA (NCollection_Vec4<float> (ConvertFromHalfFloat (aPixel.r()), ConvertFromHalfFloat (aPixel.g()),
                                                           ConvertFromHalfFloat (aPixel.b()), ConvertFromHalfFloat (aPixel.a())));
     }
     case Image_Format_RGBA:
     {
-      const Image_ColorRGBA& aPixel = Value<Image_ColorRGBA> (theY, theX);
+      const Image_ColorRGBA& aPixel = *reinterpret_cast<const Image_ColorRGBA*> (theRawValue);
       return theToLinearize
            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
@@ -326,7 +369,7 @@ Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
     }
     case Image_Format_BGRA:
     {
-      const Image_ColorBGRA& aPixel = Value<Image_ColorBGRA> (theY, theX);
+      const Image_ColorBGRA& aPixel = *reinterpret_cast<const Image_ColorBGRA*> (theRawValue);
       return theToLinearize
            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
@@ -336,7 +379,7 @@ Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
     }
     case Image_Format_RGB32:
     {
-      const Image_ColorRGB32& aPixel = Value<Image_ColorRGB32> (theY, theX);
+      const Image_ColorRGB32& aPixel = *reinterpret_cast<const Image_ColorRGB32*> (theRawValue);
       return theToLinearize
            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
@@ -345,7 +388,7 @@ Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
     }
     case Image_Format_BGR32:
     {
-      const Image_ColorBGR32& aPixel = Value<Image_ColorBGR32> (theY, theX);
+      const Image_ColorBGR32& aPixel = *reinterpret_cast<const Image_ColorBGR32*> (theRawValue);
       return theToLinearize
            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
@@ -354,7 +397,7 @@ Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
     }
     case Image_Format_RGB:
     {
-      const Image_ColorRGB& aPixel = Value<Image_ColorRGB> (theY, theX);
+      const Image_ColorRGB& aPixel = *reinterpret_cast<const Image_ColorRGB*> (theRawValue);
       return theToLinearize
            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
@@ -363,7 +406,7 @@ Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
     }
     case Image_Format_BGR:
     {
-      const Image_ColorBGR& aPixel = Value<Image_ColorBGR> (theY, theX);
+      const Image_ColorBGR& aPixel = *reinterpret_cast<const Image_ColorBGR*> (theRawValue);
       return theToLinearize
            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
@@ -372,18 +415,18 @@ Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
     }
     case Image_Format_Gray:
     {
-      const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
+      const Standard_Byte& aPixel = *reinterpret_cast<const Standard_Byte*> (theRawValue);
       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);
+      const Standard_Byte& aPixel = *reinterpret_cast<const Standard_Byte*> (theRawValue);
       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 uint16_t& aPixel = *reinterpret_cast<const uint16_t*> (theRawValue);
       const float anIntensity = float(aPixel) / 65535.0f;
       return Quantity_ColorRGBA (anIntensity, anIntensity, anIntensity, 1.0f); // opaque
     }
@@ -398,44 +441,37 @@ Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
 }
 
 // =======================================================================
-// function : SetPixelColor
+// function : ColorToRawPixel
 // purpose  :
 // =======================================================================
-void Image_PixMap::SetPixelColor (const Standard_Integer theX,
-                                  const Standard_Integer theY,
-                                  const Quantity_ColorRGBA& theColor,
-                                  const Standard_Boolean theToDeLinearize)
+void Image_PixMap::ColorToRawPixel (Standard_Byte* theRawValue,
+                                    const Image_Format theFormat,
+                                    const Quantity_ColorRGBA& theColor,
+                                    const Standard_Boolean theToDeLinearize)
 {
-  if (IsEmpty()
-   || theX < 0 || Standard_Size(theX) >= SizeX()
-   || theY < 0 || Standard_Size(theY) >= SizeY())
-  {
-    return;
-  }
-
   const NCollection_Vec4<float>& aColor = theColor;
-  switch (myImgFormat)
+  switch (theFormat)
   {
     case Image_Format_GrayF:
     {
-      ChangeValue<Standard_ShortReal> (theY, theX) = aColor.r();
+      *reinterpret_cast<Standard_ShortReal*> (theRawValue) = aColor.r();
       return;
     }
     case Image_Format_AlphaF:
     {
-      ChangeValue<Standard_ShortReal> (theY, theX) = aColor.a();
+      *reinterpret_cast<Standard_ShortReal*> (theRawValue) = aColor.a();
       return;
     }
     case Image_Format_RGF:
     {
-      Image_ColorRGF& aPixel = ChangeValue<Image_ColorRGF> (theY, theX);
+      Image_ColorRGF& aPixel = *reinterpret_cast<Image_ColorRGF*> (theRawValue);
       aPixel.r() = aColor.r();
       aPixel.g() = aColor.g();
       return;
     }
     case Image_Format_RGBAF:
     {
-      Image_ColorRGBAF& aPixel = ChangeValue<Image_ColorRGBAF> (theY, theX);
+      Image_ColorRGBAF& aPixel = *reinterpret_cast<Image_ColorRGBAF*> (theRawValue);
       aPixel.r() = aColor.r();
       aPixel.g() = aColor.g();
       aPixel.b() = aColor.b();
@@ -444,7 +480,7 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
     }
     case Image_Format_BGRAF:
     {
-      Image_ColorBGRAF& aPixel = ChangeValue<Image_ColorBGRAF> (theY, theX);
+      Image_ColorBGRAF& aPixel = *reinterpret_cast<Image_ColorBGRAF*> (theRawValue);
       aPixel.r() = aColor.r();
       aPixel.g() = aColor.g();
       aPixel.b() = aColor.b();
@@ -453,7 +489,7 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
     }
     case Image_Format_RGBF:
     {
-      Image_ColorRGBF& aPixel = ChangeValue<Image_ColorRGBF> (theY, theX);
+      Image_ColorRGBF& aPixel = *reinterpret_cast<Image_ColorRGBF*> (theRawValue);
       aPixel.r() = aColor.r();
       aPixel.g() = aColor.g();
       aPixel.b() = aColor.b();
@@ -461,7 +497,7 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
     }
     case Image_Format_BGRF:
     {
-      Image_ColorBGRF& aPixel = ChangeValue<Image_ColorBGRF> (theY, theX);
+      Image_ColorBGRF& aPixel = *reinterpret_cast<Image_ColorBGRF*> (theRawValue);
       aPixel.r() = aColor.r();
       aPixel.g() = aColor.g();
       aPixel.b() = aColor.b();
@@ -469,20 +505,20 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
     }
     case Image_Format_GrayF_half:
     {
-      uint16_t& aPixel = ChangeValue<uint16_t> (theY, theX);
+      uint16_t& aPixel = *reinterpret_cast<uint16_t*> (theRawValue);
       aPixel = ConvertToHalfFloat (aColor.r());
       return;
     }
     case Image_Format_RGF_half:
     {
-      NCollection_Vec2<uint16_t>& aPixel = ChangeValue<NCollection_Vec2<uint16_t>> (theY, theX);
+      NCollection_Vec2<uint16_t>& aPixel = *reinterpret_cast<NCollection_Vec2<uint16_t>*> (theRawValue);
       aPixel.x() = ConvertToHalfFloat (aColor.r());
       aPixel.y() = ConvertToHalfFloat (aColor.g());
       return;
     }
     case Image_Format_RGBAF_half:
     {
-      NCollection_Vec4<uint16_t>& aPixel = ChangeValue<NCollection_Vec4<uint16_t>> (theY, theX);
+      NCollection_Vec4<uint16_t>& aPixel = *reinterpret_cast<NCollection_Vec4<uint16_t>*> (theRawValue);
       aPixel.r() = ConvertToHalfFloat (aColor.r());
       aPixel.g() = ConvertToHalfFloat (aColor.g());
       aPixel.b() = ConvertToHalfFloat (aColor.b());
@@ -491,7 +527,7 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
     }
     case Image_Format_RGBA:
     {
-      Image_ColorRGBA& aPixel = ChangeValue<Image_ColorRGBA> (theY, theX);
+      Image_ColorRGBA& aPixel = *reinterpret_cast<Image_ColorRGBA*> (theRawValue);
       if (theToDeLinearize)
       {
         aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
@@ -509,7 +545,7 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
     }
     case Image_Format_BGRA:
     {
-      Image_ColorBGRA& aPixel = ChangeValue<Image_ColorBGRA> (theY, theX);
+      Image_ColorBGRA& aPixel = *reinterpret_cast<Image_ColorBGRA*> (theRawValue);
       if (theToDeLinearize)
       {
         aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
@@ -527,7 +563,7 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
     }
     case Image_Format_RGB32:
     {
-      Image_ColorRGB32& aPixel = ChangeValue<Image_ColorRGB32> (theY, theX);
+      Image_ColorRGB32& aPixel = *reinterpret_cast<Image_ColorRGB32*> (theRawValue);
       if (theToDeLinearize)
       {
         aPixel.r()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
@@ -545,7 +581,7 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
     }
     case Image_Format_BGR32:
     {
-      Image_ColorBGR32& aPixel = ChangeValue<Image_ColorBGR32> (theY, theX);
+      Image_ColorBGR32& aPixel = *reinterpret_cast<Image_ColorBGR32*> (theRawValue);
       if (theToDeLinearize)
       {
         aPixel.r()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
@@ -563,7 +599,7 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
     }
     case Image_Format_RGB:
     {
-      Image_ColorRGB& aPixel = ChangeValue<Image_ColorRGB> (theY, theX);
+      Image_ColorRGB& aPixel = *reinterpret_cast<Image_ColorRGB*> (theRawValue);
       if (theToDeLinearize)
       {
         aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
@@ -580,7 +616,7 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
     }
     case Image_Format_BGR:
     {
-      Image_ColorBGR& aPixel = ChangeValue<Image_ColorBGR> (theY, theX);
+      Image_ColorBGR& aPixel = *reinterpret_cast<Image_ColorBGR*> (theRawValue);
       if (theToDeLinearize)
       {
         aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
@@ -597,17 +633,17 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
     }
     case Image_Format_Gray:
     {
-      ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(aColor.r() * 255.0f);
+      *reinterpret_cast<Standard_Byte*>(theRawValue) = Standard_Byte(aColor.r() * 255.0f);
       return;
     }
     case Image_Format_Alpha:
     {
-      ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(aColor.a() * 255.0f);
+      *reinterpret_cast<Standard_Byte*>(theRawValue) = Standard_Byte(aColor.a() * 255.0f);
       return;
     }
     case Image_Format_Gray16:
     {
-      ChangeValue<uint16_t> (theY, theX) = uint16_t(aColor.r() * 65535.0f);
+      *reinterpret_cast<uint16_t*>(theRawValue) = uint16_t(aColor.r() * 65535.0f);
       return;
     }
     case Image_Format_UNKNOWN:
@@ -632,18 +668,21 @@ bool Image_PixMap::SwapRgbaBgra (Image_PixMap& theImage)
     {
       const bool toResetAlpha = theImage.Format() == Image_Format_BGR32
                              || theImage.Format() == Image_Format_RGB32;
-      for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
+      for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
       {
-        for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
+        for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
         {
-          Image_ColorRGBA& aPixel     = theImage.ChangeValue<Image_ColorRGBA> (aRow, aCol);
-          Image_ColorBGRA  aPixelCopy = theImage.Value      <Image_ColorBGRA> (aRow, aCol);
-          aPixel.r() = aPixelCopy.r();
-          aPixel.g() = aPixelCopy.g();
-          aPixel.b() = aPixelCopy.b();
-          if (toResetAlpha)
+          for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
           {
-            aPixel.a() = 255;
+            Image_ColorRGBA& aPixel     = theImage.ChangeValueXYZ<Image_ColorRGBA> (aCol, aRow, aSlice);
+            Image_ColorBGRA  aPixelCopy = theImage.ValueXYZ      <Image_ColorBGRA> (aCol, aRow, aSlice);
+            aPixel.r() = aPixelCopy.r();
+            aPixel.g() = aPixelCopy.g();
+            aPixel.b() = aPixelCopy.b();
+            if (toResetAlpha)
+            {
+              aPixel.a() = 255;
+            }
           }
         }
       }
@@ -652,15 +691,18 @@ bool Image_PixMap::SwapRgbaBgra (Image_PixMap& theImage)
     case Image_Format_BGR:
     case Image_Format_RGB:
     {
-      for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
+      for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
       {
-        for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
+        for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
         {
-          Image_ColorRGB& aPixel     = theImage.ChangeValue<Image_ColorRGB> (aRow, aCol);
-          Image_ColorBGR  aPixelCopy = theImage.Value      <Image_ColorBGR> (aRow, aCol);
-          aPixel.r() = aPixelCopy.r();
-          aPixel.g() = aPixelCopy.g();
-          aPixel.b() = aPixelCopy.b();
+          for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
+          {
+            Image_ColorRGB& aPixel     = theImage.ChangeValueXYZ<Image_ColorRGB> (aCol, aRow, aSlice);
+            Image_ColorBGR  aPixelCopy = theImage.ValueXYZ      <Image_ColorBGR> (aCol, aRow, aSlice);
+            aPixel.r() = aPixelCopy.r();
+            aPixel.g() = aPixelCopy.g();
+            aPixel.b() = aPixelCopy.b();
+          }
         }
       }
       return true;
@@ -670,15 +712,18 @@ bool Image_PixMap::SwapRgbaBgra (Image_PixMap& theImage)
     case Image_Format_BGRAF:
     case Image_Format_RGBAF:
     {
-      for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
+      for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
       {
-        for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
+        for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
         {
-          Image_ColorRGBF& aPixel     = theImage.ChangeValue<Image_ColorRGBF> (aRow, aCol);
-          Image_ColorBGRF  aPixelCopy = theImage.Value      <Image_ColorBGRF> (aRow, aCol);
-          aPixel.r() = aPixelCopy.r();
-          aPixel.g() = aPixelCopy.g();
-          aPixel.b() = aPixelCopy.b();
+          for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
+          {
+            Image_ColorRGBF& aPixel     = theImage.ChangeValueXYZ<Image_ColorRGBF> (aCol, aRow, aSlice);
+            Image_ColorBGRF  aPixelCopy = theImage.ValueXYZ      <Image_ColorBGRF> (aCol, aRow, aSlice);
+            aPixel.r() = aPixelCopy.r();
+            aPixel.g() = aPixelCopy.g();
+            aPixel.b() = aPixelCopy.b();
+          }
         }
       }
       return true;
@@ -698,14 +743,17 @@ void Image_PixMap::ToBlackWhite (Image_PixMap& theImage)
     case Image_Format_Gray:
     case Image_Format_Alpha:
     {
-      for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
+      for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
       {
-        for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
+        for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
         {
-          unsigned char& aPixel = theImage.ChangeValue<unsigned char> (aRow, aCol);
-          if (aPixel != 0)
+          for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
           {
-            aPixel = 255;
+            uint8_t& aPixel = theImage.ChangeValueXYZ<uint8_t> (aCol, aRow, aSlice);
+            if (aPixel != 0)
+            {
+              aPixel = 255;
+            }
           }
         }
       }
@@ -713,14 +761,17 @@ void Image_PixMap::ToBlackWhite (Image_PixMap& theImage)
     }
     case Image_Format_Gray16:
     {
-      for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
+      for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
       {
-        for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
+        for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
         {
-          uint16_t& aPixel = theImage.ChangeValue<uint16_t> (aRow, aCol);
-          if (aPixel != 0)
+          for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
           {
-            aPixel = 65535;
+            uint16_t& aPixel = theImage.ChangeValueXYZ<uint16_t> (aCol, aRow, aSlice);
+            if (aPixel != 0)
+            {
+              aPixel = 65535;
+            }
           }
         }
       }
@@ -733,17 +784,20 @@ void Image_PixMap::ToBlackWhite (Image_PixMap& theImage)
     case Image_Format_RGBA:
     case Image_Format_BGRA:
     {
-      const NCollection_Vec3<unsigned char> aWhite24 (255, 255, 255);
-      for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
+      const NCollection_Vec3<uint8_t> aWhite24 (255, 255, 255);
+      for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
       {
-        for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
+        for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
         {
-          NCollection_Vec3<unsigned char>& aPixel = theImage.ChangeValue< NCollection_Vec3<unsigned char> > (aRow, aCol);
-          if (aPixel[0] != 0
-           || aPixel[1] != 0
-           || aPixel[2] != 0)
+          for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
           {
-            aPixel = aWhite24;
+            NCollection_Vec3<uint8_t>& aPixel = theImage.ChangeValueXYZ< NCollection_Vec3<uint8_t> > (aCol, aRow, aSlice);
+            if (aPixel[0] != 0
+             || aPixel[1] != 0
+             || aPixel[2] != 0)
+            {
+              aPixel = aWhite24;
+            }
           }
         }
       }
@@ -752,17 +806,21 @@ void Image_PixMap::ToBlackWhite (Image_PixMap& theImage)
     default:
     {
       const Quantity_ColorRGBA aWhiteRgba (1.0f, 1.0f, 1.0f, 1.0f);
-      for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
+      for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
       {
-        for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
+        for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
         {
-          const Quantity_ColorRGBA       aPixelRgba = theImage.PixelColor (Standard_Integer(aCol), Standard_Integer(aRow));
-          const NCollection_Vec4<float>& aPixel     = aPixelRgba;
-          if (aPixel[0] != 0.0f
-           || aPixel[1] != 0.0f
-           || aPixel[2] != 0.0f)
+          for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
           {
-            theImage.SetPixelColor (int(aCol), int(aRow), aWhiteRgba);
+            Standard_Byte* aRawPixel = theImage.ChangeRawValueXYZ (aCol, aRow, aSlice);
+            const Quantity_ColorRGBA       aPixelRgba = ColorFromRawPixel (aRawPixel, theImage.Format());
+            const NCollection_Vec4<float>& aPixel     = aPixelRgba;
+            if (aPixel[0] != 0.0f
+             || aPixel[1] != 0.0f
+             || aPixel[2] != 0.0f)
+            {
+              ColorToRawPixel (aRawPixel, theImage.Format(), aWhiteRgba);
+            }
           }
         }
       }
@@ -772,7 +830,7 @@ void Image_PixMap::ToBlackWhite (Image_PixMap& theImage)
 }
 
 // =======================================================================
-// function : InitCopy
+// function : FlipY
 // purpose  :
 // =======================================================================
 bool Image_PixMap::FlipY (Image_PixMap& theImage)
@@ -793,13 +851,16 @@ bool Image_PixMap::FlipY (Image_PixMap& theImage)
 
   // for odd height middle row should be left as is
   Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
-  for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
+  for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
   {
-    Standard_Byte* aTop = theImage.ChangeRow (aRowT);
-    Standard_Byte* aBot = theImage.ChangeRow (aRowB);
-    memcpy (aTmp.ChangeData(), aTop, aRowSize);
-    memcpy (aTop, aBot, aRowSize);
-    memcpy (aBot, aTmp.Data(), aRowSize);
+    for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
+    {
+      Standard_Byte* aTop = theImage.ChangeSliceRow (aSlice, aRowT);
+      Standard_Byte* aBot = theImage.ChangeSliceRow (aSlice, aRowB);
+      memcpy (aTmp.ChangeData(), aTop, aRowSize);
+      memcpy (aTop, aBot, aRowSize);
+      memcpy (aBot, aTmp.Data(), aRowSize);
+    }
   }
   return true;
 }