0028441: Coding Rules - move out nested Image_PixMap::ImgFormat enumeration to dedica...
[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 IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap,Standard_Transient)
23
24 // =======================================================================
25 // function : Image_PixMap
26 // purpose  :
27 // =======================================================================
28 Image_PixMap::Image_PixMap()
29 : myImgFormat (Image_Format_Gray)
30 {
31   //
32 }
33
34 // =======================================================================
35 // function : ~Image_PixMap
36 // purpose  :
37 // =======================================================================
38 Image_PixMap::~Image_PixMap()
39 {
40   Clear();
41 }
42
43 Standard_Size Image_PixMap::SizePixelBytes (const Image_Format thePixelFormat)
44 {
45   switch (thePixelFormat)
46   {
47     case Image_Format_GrayF:
48     case Image_Format_AlphaF:
49       return sizeof(float);
50     case Image_Format_RGBAF:
51     case Image_Format_BGRAF:
52       return sizeof(float) * 4;
53     case Image_Format_RGBF:
54     case Image_Format_BGRF:
55       return sizeof(float) * 3;
56     case Image_Format_RGBA:
57     case Image_Format_BGRA:
58       return 4;
59     case Image_Format_RGB32:
60     case Image_Format_BGR32:
61       return 4;
62     case Image_Format_RGB:
63     case Image_Format_BGR:
64       return 3;
65     case Image_Format_Gray:
66     case Image_Format_Alpha:
67       return 1;
68     case Image_Format_UNKNOWN:
69       return 1;
70   }
71   return 1;
72 }
73
74 // =======================================================================
75 // function : SetFormat
76 // purpose  :
77 // =======================================================================
78 void Image_PixMap::SetFormat (Image_Format thePixelFormat)
79 {
80   if (myImgFormat == thePixelFormat)
81   {
82     return;
83   }
84
85   if (!IsEmpty()
86     && SizePixelBytes (myImgFormat) != SizePixelBytes (thePixelFormat))
87   {
88     throw Standard_ProgramError("Image_PixMap::SetFormat() - incompatible pixel format");
89     return;
90   }
91
92   myImgFormat = thePixelFormat;
93 }
94
95 // =======================================================================
96 // function : InitWrapper
97 // purpose  :
98 // =======================================================================
99 bool Image_PixMap::InitWrapper (Image_Format        thePixelFormat,
100                                 Standard_Byte*      theDataPtr,
101                                 const Standard_Size theSizeX,
102                                 const Standard_Size theSizeY,
103                                 const Standard_Size theSizeRowBytes)
104 {
105   Clear();
106   myImgFormat = thePixelFormat;
107   if ((theSizeX == 0) || (theSizeY == 0) || (theDataPtr == NULL))
108   {
109     return false;
110   }
111
112   Handle(NCollection_BaseAllocator) anEmptyAlloc;
113   myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (thePixelFormat),
114                theSizeX, theSizeY, theSizeRowBytes, theDataPtr);
115   return true;
116 }
117
118 // =======================================================================
119 // function : InitTrash
120 // purpose  :
121 // =======================================================================
122 bool Image_PixMap::InitTrash (Image_Format        thePixelFormat,
123                               const Standard_Size theSizeX,
124                               const Standard_Size theSizeY,
125                               const Standard_Size theSizeRowBytes)
126 {
127   Clear();
128   myImgFormat = thePixelFormat;
129   if ((theSizeX == 0) || (theSizeY == 0))
130   {
131     return false;
132   }
133
134   // use argument only if it greater
135   const Standard_Size aSizeRowBytes = std::max (theSizeRowBytes, theSizeX * SizePixelBytes (thePixelFormat));
136   Handle(NCollection_BaseAllocator) anAlloc = new NCollection_AlignedAllocator (16);
137   myData.Init (anAlloc, Image_PixMap::SizePixelBytes (thePixelFormat),
138                theSizeX, theSizeY, aSizeRowBytes, NULL);
139   return !myData.IsEmpty();
140 }
141
142 // =======================================================================
143 // function : InitZero
144 // purpose  :
145 // =======================================================================
146 bool Image_PixMap::InitZero (Image_Format        thePixelFormat,
147                              const Standard_Size theSizeX,
148                              const Standard_Size theSizeY,
149                              const Standard_Size theSizeRowBytes,
150                              const Standard_Byte theValue)
151 {
152   if (!InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes))
153   {
154     return false;
155   }
156   memset (myData.ChangeData(), (int )theValue, SizeBytes());
157   return true;
158 }
159
160 // =======================================================================
161 // function : InitCopy
162 // purpose  :
163 // =======================================================================
164 bool Image_PixMap::InitCopy (const Image_PixMap& theCopy)
165 {
166   if (&theCopy == this)
167   {
168     // self-copying disallowed
169     return false;
170   }
171   if (InitTrash (theCopy.myImgFormat, theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
172   {
173     memcpy (myData.ChangeData(), theCopy.myData.Data(), theCopy.SizeBytes());
174     return true;
175   }
176   return false;
177 }
178
179 // =======================================================================
180 // function : Clear
181 // purpose  :
182 // =======================================================================
183 void Image_PixMap::Clear()
184 {
185   Handle(NCollection_BaseAllocator) anEmptyAlloc;
186   myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (myImgFormat),
187                0, 0, 0, NULL);
188 }
189
190 // =======================================================================
191 // function : PixelColor
192 // purpose  :
193 // =======================================================================
194 Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX,
195                                          const Standard_Integer theY,
196                                          Quantity_Parameter&    theAlpha) const
197 {
198   if (IsEmpty()
199    || theX < 0 || (Standard_Size )theX >= SizeX()
200    || theY < 0 || (Standard_Size )theY >= SizeY())
201   {
202     theAlpha = 0.0; // transparent
203     return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
204   }
205
206   switch (myImgFormat)
207   {
208     case Image_Format_GrayF:
209     {
210       const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
211       theAlpha = 1.0; // opaque
212       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel)),
213                              Quantity_Parameter (Standard_Real (aPixel)),
214                              Quantity_Parameter (Standard_Real (aPixel)),
215                              Quantity_TOC_RGB);
216     }
217     case Image_Format_AlphaF:
218     {
219       const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
220       theAlpha = aPixel;
221       return Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB);
222     }
223     case Image_Format_RGBAF:
224     {
225       const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX);
226       theAlpha = aPixel.a();
227       return Quantity_Color (Quantity_Parameter (aPixel.r()),
228                              Quantity_Parameter (aPixel.g()),
229                              Quantity_Parameter (aPixel.b()),
230                              Quantity_TOC_RGB);
231     }
232     case Image_Format_BGRAF:
233     {    
234       const Image_ColorBGRAF& aPixel = Value<Image_ColorBGRAF> (theY, theX);
235       theAlpha = aPixel.a();
236       return Quantity_Color (Quantity_Parameter (aPixel.r()),
237                              Quantity_Parameter (aPixel.g()),
238                              Quantity_Parameter (aPixel.b()),
239                              Quantity_TOC_RGB);
240     }
241     case Image_Format_RGBF:
242     {
243       const Image_ColorRGBF& aPixel = Value<Image_ColorRGBF> (theY, theX);
244       theAlpha =  1.0; // opaque
245       return Quantity_Color (Quantity_Parameter (aPixel.r()),
246                              Quantity_Parameter (aPixel.g()),
247                              Quantity_Parameter (aPixel.b()),
248                              Quantity_TOC_RGB);
249     }
250     case Image_Format_BGRF:
251     {
252       const Image_ColorBGRF& aPixel = Value<Image_ColorBGRF> (theY, theX);
253       theAlpha =  1.0; // opaque
254       return Quantity_Color (Quantity_Parameter (aPixel.r()),
255                              Quantity_Parameter (aPixel.g()),
256                              Quantity_Parameter (aPixel.b()),
257                              Quantity_TOC_RGB);
258     }
259     case Image_Format_RGBA:
260     {
261       const Image_ColorRGBA& aPixel = Value<Image_ColorRGBA> (theY, theX);
262       theAlpha = Standard_Real (aPixel.a()) / 255.0;
263       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
264                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
265                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
266                              Quantity_TOC_RGB);
267     }
268     case Image_Format_BGRA:
269     {
270       const Image_ColorBGRA& aPixel = Value<Image_ColorBGRA> (theY, theX);
271       theAlpha = Standard_Real (aPixel.a()) / 255.0;
272       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
273                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
274                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
275                              Quantity_TOC_RGB);
276     }
277     case Image_Format_RGB32:
278     {
279       const Image_ColorRGB32& aPixel = Value<Image_ColorRGB32> (theY, theX);
280       theAlpha = 1.0; // opaque
281       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
282                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
283                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
284                              Quantity_TOC_RGB);
285     }
286     case Image_Format_BGR32:
287     {
288       const Image_ColorBGR32& aPixel = Value<Image_ColorBGR32> (theY, theX);
289       theAlpha = 1.0; // opaque
290       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
291                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
292                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
293                              Quantity_TOC_RGB);
294     }
295     case Image_Format_RGB:
296     {
297       const Image_ColorRGB& aPixel = Value<Image_ColorRGB> (theY, theX);
298       theAlpha = 1.0; // opaque
299       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
300                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
301                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
302                              Quantity_TOC_RGB);
303     }
304     case Image_Format_BGR:
305     {
306       const Image_ColorBGR& aPixel = Value<Image_ColorBGR> (theY, theX);
307       theAlpha = 1.0; // opaque
308       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0),
309                              Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0),
310                              Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0),
311                              Quantity_TOC_RGB);
312     }
313     case Image_Format_Gray:
314     {
315       const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
316       theAlpha = 1.0; // opaque
317       return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel) / 255.0),
318                              Quantity_Parameter (Standard_Real (aPixel) / 255.0),
319                              Quantity_Parameter (Standard_Real (aPixel) / 255.0),
320                              Quantity_TOC_RGB);
321     }
322     case Image_Format_Alpha:
323     {
324       const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
325       theAlpha = Standard_Real (aPixel) / 255.0;
326       return Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB);
327     }
328     case Image_Format_UNKNOWN:
329     {
330       break;
331     }
332   }
333
334   // unsupported image type
335   theAlpha = 0.0; // transparent
336   return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB);
337 }
338
339 // =======================================================================
340 // function : SetPixelColor
341 // purpose  :
342 // =======================================================================
343 void Image_PixMap::SetPixelColor (const Standard_Integer theX,
344                                   const Standard_Integer theY,
345                                   const NCollection_Vec4<float>& theColor)
346 {
347   if (IsEmpty()
348    || theX < 0 || Standard_Size(theX) >= SizeX()
349    || theY < 0 || Standard_Size(theY) >= SizeY())
350   {
351     return;
352   }
353
354   switch (myImgFormat)
355   {
356     case Image_Format_GrayF:
357     {
358       ChangeValue<Standard_ShortReal> (theY, theX) = theColor.r();
359       return;
360     }
361     case Image_Format_AlphaF:
362     {
363       ChangeValue<Standard_ShortReal> (theY, theX) = theColor.a();
364       return;
365     }
366     case Image_Format_RGBAF:
367     {
368       Image_ColorRGBAF& aPixel = ChangeValue<Image_ColorRGBAF> (theY, theX);
369       aPixel.r() = theColor.r();
370       aPixel.g() = theColor.g();
371       aPixel.b() = theColor.b();
372       aPixel.a() = theColor.a();
373       return;
374     }
375     case Image_Format_BGRAF:
376     {
377       Image_ColorBGRAF& aPixel = ChangeValue<Image_ColorBGRAF> (theY, theX);
378       aPixel.r() = theColor.r();
379       aPixel.g() = theColor.g();
380       aPixel.b() = theColor.b();
381       aPixel.a() = theColor.a();
382       return;
383     }
384     case Image_Format_RGBF:
385     {
386       Image_ColorRGBF& aPixel = ChangeValue<Image_ColorRGBF> (theY, theX);
387       aPixel.r() = theColor.r();
388       aPixel.g() = theColor.g();
389       aPixel.b() = theColor.b();
390       return;
391     }
392     case Image_Format_BGRF:
393     {
394       Image_ColorBGRF& aPixel = ChangeValue<Image_ColorBGRF> (theY, theX);
395       aPixel.r() = theColor.r();
396       aPixel.g() = theColor.g();
397       aPixel.b() = theColor.b();
398       return;
399     }
400     case Image_Format_RGBA:
401     {
402       Image_ColorRGBA& aPixel = ChangeValue<Image_ColorRGBA> (theY, theX);
403       aPixel.r() = Standard_Byte(theColor.r() * 255.0f);
404       aPixel.g() = Standard_Byte(theColor.g() * 255.0f);
405       aPixel.b() = Standard_Byte(theColor.b() * 255.0f);
406       aPixel.a() = Standard_Byte(theColor.a() * 255.0f);
407       return;
408     }
409     case Image_Format_BGRA:
410     {
411       Image_ColorBGRA& aPixel = ChangeValue<Image_ColorBGRA> (theY, theX);
412       aPixel.r() = Standard_Byte(theColor.r() * 255.0f);
413       aPixel.g() = Standard_Byte(theColor.g() * 255.0f);
414       aPixel.b() = Standard_Byte(theColor.b() * 255.0f);
415       aPixel.a() = Standard_Byte(theColor.a() * 255.0f);
416       return;
417     }
418     case Image_Format_RGB32:
419     {
420       Image_ColorRGB32& aPixel = ChangeValue<Image_ColorRGB32> (theY, theX);
421       aPixel.r()  = Standard_Byte(theColor.r() * 255.0f);
422       aPixel.g()  = Standard_Byte(theColor.g() * 255.0f);
423       aPixel.b()  = Standard_Byte(theColor.b() * 255.0f);
424       aPixel.a_() = 255;
425       return;
426     }
427     case Image_Format_BGR32:
428     {
429       Image_ColorBGR32& aPixel = ChangeValue<Image_ColorBGR32> (theY, theX);
430       aPixel.r()  = Standard_Byte(theColor.r() * 255.0f);
431       aPixel.g()  = Standard_Byte(theColor.g() * 255.0f);
432       aPixel.b()  = Standard_Byte(theColor.b() * 255.0f);
433       aPixel.a_() = 255;
434       return;
435     }
436     case Image_Format_RGB:
437     {
438       Image_ColorRGB& aPixel = ChangeValue<Image_ColorRGB> (theY, theX);
439       aPixel.r() = Standard_Byte(theColor.r() * 255.0f);
440       aPixel.g() = Standard_Byte(theColor.g() * 255.0f);
441       aPixel.b() = Standard_Byte(theColor.b() * 255.0f);
442       return;
443     }
444     case Image_Format_BGR:
445     {
446       Image_ColorBGR& aPixel = ChangeValue<Image_ColorBGR> (theY, theX);
447       aPixel.r() = Standard_Byte(theColor.r() * 255.0f);
448       aPixel.g() = Standard_Byte(theColor.g() * 255.0f);
449       aPixel.b() = Standard_Byte(theColor.b() * 255.0f);
450       return;
451     }
452     case Image_Format_Gray:
453     {
454       ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(theColor.r() * 255.0f);
455       return;
456     }
457     case Image_Format_Alpha:
458     {
459       ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(theColor.a() * 255.0f);
460       return;
461     }
462     case Image_Format_UNKNOWN:
463     {
464       return;
465     }
466   }
467 }
468
469 // =======================================================================
470 // function : SwapRgbaBgra
471 // purpose  :
472 // =======================================================================
473 bool Image_PixMap::SwapRgbaBgra (Image_PixMap& theImage)
474 {
475   switch (theImage.Format())
476   {
477     case Image_Format_BGR32:
478     case Image_Format_RGB32:
479     case Image_Format_BGRA:
480     case Image_Format_RGBA:
481     {
482       const bool toResetAlpha = theImage.Format() == Image_Format_BGR32
483                              || theImage.Format() == Image_Format_RGB32;
484       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
485       {
486         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
487         {
488           Image_ColorRGBA& aPixel     = theImage.ChangeValue<Image_ColorRGBA> (aRow, aCol);
489           Image_ColorBGRA  aPixelCopy = theImage.Value      <Image_ColorBGRA> (aRow, aCol);
490           aPixel.r() = aPixelCopy.r();
491           aPixel.g() = aPixelCopy.g();
492           aPixel.b() = aPixelCopy.b();
493           if (toResetAlpha)
494           {
495             aPixel.a() = 255;
496           }
497         }
498       }
499       return true;
500     }
501     case Image_Format_BGR:
502     case Image_Format_RGB:
503     {
504       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
505       {
506         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
507         {
508           Image_ColorRGB& aPixel     = theImage.ChangeValue<Image_ColorRGB> (aRow, aCol);
509           Image_ColorBGR  aPixelCopy = theImage.Value      <Image_ColorBGR> (aRow, aCol);
510           aPixel.r() = aPixelCopy.r();
511           aPixel.g() = aPixelCopy.g();
512           aPixel.b() = aPixelCopy.b();
513         }
514       }
515       return true;
516     }
517     case Image_Format_BGRF:
518     case Image_Format_RGBF:
519     case Image_Format_BGRAF:
520     case Image_Format_RGBAF:
521     {
522       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
523       {
524         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
525         {
526           Image_ColorRGBF& aPixel     = theImage.ChangeValue<Image_ColorRGBF> (aRow, aCol);
527           Image_ColorBGRF  aPixelCopy = theImage.Value      <Image_ColorBGRF> (aRow, aCol);
528           aPixel.r() = aPixelCopy.r();
529           aPixel.g() = aPixelCopy.g();
530           aPixel.b() = aPixelCopy.b();
531         }
532       }
533       return true;
534     }
535     default: return false;
536   }
537 }