Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/opencascade/Image_PixMap.hxx was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Created on: 2012-07-18
0002 // Created by: Kirill GAVRILOV
0003 // Copyright (c) 2012-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef Image_PixMap_HeaderFile
0017 #define Image_PixMap_HeaderFile
0018 
0019 #include <Image_CompressedFormat.hxx>
0020 #include <Image_PixMapData.hxx>
0021 #include <Standard_Transient.hxx>
0022 #include <Quantity_ColorRGBA.hxx>
0023 
0024 //! Class represents packed image plane.
0025 class Image_PixMap : public Standard_Transient
0026 {
0027   DEFINE_STANDARD_RTTIEXT(Image_PixMap, Standard_Transient)
0028 public:
0029   //! Determine Big-Endian at runtime
0030   static inline bool IsBigEndianHost()
0031   {
0032     union {
0033       int  myInt;
0034       char myChar[sizeof(int)];
0035     } aUnion;
0036 
0037     aUnion.myInt = 1;
0038     return !aUnion.myChar[0];
0039   }
0040 
0041   //! Return bytes reserved for one pixel (may include extra bytes for alignment).
0042   Standard_EXPORT static size_t SizePixelBytes(const Image_Format thePixelFormat);
0043 
0044   //! Auxiliary method for swapping bytes between RGB and BGR formats.
0045   //! This method modifies the image data but does not change pixel format!
0046   //! Method will fail if pixel format is not one of the following:
0047   //!  - Image_Format_RGB32 / Image_Format_BGR32
0048   //!  - Image_Format_RGBA  / Image_Format_BGRA
0049   //!  - Image_Format_RGB   / Image_Format_BGR
0050   //!  - Image_Format_RGBF  / Image_Format_BGRF
0051   //!  - Image_Format_RGBAF / Image_Format_BGRAF
0052   Standard_EXPORT static bool SwapRgbaBgra(Image_PixMap& theImage);
0053 
0054   //! Convert image to Black/White.
0055   Standard_EXPORT static void ToBlackWhite(Image_PixMap& theImage);
0056 
0057   //! Reverse line order as it draws it from bottom to top.
0058   Standard_EXPORT static bool FlipY(Image_PixMap& theImage);
0059 
0060   //! Return default image data allocator.
0061   Standard_EXPORT static const occ::handle<NCollection_BaseAllocator>& DefaultAllocator();
0062 
0063   //! Return string representation of pixel format.
0064   Standard_EXPORT static const char* ImageFormatToString(Image_Format theFormat);
0065 
0066   //! Return string representation of compressed pixel format.
0067   Standard_EXPORT static const char* ImageFormatToString(Image_CompressedFormat theFormat);
0068 
0069   //! Convert raw pixel value into Quantity_ColorRGBA. This function is relatively slow.
0070   //! @param[in] theRawValue pointer to pixel definition
0071   //! @param[in] theFormat pixel format
0072   //! @param[in] theToLinearize when TRUE, the color stored in non-linear color space (e.g.
0073   //! Image_Format_RGB) will be linearized
0074   //! @return the pixel color
0075   Standard_EXPORT static Quantity_ColorRGBA ColorFromRawPixel(const uint8_t*     theRawValue,
0076                                                               const Image_Format theFormat,
0077                                                               const bool theToLinearize = false);
0078 
0079   //! Set raw pixel value from Quantity_ColorRGBA. This function is relatively slow.
0080   //! @param[out] theRawValue pointer to pixel definition to modify
0081   //! @param[in]  theFormat pixel format
0082   //! @param[in]  theColor color value to convert from
0083   //! @param[in] theToDeLinearize when TRUE, the gamma correction will be applied for storing in
0084   //! non-linear color space (e.g. Image_Format_RGB)
0085   Standard_EXPORT static void ColorToRawPixel(uint8_t*                  theRawValue,
0086                                               const Image_Format        theFormat,
0087                                               const Quantity_ColorRGBA& theColor,
0088                                               const bool                theToDeLinearize = false);
0089 
0090 public: // high-level API
0091   //! Return pixel format.
0092   Image_Format Format() const { return myImgFormat; }
0093 
0094   //! Override pixel format specified by InitXXX() methods.
0095   //! Will throw exception if pixel size of new format is not equal to currently initialized format.
0096   //! Intended to switch formats indicating different interpretation of the same data
0097   //! (e.g. ImgGray and ImgAlpha).
0098   Standard_EXPORT void SetFormat(const Image_Format thePixelFormat);
0099 
0100   //! Return image width in pixels.
0101   size_t Width() const { return myData.SizeX; }
0102 
0103   //! Return image height in pixels.
0104   size_t Height() const { return myData.SizeY; }
0105 
0106   //! Return image depth in pixels.
0107   size_t Depth() const { return myData.SizeZ; }
0108 
0109   //! Return image width in pixels.
0110   size_t SizeX() const { return myData.SizeX; }
0111 
0112   //! Return image height in pixels.
0113   size_t SizeY() const { return myData.SizeY; }
0114 
0115   //! Return image depth in pixels.
0116   size_t SizeZ() const { return myData.SizeZ; }
0117 
0118   //! Return image width x height x depth in pixels.
0119   NCollection_Vec3<size_t> SizeXYZ() const
0120   {
0121     return NCollection_Vec3<size_t>(myData.SizeX, myData.SizeY, myData.SizeZ);
0122   }
0123 
0124   //! Return width / height.
0125   double Ratio() const { return (SizeY() > 0) ? (double(SizeX()) / double(SizeY())) : 1.0; }
0126 
0127   //! Return true if data is NULL.
0128   bool IsEmpty() const { return myData.IsEmpty(); }
0129 
0130   //! Empty constructor. Initialize the NULL image plane.
0131   Standard_EXPORT Image_PixMap();
0132 
0133   //! Destructor
0134   Standard_EXPORT ~Image_PixMap() override;
0135 
0136   //! Returns the pixel color. This function is relatively slow.
0137   //! Beware that this method takes coordinates in opposite order in contrast to ::Value() and
0138   //! ::ChangeValue().
0139   //! @param[in] theX column index from left, starting from 0
0140   //! @param[in] theY row    index from top,  starting from 0
0141   //! @param[in] theToLinearize when TRUE, the color stored in non-linear color space (e.g.
0142   //! Image_Format_RGB) will be linearized
0143   //! @return the pixel color
0144   Quantity_ColorRGBA PixelColor(int theX, int theY, bool theToLinearize = false) const
0145   {
0146     if (IsEmpty() || theX < 0 || (size_t)theX >= SizeX() || theY < 0 || (size_t)theY >= SizeY())
0147     {
0148       return Quantity_ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f); // transparent
0149     }
0150 
0151     const uint8_t* aRawPixel = RawValueXY(theX, theY);
0152     return ColorFromRawPixel(aRawPixel, myImgFormat, theToLinearize);
0153   }
0154 
0155   //! Sets the pixel color. This function is relatively slow.
0156   //! Beware that this method takes coordinates in opposite order in contrast to ::Value() and
0157   //! ::ChangeValue().
0158   //! @param[in] theX column index from left
0159   //! @param[in] theY row    index from top
0160   //! @param[in] theColor color to store
0161   //! @param[in] theToDeLinearize when TRUE, the gamma correction will be applied for storing in
0162   //! non-linear color space (e.g. Image_Format_RGB)
0163   void SetPixelColor(const int             theX,
0164                      const int             theY,
0165                      const Quantity_Color& theColor,
0166                      const bool            theToDeLinearize = false)
0167   {
0168     SetPixelColor(theX, theY, Quantity_ColorRGBA(theColor, 1.0f), theToDeLinearize);
0169   }
0170 
0171   //! Sets the pixel color. This function is relatively slow.
0172   //! Beware that this method takes coordinates in opposite order in contrast to ::Value() and
0173   //! ::ChangeValue().
0174   //! @param[in] theX column index from left
0175   //! @param[in] theY row    index from top
0176   //! @param[in] theColor color to store
0177   //! @param[in] theToDeLinearize when TRUE, the gamma correction will be applied for storing in
0178   //! non-linear color space (e.g. Image_Format_RGB)
0179   void SetPixelColor(const int                 theX,
0180                      const int                 theY,
0181                      const Quantity_ColorRGBA& theColor,
0182                      const bool                theToDeLinearize = false)
0183   {
0184     if (IsEmpty() || theX < 0 || size_t(theX) >= SizeX() || theY < 0 || size_t(theY) >= SizeY())
0185     {
0186       return;
0187     }
0188 
0189     uint8_t* aRawPixel = ChangeRawValueXY(theX, theY);
0190     ColorToRawPixel(aRawPixel, myImgFormat, theColor, theToDeLinearize);
0191   }
0192 
0193   //! Initialize image plane as wrapper over alien data.
0194   //! Data will not be copied! Notice that caller should ensure
0195   //! that data pointer will not be released during this wrapper lifetime.
0196   //! You may call InitCopy() to perform data copying.
0197   Standard_EXPORT virtual bool InitWrapper(Image_Format thePixelFormat,
0198                                            uint8_t*     theDataPtr,
0199                                            const size_t theSizeX,
0200                                            const size_t theSizeY,
0201                                            const size_t theSizeRowBytes = 0);
0202 
0203   //! Initialize image plane with required dimensions.
0204   //! Memory will be left uninitialized (performance trick).
0205   Standard_EXPORT virtual bool InitTrash(Image_Format thePixelFormat,
0206                                          const size_t theSizeX,
0207                                          const size_t theSizeY,
0208                                          const size_t theSizeRowBytes = 0);
0209 
0210   //! Initialize by copying data.
0211   //! If you want to copy alien data you should create wrapper using InitWrapper() before.
0212   Standard_EXPORT virtual bool InitCopy(const Image_PixMap& theCopy);
0213 
0214   //! Initialize image plane with required dimensions.
0215   //! Buffer will be zeroed (black color for most formats).
0216   bool InitZero(Image_Format  thePixelFormat,
0217                 const size_t  theSizeX,
0218                 const size_t  theSizeY,
0219                 const size_t  theSizeRowBytes = 0,
0220                 const uint8_t theValue        = 0)
0221   {
0222     return InitZero3D(thePixelFormat,
0223                       NCollection_Vec3<size_t>(theSizeX, theSizeY, 1),
0224                       theSizeRowBytes,
0225                       theValue);
0226   }
0227 
0228   //! Method correctly deallocate internal buffer.
0229   Standard_EXPORT virtual void Clear();
0230 
0231 public:
0232   //! Initialize 2D/3D image as wrapper over alien data.
0233   //! Data will not be copied! Notice that caller should ensure
0234   //! that data pointer will not be released during this wrapper lifetime.
0235   //! You may call InitCopy() to perform data copying.
0236   Standard_EXPORT virtual bool InitWrapper3D(Image_Format                    thePixelFormat,
0237                                              uint8_t*                        theDataPtr,
0238                                              const NCollection_Vec3<size_t>& theSizeXYZ,
0239                                              const size_t                    theSizeRowBytes = 0);
0240 
0241   //! Initialize 2D/3D image with required dimensions.
0242   //! Memory will be left uninitialized (performance trick).
0243   Standard_EXPORT virtual bool InitTrash3D(Image_Format                    thePixelFormat,
0244                                            const NCollection_Vec3<size_t>& theSizeXYZ,
0245                                            const size_t                    theSizeRowBytes = 0);
0246 
0247   //! Initialize 2D/3D image with required dimensions.
0248   //! Buffer will be zeroed (black color for most formats).
0249   Standard_EXPORT bool InitZero3D(Image_Format                    thePixelFormat,
0250                                   const NCollection_Vec3<size_t>& theSizeXYZ,
0251                                   const size_t                    theSizeRowBytes = 0,
0252                                   const uint8_t                   theValue        = 0);
0253 
0254 public: //! @name low-level API for batch-processing (pixels reading / comparison / modification)
0255   //! Returns TRUE if image data is stored from Top to the Down.
0256   //! By default Bottom Up order is used instead
0257   //! (topmost scanlines starts from the bottom in memory).
0258   //! which is most image frameworks naturally support.
0259   //!
0260   //! Notice that access methods within this class automatically
0261   //! convert input row-index to apply this flag!
0262   //! You should use this flag only if interconnect with alien APIs and buffers.
0263   //! @return true if image data is top-down
0264   bool IsTopDown() const { return myData.TopToDown == 1; }
0265 
0266   //! Setup scanlines order in memory - top-down or bottom-up.
0267   //! Drawers should explicitly specify this value if current state IsTopDown() was ignored!
0268   //! @param theIsTopDown top-down flag
0269   void SetTopDown(const bool theIsTopDown) { myData.SetTopDown(theIsTopDown); }
0270 
0271   //! Returns +1 if scanlines ordered in Top->Down order in memory and -1 otherwise.
0272   //! @return scanline increment for Top->Down iteration
0273   size_t TopDownInc() const { return myData.TopToDown; }
0274 
0275   //! Return data pointer for low-level operations (copying entire buffer, parsing with extra tools
0276   //! etc.).
0277   const uint8_t* Data() const { return myData.Data(); }
0278 
0279   //! Return data pointer for low-level operations (copying entire buffer, parsing with extra tools
0280   //! etc.).
0281   uint8_t* ChangeData() { return myData.ChangeData(); }
0282 
0283   //! Return data pointer to requested row (first column).
0284   //! Indexation starts from 0.
0285   const uint8_t* Row(size_t theRow) const { return myData.Row(theRow); }
0286 
0287   //! Return data pointer to requested row (first column).
0288   //! Indexation starts from 0.
0289   uint8_t* ChangeRow(size_t theRow) { return myData.ChangeRow(theRow); }
0290 
0291   //! Return data pointer to requested 2D slice.
0292   //! Indexation starts from 0.
0293   const uint8_t* Slice(size_t theSlice) const { return myData.Slice(theSlice); }
0294 
0295   //! Return data pointer to requested 2D slice.
0296   //! Indexation starts from 0.
0297   uint8_t* ChangeSlice(size_t theSlice) { return myData.ChangeSlice(theSlice); }
0298 
0299   //! Return data pointer to requested row (first column).
0300   //! Indexation starts from 0.
0301   const uint8_t* SliceRow(size_t theSlice, size_t theRow) const
0302   {
0303     return myData.SliceRow(theSlice, theRow);
0304   }
0305 
0306   //! Return data pointer to requested row (first column).
0307   //! Indexation starts from 0.
0308   uint8_t* ChangeSliceRow(size_t theSlice, size_t theRow)
0309   {
0310     return myData.ChangeSliceRow(theSlice, theRow);
0311   }
0312 
0313   //! Return bytes reserved for one pixel (may include extra bytes for alignment).
0314   size_t SizePixelBytes() const { return myData.SizeBPP; }
0315 
0316   //! Return bytes reserved per row.
0317   //! Could be larger than needed to store packed row (extra bytes for alignment etc.).
0318   size_t SizeRowBytes() const { return myData.SizeRowBytes; }
0319 
0320   //! Return the extra bytes in the row.
0321   size_t RowExtraBytes() const { return SizeRowBytes() - SizeX() * SizePixelBytes(); }
0322 
0323   //! Compute the maximal row alignment for current row size.
0324   //! @return maximal row alignment in bytes (up to 16 bytes).
0325   size_t MaxRowAligmentBytes() const { return myData.MaxRowAligmentBytes(); }
0326 
0327   //! Return number of bytes per 2D slice.
0328   size_t SizeSliceBytes() const { return myData.SizeSliceBytes; }
0329 
0330   //! Return buffer size
0331   size_t SizeBytes() const { return myData.Size(); }
0332 
0333 public:
0334   //! Access image pixel with specified color type.
0335   //! Indexation starts from 0.
0336   //! This method does not perform any type checks - use on own risk (check Format() before)!
0337   //! WARNING: Input parameters are defined in the decreasing majority following memory layout -
0338   //! e.g. row first, column next.
0339   template <typename ColorType_t>
0340   const ColorType_t& Value(size_t theRow, size_t theCol) const
0341   {
0342     return *reinterpret_cast<const ColorType_t*>(myData.Value(theRow, theCol));
0343   }
0344 
0345   //! Access image pixel with specified color type.
0346   //! Indexation starts from 0.
0347   //! This method does not perform any type checks - use on own risk (check Format() before)!
0348   //! WARNING: Input parameters are defined in the decreasing majority following memory layout -
0349   //! e.g. row first, column next.
0350   template <typename ColorType_t>
0351   ColorType_t& ChangeValue(size_t theRow, size_t theCol)
0352   {
0353     return *reinterpret_cast<ColorType_t*>(myData.ChangeValue(theRow, theCol));
0354   }
0355 
0356   //! Access image pixel as raw data pointer.
0357   //! Indexation starts from 0.
0358   //! This method does not perform any type checks - use on own risk (check Format() before)!
0359   //! WARNING: Input parameters are defined in the decreasing majority following memory layout -
0360   //! e.g. row first, column next.
0361   const uint8_t* RawValue(size_t theRow, size_t theCol) const
0362   {
0363     return myData.Value(theRow, theCol);
0364   }
0365 
0366   //! Access image pixel as raw data pointer.
0367   //! Indexation starts from 0.
0368   //! This method does not perform any type checks - use on own risk (check Format() before)!
0369   //! WARNING: Input parameters are defined in the decreasing majority following memory layout -
0370   //! e.g. row first, column next.
0371   uint8_t* ChangeRawValue(size_t theRow, size_t theCol)
0372   {
0373     return myData.ChangeValue(theRow, theCol);
0374   }
0375 
0376   //! Access image pixel with specified color type.
0377   //! Indexation starts from 0.
0378   //! This method does not perform any type checks - use on own risk (check Format() before)!
0379   //! WARNING: Input parameters are defined in traditional X, Y order.
0380   template <typename ColorType_t>
0381   const ColorType_t& ValueXY(size_t theX, size_t theY) const
0382   {
0383     return *reinterpret_cast<const ColorType_t*>(myData.ValueXY(theX, theY));
0384   }
0385 
0386   //! Access image pixel with specified color type.
0387   //! Indexation starts from 0.
0388   //! This method does not perform any type checks - use on own risk (check Format() before)!
0389   //! WARNING: Input parameters are defined in traditional X, Y order.
0390   template <typename ColorType_t>
0391   ColorType_t& ChangeValueXY(size_t theX, size_t theY)
0392   {
0393     return *reinterpret_cast<ColorType_t*>(myData.ChangeValueXY(theX, theY));
0394   }
0395 
0396   //! Access image pixel as raw data pointer.
0397   //! Indexation starts from 0.
0398   //! This method does not perform any type checks - use on own risk (check Format() before)!
0399   //! WARNING: Input parameters are defined in traditional X, Y order.
0400   const uint8_t* RawValueXY(size_t theX, size_t theY) const { return myData.ValueXY(theX, theY); }
0401 
0402   //! Access image pixel as raw data pointer.
0403   //! Indexation starts from 0.
0404   //! This method does not perform any type checks - use on own risk (check Format() before)!
0405   //! WARNING: Input parameters are defined in traditional X, Y order.
0406   uint8_t* ChangeRawValueXY(size_t theX, size_t theY) { return myData.ChangeValueXY(theX, theY); }
0407 
0408 public:
0409   //! Access image pixel with specified color type.
0410   //! Indexation starts from 0.
0411   //! This method does not perform any type checks - use on own risk (check Format() before)!
0412   //! WARNING: Input parameters are defined in traditional X, Y, Z order.
0413   template <typename ColorType_t>
0414   const ColorType_t& ValueXYZ(size_t theX, size_t theY, size_t theZ) const
0415   {
0416     return *reinterpret_cast<const ColorType_t*>(myData.ValueXYZ(theX, theY, theZ));
0417   }
0418 
0419   //! Access image pixel with specified color type.
0420   //! Indexation starts from 0.
0421   //! This method does not perform any type checks - use on own risk (check Format() before)!
0422   //! WARNING: Input parameters are defined in traditional X, Y, Z order.
0423   template <typename ColorType_t>
0424   ColorType_t& ChangeValueXYZ(size_t theX, size_t theY, size_t theZ)
0425   {
0426     return *reinterpret_cast<ColorType_t*>(myData.ChangeValueXYZ(theX, theY, theZ));
0427   }
0428 
0429   //! Access image pixel as raw data pointer.
0430   //! Indexation starts from 0.
0431   //! This method does not perform any type checks - use on own risk (check Format() before)!
0432   //! WARNING: Input parameters are defined in traditional X, Y, Z order.
0433   const uint8_t* RawValueXYZ(size_t theX, size_t theY, size_t theZ) const
0434   {
0435     return myData.ValueXYZ(theX, theY, theZ);
0436   }
0437 
0438   //! Access image pixel as raw data pointer.
0439   //! Indexation starts from 0.
0440   //! This method does not perform any type checks - use on own risk (check Format() before)!
0441   //! WARNING: Input parameters are defined in traditional X, Y, Z order.
0442   uint8_t* ChangeRawValueXYZ(size_t theX, size_t theY, size_t theZ)
0443   {
0444     return myData.ChangeValueXYZ(theX, theY, theZ);
0445   }
0446 
0447 public:
0448   //! Convert 16-bit half-float value into 32-bit float (simple conversion).
0449   static float ConvertFromHalfFloat(const uint16_t theHalf)
0450   {
0451     union FloatUint32 {
0452       float    Float32;
0453       uint32_t UInt32;
0454     };
0455 
0456     const uint32_t e = (theHalf & 0x7C00) >> 10; // exponent
0457     const uint32_t m = (theHalf & 0x03FF) << 13; // mantissa
0458     FloatUint32    mf, aRes;
0459     mf.Float32 = (float)m;
0460     // clang-format off
0461     const uint32_t v = mf.UInt32 >> 23; // evil log2 bit hack to count leading zeros in denormalized format
0462     aRes.UInt32 = (theHalf & 0x8000)<<16 | (e != 0) * ((e + 112) << 23 | m) | ((e == 0) & (m != 0)) * ((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000)); // sign : normalized : denormalized
0463     // clang-format on
0464     return aRes.Float32;
0465   }
0466 
0467   //! Convert 32-bit float value into IEEE-754 16-bit floating-point format without infinity:
0468   //! 1-5-10, exp-15, +-131008.0, +-6.1035156E-5, +-5.9604645E-8, 3.311 digits.
0469   static uint16_t ConvertToHalfFloat(const float theFloat)
0470   {
0471     union FloatUint32 {
0472       float    Float32;
0473       uint32_t UInt32;
0474     };
0475 
0476     FloatUint32 anInput;
0477     anInput.Float32 = theFloat;
0478     // clang-format off
0479     const uint32_t b = anInput.UInt32 + 0x00001000; // round-to-nearest-even: add last bit after truncated mantissa
0480     const uint32_t e = (b & 0x7F800000) >> 23; // exponent
0481     const uint32_t m =  b & 0x007FFFFF; // mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
0482     return (uint16_t)((b & 0x80000000) >> 16 | (e > 112) * ((((e - 112) << 10) & 0x7C00) | m >> 13)
0483          | ((e < 113) & (e > 101)) * ((((0x007FF000 + m) >> (125 - e)) + 1) >> 1) | (e > 143) * 0x7FFF); // sign : normalized : denormalized : saturate
0484     // clang-format on
0485   }
0486 
0487 protected:
0488   Image_PixMapData myData;      //!< data buffer
0489   Image_Format     myImgFormat; //!< pixel format
0490 
0491 private:
0492   //! Copying allowed only within Handles
0493   Image_PixMap(const Image_PixMap&)            = delete;
0494   Image_PixMap& operator=(const Image_PixMap&) = delete;
0495 };
0496 
0497 #endif // _Image_PixMap_H__