362c154a25140876f863c11da6b0659ebe551ea9
[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 #include <NCollection_AlignedAllocator.hxx>
18 #include <Standard_ProgramError.hxx>
19
20 #include <algorithm>
21
22
23
24
25 IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap,Standard_Transient)
26
27 // =======================================================================
28 // function : Image_PixMap
29 // purpose  :
30 // =======================================================================
31 Image_PixMap::Image_PixMap()
32 : myImgFormat (Image_PixMap::ImgGray)
33 {
34   //
35 }
36
37 // =======================================================================
38 // function : ~Image_PixMap
39 // purpose  :
40 // =======================================================================
41 Image_PixMap::~Image_PixMap()
42 {
43   Clear();
44 }
45
46 Standard_Size Image_PixMap::SizePixelBytes (const Image_PixMap::ImgFormat thePixelFormat)
47 {
48   switch (thePixelFormat)
49   {
50     case ImgGrayF:
51     case ImgAlphaF:
52       return sizeof(float);
53     case ImgRGBAF:
54     case ImgBGRAF:
55       return sizeof(float) * 4;
56     case ImgRGBF:
57     case ImgBGRF:
58       return sizeof(float) * 3;
59     case ImgRGBA:
60     case ImgBGRA:
61       return 4;
62     case ImgRGB32:
63     case ImgBGR32:
64       return 4;
65     case ImgRGB:
66     case ImgBGR:
67       return 3;
68     case ImgGray:
69     case ImgAlpha:
70       return 1;
71     case ImgUNKNOWN:
72       return 1;
73   }
74   return 1;
75 }
76
77 // =======================================================================
78 // function : SetFormat
79 // purpose  :
80 // =======================================================================
81 void Image_PixMap::SetFormat (Image_PixMap::ImgFormat thePixelFormat)
82 {
83   if (myImgFormat == thePixelFormat)
84   {
85     return;
86   }
87
88   if (!IsEmpty()
89     && SizePixelBytes (myImgFormat) != SizePixelBytes (thePixelFormat))
90   {
91     Standard_ProgramError::Raise ("Image_PixMap::SetFormat() - incompatible pixel format");
92     return;
93   }
94
95   myImgFormat = thePixelFormat;
96 }
97
98 // =======================================================================
99 // function : InitWrapper
100 // purpose  :
101 // =======================================================================
102 bool Image_PixMap::InitWrapper (Image_PixMap::ImgFormat thePixelFormat,
103                                 Standard_Byte*          theDataPtr,
104                                 const Standard_Size     theSizeX,
105                                 const Standard_Size     theSizeY,
106                                 const Standard_Size     theSizeRowBytes)
107 {
108   Clear();
109   myImgFormat = thePixelFormat;
110   if ((theSizeX == 0) || (theSizeY == 0) || (theDataPtr == NULL))
111   {
112     return false;
113   }
114
115   Handle(NCollection_BaseAllocator) anEmptyAlloc;
116   myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (thePixelFormat),
117                theSizeX, theSizeY, theSizeRowBytes, theDataPtr);
118   return true;
119 }
120
121 // =======================================================================
122 // function : InitTrash
123 // purpose  :
124 // =======================================================================
125 bool Image_PixMap::InitTrash (Image_PixMap::ImgFormat thePixelFormat,
126                               const Standard_Size     theSizeX,
127                               const Standard_Size     theSizeY,
128                               const Standard_Size     theSizeRowBytes)
129 {
130   Clear();
131   myImgFormat = thePixelFormat;
132   if ((theSizeX == 0) || (theSizeY == 0))
133   {
134     return false;
135   }
136
137   // use argument only if it greater
138   const Standard_Size aSizeRowBytes = std::max (theSizeRowBytes, theSizeX * SizePixelBytes (thePixelFormat));
139   Handle(NCollection_BaseAllocator) anAlloc = new NCollection_AlignedAllocator (16);
140   myData.Init (anAlloc, Image_PixMap::SizePixelBytes (thePixelFormat),
141                theSizeX, theSizeY, aSizeRowBytes, NULL);
142   return !myData.IsEmpty();
143 }
144
145 // =======================================================================
146 // function : InitZero
147 // purpose  :
148 // =======================================================================
149 bool Image_PixMap::InitZero (Image_PixMap::ImgFormat thePixelFormat,
150                              const Standard_Size     theSizeX,
151                              const Standard_Size     theSizeY,
152                              const Standard_Size     theSizeRowBytes,
153                              const Standard_Byte     theValue)
154 {
155   if (!InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes))
156   {
157     return false;
158   }
159   memset (myData.ChangeData(), (int )theValue, SizeBytes());
160   return true;
161 }
162
163 // =======================================================================
164 // function : InitCopy
165 // purpose  :
166 // =======================================================================
167 bool Image_PixMap::InitCopy (const Image_PixMap& theCopy)
168 {
169   if (&theCopy == this)
170   {
171     // self-copying disallowed
172     return false;
173   }
174   if (InitTrash (theCopy.myImgFormat, theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
175   {
176     memcpy (myData.ChangeData(), theCopy.myData.Data(), theCopy.SizeBytes());
177     return true;
178   }
179   return false;
180 }
181
182 // =======================================================================
183 // function : Clear
184 // purpose  :
185 // =======================================================================
186 void Image_PixMap::Clear()
187 {
188   Handle(NCollection_BaseAllocator) anEmptyAlloc;
189   myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (myImgFormat),
190                0, 0, 0, NULL);
191 }
192
193 // =======================================================================
194 // function : PixelColor
195 // purpose  :
196 // =======================================================================
197 Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
198                                          const Standard_Integer theY,
199                                          Quantity_Parameter&    theAlpha) const
200 {
201   if (IsEmpty()
202    || theX < 0 || (Standard_Size )theX >= SizeX()
203    || theY < 0 || (Standard_Size )theY >= SizeY())
204   {
205     theAlpha = 0.0; // transparent
206     return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
207   }
208
209   switch (myImgFormat)
210   {
211     case ImgGrayF:
212     {
213       const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
214       theAlpha = 1.0; // opaque
215       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel)),
216                              Quantity_Parameter (Standard_Real (aPixel)),
217                              Quantity_Parameter (Standard_Real (aPixel)),
218                              Quantity_TOC_RGB);
219     }
220     case ImgAlphaF:
221     {
222       const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
223       theAlpha = aPixel;
224       return Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB);
225     }
226     case ImgRGBAF:
227     {
228       const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX);
229       theAlpha = aPixel.a();
230       return Quantity_Color (Quantity_Parameter (aPixel.r()),
231                              Quantity_Parameter (aPixel.g()),
232                              Quantity_Parameter (aPixel.b()),
233                              Quantity_TOC_RGB);
234     }
235     case ImgBGRAF:
236     {    
237       const Image_ColorBGRAF& aPixel = Value<Image_ColorBGRAF> (theY, theX);
238       theAlpha = aPixel.a();
239       return Quantity_Color (Quantity_Parameter (aPixel.r()),
240                              Quantity_Parameter (aPixel.g()),
241                              Quantity_Parameter (aPixel.b()),
242                              Quantity_TOC_RGB);
243     }
244     case ImgRGBF:
245     {
246       const Image_ColorRGBF& aPixel = Value<Image_ColorRGBF> (theY, theX);
247       theAlpha =  1.0; // opaque
248       return Quantity_Color (Quantity_Parameter (aPixel.r()),
249                              Quantity_Parameter (aPixel.g()),
250                              Quantity_Parameter (aPixel.b()),
251                              Quantity_TOC_RGB);
252     }
253     case ImgBGRF:
254     {
255       const Image_ColorBGRF& aPixel = Value<Image_ColorBGRF> (theY, theX);
256       theAlpha =  1.0; // opaque
257       return Quantity_Color (Quantity_Parameter (aPixel.r()),
258                              Quantity_Parameter (aPixel.g()),
259                              Quantity_Parameter (aPixel.b()),
260                              Quantity_TOC_RGB);
261     }
262     case ImgRGBA:
263     {
264       const Image_ColorRGBA& aPixel = Value<Image_ColorRGBA> (theY, theX);
265       theAlpha = Standard_Real (aPixel.a()) / 255.0;
266       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
267                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
268                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
269                              Quantity_TOC_RGB);
270     }
271     case ImgBGRA:
272     {
273       const Image_ColorBGRA& aPixel = Value<Image_ColorBGRA> (theY, theX);
274       theAlpha = Standard_Real (aPixel.a()) / 255.0;
275       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
276                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
277                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
278                              Quantity_TOC_RGB);
279     }
280     case ImgRGB32:
281     {
282       const Image_ColorRGB32& aPixel = Value<Image_ColorRGB32> (theY, theX);
283       theAlpha = 1.0; // opaque
284       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
285                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
286                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
287                              Quantity_TOC_RGB);
288     }
289     case ImgBGR32:
290     {
291       const Image_ColorBGR32& aPixel = Value<Image_ColorBGR32> (theY, theX);
292       theAlpha = 1.0; // opaque
293       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
294                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
295                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
296                              Quantity_TOC_RGB);
297     }
298     case ImgRGB:
299     {
300       const Image_ColorRGB& aPixel = Value<Image_ColorRGB> (theY, theX);
301       theAlpha = 1.0; // opaque
302       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
303                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
304                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
305                              Quantity_TOC_RGB);
306     }
307     case ImgBGR:
308     {
309       const Image_ColorBGR& aPixel = Value<Image_ColorBGR> (theY, theX);
310       theAlpha = 1.0; // opaque
311       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
312                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
313                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
314                              Quantity_TOC_RGB);
315     }
316     case ImgGray:
317     {
318       const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
319       theAlpha = 1.0; // opaque
320       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel) / 255.0),
321                              Quantity_Parameter (Standard_Real (aPixel) / 255.0),
322                              Quantity_Parameter (Standard_Real (aPixel) / 255.0),
323                              Quantity_TOC_RGB);
324     }
325     case ImgAlpha:
326     {
327       const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
328       theAlpha = Standard_Real (aPixel) / 255.0;
329       return Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB);
330     }
331     case ImgUNKNOWN:
332     {
333       break;
334     }
335   }
336
337   // unsupported image type
338   theAlpha = 0.0; // transparent
339   return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
340 }
341
342 // =======================================================================
343 // function : SwapRgbaBgra
344 // purpose  :
345 // =======================================================================
346 bool Image_PixMap::SwapRgbaBgra (Image_PixMap& theImage)
347 {
348   switch (theImage.Format())
349   {
350     case Image_PixMap::ImgBGR32:
351     case Image_PixMap::ImgRGB32:
352     case Image_PixMap::ImgBGRA:
353     case Image_PixMap::ImgRGBA:
354     {
355       const bool toResetAlpha = theImage.Format() == Image_PixMap::ImgBGR32
356                              || theImage.Format() == Image_PixMap::ImgRGB32;
357       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
358       {
359         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
360         {
361           Image_ColorRGBA& aPixel     = theImage.ChangeValue<Image_ColorRGBA> (aRow, aCol);
362           Image_ColorBGRA  aPixelCopy = theImage.Value      <Image_ColorBGRA> (aRow, aCol);
363           aPixel.r() = aPixelCopy.r();
364           aPixel.g() = aPixelCopy.g();
365           aPixel.b() = aPixelCopy.b();
366           if (toResetAlpha)
367           {
368             aPixel.a() = 255;
369           }
370         }
371       }
372       return true;
373     }
374     case Image_PixMap::ImgBGR:
375     case Image_PixMap::ImgRGB:
376     {
377       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
378       {
379         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
380         {
381           Image_ColorRGB& aPixel     = theImage.ChangeValue<Image_ColorRGB> (aRow, aCol);
382           Image_ColorBGR  aPixelCopy = theImage.Value      <Image_ColorBGR> (aRow, aCol);
383           aPixel.r() = aPixelCopy.r();
384           aPixel.g() = aPixelCopy.g();
385           aPixel.b() = aPixelCopy.b();
386         }
387       }
388       return true;
389     }
390     case Image_PixMap::ImgBGRF:
391     case Image_PixMap::ImgRGBF:
392     case Image_PixMap::ImgBGRAF:
393     case Image_PixMap::ImgRGBAF:
394     {
395       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
396       {
397         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
398         {
399           Image_ColorRGBF& aPixel     = theImage.ChangeValue<Image_ColorRGBF> (aRow, aCol);
400           Image_ColorBGRF  aPixelCopy = theImage.Value      <Image_ColorBGRF> (aRow, aCol);
401           aPixel.r() = aPixelCopy.r();
402           aPixel.g() = aPixelCopy.g();
403           aPixel.b() = aPixelCopy.b();
404         }
405       }
406       return true;
407     }
408     default: return false;
409   }
410 }