7043cdd2c6d000a248f222b41a57557c84b172af
[occt.git] / src / Image / Image_PixMap.cxx
1 // Created on: 2010-07-18
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2010-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <Image_PixMap.hxx>
17
18 #ifdef _MSC_VER
19   #include <malloc.h>
20 #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
21   #include <mm_malloc.h>
22 #else
23   extern "C" int posix_memalign (void** thePtr, size_t theAlign, size_t theBytesCount);
24 #endif
25
26 template<typename TypePtr>
27 inline TypePtr MemAllocAligned (const Standard_Size& theBytesCount,
28                                 const Standard_Size& theAlign = 16)
29 {
30 #if defined(_MSC_VER)
31   return (TypePtr )_aligned_malloc (theBytesCount, theAlign);
32 #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
33   return (TypePtr )     _mm_malloc (theBytesCount, theAlign);
34 #else
35   void* aPtr;
36   if (posix_memalign (&aPtr, theAlign, theBytesCount))
37   {
38     aPtr = NULL;
39   }
40   return (TypePtr )aPtr;
41 #endif
42 }
43
44 inline void MemFreeAligned (void* thePtrAligned)
45 {
46 #if defined(_MSC_VER)
47   _aligned_free (thePtrAligned);
48 #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
49   _mm_free (thePtrAligned);
50 #else
51   free (thePtrAligned);
52 #endif
53 }
54
55 IMPLEMENT_STANDARD_HANDLE (Image_PixMap, Standard_Transient)
56 IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap, Standard_Transient)
57
58 // =======================================================================
59 // function : Image_PixMap
60 // purpose  :
61 // =======================================================================
62 Image_PixMap::Image_PixMap()
63 : myImgFormat (Image_PixMap::ImgGray),
64   myIsOwnPointer (true)
65 {
66   memset (&myData, 0, sizeof(myData));
67   myData.mySizeBPP   = 1;
68   myData.myTopToDown = Standard_Size(-1);
69   setFormat (Image_PixMap::ImgGray);
70 }
71
72 // =======================================================================
73 // function : ~Image_PixMap
74 // purpose  :
75 // =======================================================================
76 Image_PixMap::~Image_PixMap()
77 {
78   Clear();
79 }
80
81 Standard_Size Image_PixMap::SizePixelBytes (const Image_PixMap::ImgFormat thePixelFormat)
82 {
83   switch (thePixelFormat)
84   {
85     case ImgGrayF:
86       return sizeof(float);
87     case ImgRGBAF:
88     case ImgBGRAF:
89       return sizeof(float) * 4;
90     case ImgRGBF:
91     case ImgBGRF:
92       return sizeof(float) * 3;
93     case ImgRGBA:
94     case ImgBGRA:
95       return 4;
96     case ImgRGB32:
97     case ImgBGR32:
98       return 4;
99     case ImgRGB:
100     case ImgBGR:
101       return 3;
102     case ImgGray:
103     default:
104       return 1;
105   }
106 }
107
108 // =======================================================================
109 // function : setFormat
110 // purpose  :
111 // =======================================================================
112 void Image_PixMap::setFormat (Image_PixMap::ImgFormat thePixelFormat)
113 {
114   myImgFormat      = thePixelFormat;
115   myData.mySizeBPP = SizePixelBytes (myImgFormat);
116 }
117
118 // =======================================================================
119 // function : setTopDown
120 // purpose  :
121 // =======================================================================
122 void Image_PixMap::setTopDown()
123 {
124   myData.myTopRowPtr = ((myData.myTopToDown == 1 || myData.myDataPtr == NULL)
125                      ? myData.myDataPtr : (myData.myDataPtr + myData.mySizeRowBytes * (myData.mySizeY - 1)));
126 }
127
128 // =======================================================================
129 // function : InitWrapper
130 // purpose  :
131 // =======================================================================
132 bool Image_PixMap::InitWrapper (Image_PixMap::ImgFormat thePixelFormat,
133                                 Standard_Byte*          theDataPtr,
134                                 const Standard_Size     theSizeX,
135                                 const Standard_Size     theSizeY,
136                                 const Standard_Size     theSizeRowBytes)
137 {
138   Clear (thePixelFormat);
139   if ((theSizeX == 0) || (theSizeY == 0) || (theDataPtr == NULL))
140   {
141     return false;
142   }
143   myData.mySizeX        = theSizeX;
144   myData.mySizeY        = theSizeY;
145   myData.mySizeRowBytes = (theSizeRowBytes != 0) ? theSizeRowBytes : (theSizeX * myData.mySizeBPP);
146   myData.myDataPtr      = theDataPtr;
147   myIsOwnPointer = false;
148   setTopDown();
149   return true;
150 }
151
152 // =======================================================================
153 // function : InitTrash
154 // purpose  :
155 // =======================================================================
156 bool Image_PixMap::InitTrash (Image_PixMap::ImgFormat thePixelFormat,
157                               const Standard_Size     theSizeX,
158                               const Standard_Size     theSizeY,
159                               const Standard_Size     theSizeRowBytes)
160 {
161   Clear (thePixelFormat);
162   if ((theSizeX == 0) || (theSizeY == 0))
163   {
164     return false;
165   }
166   myData.mySizeX        = theSizeX;
167   myData.mySizeY        = theSizeY;
168   myData.mySizeRowBytes = myData.mySizeX * myData.mySizeBPP;
169   if (theSizeRowBytes > myData.mySizeRowBytes)
170   {
171     // use argument only if it greater
172     myData.mySizeRowBytes = theSizeRowBytes;
173   }
174   myData.myDataPtr = MemAllocAligned<Standard_Byte*> (SizeBytes());
175   myIsOwnPointer   = true;
176   setTopDown();
177   return myData.myDataPtr != NULL;
178 }
179
180 // =======================================================================
181 // function : InitZero
182 // purpose  :
183 // =======================================================================
184 bool Image_PixMap::InitZero (Image_PixMap::ImgFormat thePixelFormat,
185                              const Standard_Size     theSizeX,
186                              const Standard_Size     theSizeY,
187                              const Standard_Size     theSizeRowBytes,
188                              const Standard_Byte     theValue)
189 {
190   if (!InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes))
191   {
192     return false;
193   }
194   memset (myData.myDataPtr, (int )theValue, SizeBytes());
195   return true;
196 }
197
198 // =======================================================================
199 // function : InitCopy
200 // purpose  :
201 // =======================================================================
202 bool Image_PixMap::InitCopy (const Image_PixMap& theCopy)
203 {
204   if (&theCopy == this)
205   {
206     // self-copying disallowed
207     return false;
208   }
209   if (InitTrash (theCopy.myImgFormat, theCopy.myData.mySizeX, theCopy.myData.mySizeY, theCopy.myData.mySizeRowBytes))
210   {
211     memcpy (myData.myDataPtr, theCopy.myData.myDataPtr, theCopy.SizeBytes());
212     return true;
213   }
214   return false;
215 }
216
217 // =======================================================================
218 // function : Clear
219 // purpose  :
220 // =======================================================================
221 void Image_PixMap::Clear (Image_PixMap::ImgFormat thePixelFormat)
222 {
223   if (myIsOwnPointer && (myData.myDataPtr != NULL))
224   {
225     MemFreeAligned (myData.myDataPtr);
226   }
227   myData.myDataPtr = myData.myTopRowPtr = NULL;
228   myIsOwnPointer = true;
229   myData.mySizeX = myData.mySizeY = myData.mySizeRowBytes = 0;
230   setFormat (thePixelFormat);
231 }
232
233 // =======================================================================
234 // function : PixelColor
235 // purpose  :
236 // =======================================================================
237 Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
238                                          const Standard_Integer theY,
239                                          Quantity_Parameter&    theAlpha) const
240 {
241   if (IsEmpty() ||
242       theX < 0 || (Standard_Size )theX >= myData.mySizeX ||
243       theY < 0 || (Standard_Size )theY >= myData.mySizeY)
244   {
245     theAlpha = 0.0; // transparent
246     return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
247   }
248
249   switch (myImgFormat)
250   {
251     case ImgGrayF:
252     {
253       const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
254       theAlpha = 1.0; // opaque
255       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel)),
256                              Quantity_Parameter (Standard_Real (aPixel)),
257                              Quantity_Parameter (Standard_Real (aPixel)),
258                              Quantity_TOC_RGB);
259     }
260     case ImgRGBAF:
261     {
262       const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX);
263       theAlpha = aPixel.a();
264       return Quantity_Color (Quantity_Parameter (aPixel.r()),
265                              Quantity_Parameter (aPixel.g()),
266                              Quantity_Parameter (aPixel.b()),
267                              Quantity_TOC_RGB);
268     }
269     case ImgBGRAF:
270     {    
271       const Image_ColorBGRAF& aPixel = Value<Image_ColorBGRAF> (theY, theX);
272       theAlpha = aPixel.a();
273       return Quantity_Color (Quantity_Parameter (aPixel.r()),
274                              Quantity_Parameter (aPixel.g()),
275                              Quantity_Parameter (aPixel.b()),
276                              Quantity_TOC_RGB);
277     }
278     case ImgRGBF:
279     {
280       const Image_ColorRGBF& aPixel = Value<Image_ColorRGBF> (theY, theX);
281       theAlpha =  1.0; // opaque
282       return Quantity_Color (Quantity_Parameter (aPixel.r()),
283                              Quantity_Parameter (aPixel.g()),
284                              Quantity_Parameter (aPixel.b()),
285                              Quantity_TOC_RGB);
286     }
287     case ImgBGRF:
288     {
289       const Image_ColorBGRF& aPixel = Value<Image_ColorBGRF> (theY, theX);
290       theAlpha =  1.0; // opaque
291       return Quantity_Color (Quantity_Parameter (aPixel.r()),
292                              Quantity_Parameter (aPixel.g()),
293                              Quantity_Parameter (aPixel.b()),
294                              Quantity_TOC_RGB);
295     }
296     case ImgRGBA:
297     {
298       const Image_ColorRGBA& aPixel = Value<Image_ColorRGBA> (theY, theX);
299       theAlpha = Standard_Real (aPixel.a()) / 255.0;
300       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
301                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
302                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
303                              Quantity_TOC_RGB);
304     }
305     case ImgBGRA:
306     {
307       const Image_ColorBGRA& aPixel = Value<Image_ColorBGRA> (theY, theX);
308       theAlpha = Standard_Real (aPixel.a()) / 255.0;
309       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
310                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
311                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
312                              Quantity_TOC_RGB);
313     }
314     case ImgRGB32:
315     {
316       const Image_ColorRGB32& aPixel = Value<Image_ColorRGB32> (theY, theX);
317       theAlpha = 1.0; // opaque
318       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
319                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
320                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
321                              Quantity_TOC_RGB);
322     }
323     case ImgBGR32:
324     {
325       const Image_ColorBGR32& aPixel = Value<Image_ColorBGR32> (theY, theX);
326       theAlpha = 1.0; // opaque
327       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
328                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
329                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
330                              Quantity_TOC_RGB);
331     }
332     case ImgRGB:
333     {
334       const Image_ColorRGB& aPixel = Value<Image_ColorRGB> (theY, theX);
335       theAlpha = 1.0; // opaque
336       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
337                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
338                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
339                              Quantity_TOC_RGB);
340     }
341     case ImgBGR:
342     {
343       const Image_ColorBGR& aPixel = Value<Image_ColorBGR> (theY, theX);
344       theAlpha = 1.0; // opaque
345       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
346                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
347                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
348                              Quantity_TOC_RGB);
349     }
350     case ImgGray:
351     {
352       const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
353       theAlpha = 1.0; // opaque
354       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel) / 255.0),
355                              Quantity_Parameter (Standard_Real (aPixel) / 255.0),
356                              Quantity_Parameter (Standard_Real (aPixel) / 255.0),
357                              Quantity_TOC_RGB);
358     }
359     default:
360     {
361       // not supported image type
362       theAlpha = 0.0; // transparent
363       return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
364     }
365   }
366 }