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 #include <NCollection_AlignedAllocator.hxx>
19 #include <Standard_ProgramError.hxx>
20 
21 #include <algorithm>
22 
23 namespace
24 {
25   //! Structure defining image pixel format description.
26   struct Image_FormatInfo
27   {
28     const char*  Name;         //!< string representation
29     int          Format;       //!< enumeration name
30     unsigned int NbComponents; //!< number of components
31     unsigned int PixelSize;    //!< bytes per pixel
32 
Image_FormatInfo__anon2c205f8c0111::Image_FormatInfo33     Image_FormatInfo (Image_Format theFormat, const char* theName, unsigned int theNbComponents, Standard_Size thePixelSize)
34     : Name (theName), Format (theFormat), NbComponents (theNbComponents), PixelSize ((unsigned int )thePixelSize) {}
35 
Image_FormatInfo__anon2c205f8c0111::Image_FormatInfo36     Image_FormatInfo (Image_CompressedFormat theFormat, const char* theName, unsigned int theNbComponents, Standard_Size thePixelSize)
37     : Name (theName), Format (theFormat), NbComponents (theNbComponents), PixelSize ((unsigned int )thePixelSize) {}
38   };
39 
40   #define ImageFormatInfo(theName, theNbComponents, thePixelSize) \
41     Image_FormatInfo(Image_Format_##theName, #theName, theNbComponents, thePixelSize)
42 
43   #define CompressedImageFormatInfo(theName, theNbComponents, thePixelSize) \
44     Image_FormatInfo(Image_CompressedFormat_##theName, #theName, theNbComponents, thePixelSize)
45 
46   //! Table of image pixel formats.
47   static const Image_FormatInfo Image_Table_ImageFormats[Image_CompressedFormat_NB] =
48   {
49     ImageFormatInfo(UNKNOWN, 0, 1),
50     ImageFormatInfo(Gray,    1, 1),
51     ImageFormatInfo(Alpha,   1, 1),
52     ImageFormatInfo(RGB,     3, 3),
53     ImageFormatInfo(BGR,     3, 3),
54     ImageFormatInfo(RGB32,   3, 4),
55     ImageFormatInfo(BGR32,   3, 4),
56     ImageFormatInfo(RGBA,    4, 4),
57     ImageFormatInfo(BGRA,    4, 4),
58     ImageFormatInfo(GrayF,   1, sizeof(float)),
59     ImageFormatInfo(AlphaF,  1, sizeof(float)),
60     ImageFormatInfo(RGF,     2, sizeof(float) * 2),
61     ImageFormatInfo(RGBF,    3, sizeof(float) * 3),
62     ImageFormatInfo(BGRF,    3, sizeof(float) * 3),
63     ImageFormatInfo(RGBAF,   4, sizeof(float) * 4),
64     ImageFormatInfo(BGRAF,   4, sizeof(float) * 4),
65     ImageFormatInfo(RGF_half,   2, sizeof(uint16_t) * 2),
66     ImageFormatInfo(RGBAF_half, 4, sizeof(uint16_t) * 4),
67     CompressedImageFormatInfo(RGB_S3TC_DXT1,  3, 1), // DXT1 uses circa half a byte per pixel (64 bits per 4x4 block)
68     CompressedImageFormatInfo(RGBA_S3TC_DXT1, 4, 1),
69     CompressedImageFormatInfo(RGBA_S3TC_DXT3, 4, 1), // DXT3/5 uses circa 1 byte per pixel (128 bits per 4x4 block)
70     CompressedImageFormatInfo(RGBA_S3TC_DXT5, 4, 1)
71   };
72 }
73 
IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap,Standard_Transient) const74 IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap,Standard_Transient)
75 
76 // =======================================================================
77 // function : DefaultAllocator
78 // purpose  :
79 // =======================================================================
80 const Handle(NCollection_BaseAllocator)& Image_PixMap::DefaultAllocator()
81 {
82   static const Handle(NCollection_BaseAllocator) THE_ALLOC = new NCollection_AlignedAllocator (16);
83   return THE_ALLOC;
84 }
85 
86 // =======================================================================
87 // function : ImageFormatToString
88 // purpose  :
89 // =======================================================================
ImageFormatToString(Image_Format theFormat)90 Standard_CString Image_PixMap::ImageFormatToString (Image_Format theFormat)
91 {
92   return Image_Table_ImageFormats[theFormat].Name;
93 }
94 
95 // =======================================================================
96 // function : ImageFormatToString
97 // purpose  :
98 // =======================================================================
ImageFormatToString(Image_CompressedFormat theFormat)99 Standard_CString Image_PixMap::ImageFormatToString (Image_CompressedFormat theFormat)
100 {
101   return Image_Table_ImageFormats[theFormat].Name;
102 }
103 
104 // =======================================================================
105 // function : Image_PixMap
106 // purpose  :
107 // =======================================================================
Image_PixMap()108 Image_PixMap::Image_PixMap()
109 : myImgFormat (Image_Format_Gray)
110 {
111   //
112 }
113 
114 // =======================================================================
115 // function : ~Image_PixMap
116 // purpose  :
117 // =======================================================================
~Image_PixMap()118 Image_PixMap::~Image_PixMap()
119 {
120   Clear();
121 }
122 
123 // =======================================================================
124 // function : SizePixelBytes
125 // purpose  :
126 // =======================================================================
SizePixelBytes(const Image_Format thePixelFormat)127 Standard_Size Image_PixMap::SizePixelBytes (const Image_Format thePixelFormat)
128 {
129   return Image_Table_ImageFormats[thePixelFormat].PixelSize;
130 }
131 
132 // =======================================================================
133 // function : SetFormat
134 // purpose  :
135 // =======================================================================
SetFormat(Image_Format thePixelFormat)136 void Image_PixMap::SetFormat (Image_Format thePixelFormat)
137 {
138   if (myImgFormat == thePixelFormat)
139   {
140     return;
141   }
142 
143   if (!IsEmpty()
144     && SizePixelBytes (myImgFormat) != SizePixelBytes (thePixelFormat))
145   {
146     throw Standard_ProgramError("Image_PixMap::SetFormat() - incompatible pixel format");
147     return;
148   }
149 
150   myImgFormat = thePixelFormat;
151 }
152 
153 // =======================================================================
154 // function : InitWrapper
155 // purpose  :
156 // =======================================================================
InitWrapper(Image_Format thePixelFormat,Standard_Byte * theDataPtr,const Standard_Size theSizeX,const Standard_Size theSizeY,const Standard_Size theSizeRowBytes)157 bool Image_PixMap::InitWrapper (Image_Format        thePixelFormat,
158                                 Standard_Byte*      theDataPtr,
159                                 const Standard_Size theSizeX,
160                                 const Standard_Size theSizeY,
161                                 const Standard_Size theSizeRowBytes)
162 {
163   Clear();
164   myImgFormat = thePixelFormat;
165   if ((theSizeX == 0) || (theSizeY == 0) || (theDataPtr == NULL))
166   {
167     return false;
168   }
169 
170   Handle(NCollection_BaseAllocator) anEmptyAlloc;
171   myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (thePixelFormat),
172                theSizeX, theSizeY, theSizeRowBytes, theDataPtr);
173   return true;
174 }
175 
176 // =======================================================================
177 // function : InitTrash
178 // purpose  :
179 // =======================================================================
InitTrash(Image_Format thePixelFormat,const Standard_Size theSizeX,const Standard_Size theSizeY,const Standard_Size theSizeRowBytes)180 bool Image_PixMap::InitTrash (Image_Format        thePixelFormat,
181                               const Standard_Size theSizeX,
182                               const Standard_Size theSizeY,
183                               const Standard_Size theSizeRowBytes)
184 {
185   Clear();
186   myImgFormat = thePixelFormat;
187   if ((theSizeX == 0) || (theSizeY == 0))
188   {
189     return false;
190   }
191 
192   // use argument only if it greater
193   const Standard_Size aSizeRowBytes = std::max (theSizeRowBytes, theSizeX * SizePixelBytes (thePixelFormat));
194   myData.Init (DefaultAllocator(), Image_PixMap::SizePixelBytes (thePixelFormat),
195                theSizeX, theSizeY, aSizeRowBytes, NULL);
196   return !myData.IsEmpty();
197 }
198 
199 // =======================================================================
200 // function : InitZero
201 // purpose  :
202 // =======================================================================
InitZero(Image_Format thePixelFormat,const Standard_Size theSizeX,const Standard_Size theSizeY,const Standard_Size theSizeRowBytes,const Standard_Byte theValue)203 bool Image_PixMap::InitZero (Image_Format        thePixelFormat,
204                              const Standard_Size theSizeX,
205                              const Standard_Size theSizeY,
206                              const Standard_Size theSizeRowBytes,
207                              const Standard_Byte theValue)
208 {
209   if (!InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes))
210   {
211     return false;
212   }
213   memset (myData.ChangeData(), (int )theValue, SizeBytes());
214   return true;
215 }
216 
217 // =======================================================================
218 // function : InitCopy
219 // purpose  :
220 // =======================================================================
InitCopy(const Image_PixMap & theCopy)221 bool Image_PixMap::InitCopy (const Image_PixMap& theCopy)
222 {
223   if (&theCopy == this)
224   {
225     // self-copying disallowed
226     return false;
227   }
228   if (InitTrash (theCopy.myImgFormat, theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
229   {
230     memcpy (myData.ChangeData(), theCopy.myData.Data(), theCopy.SizeBytes());
231     return true;
232   }
233   return false;
234 }
235 
236 // =======================================================================
237 // function : Clear
238 // purpose  :
239 // =======================================================================
Clear()240 void Image_PixMap::Clear()
241 {
242   Handle(NCollection_BaseAllocator) anEmptyAlloc;
243   myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (myImgFormat),
244                0, 0, 0, NULL);
245 }
246 
247 // =======================================================================
248 // function : PixelColor
249 // purpose  :
250 // =======================================================================
PixelColor(const Standard_Integer theX,const Standard_Integer theY,const Standard_Boolean theToLinearize) const251 Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
252                                              const Standard_Integer theY,
253                                              const Standard_Boolean theToLinearize) const
254 {
255   if (IsEmpty()
256    || theX < 0 || (Standard_Size )theX >= SizeX()
257    || theY < 0 || (Standard_Size )theY >= SizeY())
258   {
259     return Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 0.0f); // transparent
260   }
261 
262   switch (myImgFormat)
263   {
264     case Image_Format_GrayF:
265     {
266       const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
267       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel, aPixel, aPixel, 1.0f)); // opaque
268     }
269     case Image_Format_AlphaF:
270     {
271       const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
272       return Quantity_ColorRGBA (NCollection_Vec4<float> (1.0f, 1.0f, 1.0f, aPixel));
273     }
274     case Image_Format_RGF:
275     {
276       const Image_ColorRGF& aPixel = Value<Image_ColorRGF> (theY, theX);
277       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), 0.0f, 1.0f));
278     }
279     case Image_Format_RGBAF:
280     {
281       const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX);
282       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), aPixel.a()));
283     }
284     case Image_Format_BGRAF:
285     {
286       const Image_ColorBGRAF& aPixel = Value<Image_ColorBGRAF> (theY, theX);
287       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), aPixel.a()));
288     }
289     case Image_Format_RGBF:
290     {
291       const Image_ColorRGBF& aPixel = Value<Image_ColorRGBF> (theY, theX);
292       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), 1.0f)); // opaque
293     }
294     case Image_Format_BGRF:
295     {
296       const Image_ColorBGRF& aPixel = Value<Image_ColorBGRF> (theY, theX);
297       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), 1.0f)); // opaque
298     }
299     case Image_Format_RGF_half:
300     {
301       const NCollection_Vec2<uint16_t>& aPixel = Value<NCollection_Vec2<uint16_t>> (theY, theX);
302       return Quantity_ColorRGBA (NCollection_Vec4<float> (ConvertFromHalfFloat (aPixel.x()), ConvertFromHalfFloat (aPixel.y()), 0.0f, 1.0f));
303     }
304     case Image_Format_RGBAF_half:
305     {
306       const NCollection_Vec4<uint16_t>& aPixel = Value<NCollection_Vec4<uint16_t>> (theY, theX);
307       return Quantity_ColorRGBA (NCollection_Vec4<float> (ConvertFromHalfFloat (aPixel.r()), ConvertFromHalfFloat (aPixel.g()),
308                                                           ConvertFromHalfFloat (aPixel.b()), ConvertFromHalfFloat (aPixel.a())));
309     }
310     case Image_Format_RGBA:
311     {
312       const Image_ColorRGBA& aPixel = Value<Image_ColorRGBA> (theY, theX);
313       return theToLinearize
314            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
315                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
316                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f),
317                                  float(aPixel.a()) / 255.0f)
318            : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, float(aPixel.a()) / 255.0f);
319     }
320     case Image_Format_BGRA:
321     {
322       const Image_ColorBGRA& aPixel = Value<Image_ColorBGRA> (theY, theX);
323       return theToLinearize
324            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
325                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
326                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f),
327                                  float(aPixel.a()) / 255.0f)
328            : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, float(aPixel.a()) / 255.0f);
329     }
330     case Image_Format_RGB32:
331     {
332       const Image_ColorRGB32& aPixel = Value<Image_ColorRGB32> (theY, theX);
333       return theToLinearize
334            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
335                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
336                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f), 1.0f)
337            : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f);
338     }
339     case Image_Format_BGR32:
340     {
341       const Image_ColorBGR32& aPixel = Value<Image_ColorBGR32> (theY, theX);
342       return theToLinearize
343            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
344                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
345                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f), 1.0f)
346            : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f);
347     }
348     case Image_Format_RGB:
349     {
350       const Image_ColorRGB& aPixel = Value<Image_ColorRGB> (theY, theX);
351       return theToLinearize
352            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
353                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
354                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f), 1.0f)
355            : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f);
356     }
357     case Image_Format_BGR:
358     {
359       const Image_ColorBGR& aPixel = Value<Image_ColorBGR> (theY, theX);
360       return theToLinearize
361            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
362                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
363                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f), 1.0f)
364            : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f);
365     }
366     case Image_Format_Gray:
367     {
368       const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
369       return Quantity_ColorRGBA (float(aPixel) / 255.0f, float(aPixel) / 255.0f, float(aPixel) / 255.0f, 1.0f); // opaque
370     }
371     case Image_Format_Alpha:
372     {
373       const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
374       return Quantity_ColorRGBA (1.0f, 1.0f, 1.0f, float(aPixel) / 255.0f);
375     }
376     case Image_Format_UNKNOWN:
377     {
378       break;
379     }
380   }
381 
382   // unsupported image type
383   return Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 0.0f); // transparent
384 }
385 
386 // =======================================================================
387 // function : SetPixelColor
388 // purpose  :
389 // =======================================================================
SetPixelColor(const Standard_Integer theX,const Standard_Integer theY,const Quantity_ColorRGBA & theColor,const Standard_Boolean theToDeLinearize)390 void Image_PixMap::SetPixelColor (const Standard_Integer theX,
391                                   const Standard_Integer theY,
392                                   const Quantity_ColorRGBA& theColor,
393                                   const Standard_Boolean theToDeLinearize)
394 {
395   if (IsEmpty()
396    || theX < 0 || Standard_Size(theX) >= SizeX()
397    || theY < 0 || Standard_Size(theY) >= SizeY())
398   {
399     return;
400   }
401 
402   const NCollection_Vec4<float>& aColor = theColor;
403   switch (myImgFormat)
404   {
405     case Image_Format_GrayF:
406     {
407       ChangeValue<Standard_ShortReal> (theY, theX) = aColor.r();
408       return;
409     }
410     case Image_Format_AlphaF:
411     {
412       ChangeValue<Standard_ShortReal> (theY, theX) = aColor.a();
413       return;
414     }
415     case Image_Format_RGF:
416     {
417       Image_ColorRGF& aPixel = ChangeValue<Image_ColorRGF> (theY, theX);
418       aPixel.r() = aColor.r();
419       aPixel.g() = aColor.g();
420       return;
421     }
422     case Image_Format_RGBAF:
423     {
424       Image_ColorRGBAF& aPixel = ChangeValue<Image_ColorRGBAF> (theY, theX);
425       aPixel.r() = aColor.r();
426       aPixel.g() = aColor.g();
427       aPixel.b() = aColor.b();
428       aPixel.a() = aColor.a();
429       return;
430     }
431     case Image_Format_BGRAF:
432     {
433       Image_ColorBGRAF& aPixel = ChangeValue<Image_ColorBGRAF> (theY, theX);
434       aPixel.r() = aColor.r();
435       aPixel.g() = aColor.g();
436       aPixel.b() = aColor.b();
437       aPixel.a() = aColor.a();
438       return;
439     }
440     case Image_Format_RGBF:
441     {
442       Image_ColorRGBF& aPixel = ChangeValue<Image_ColorRGBF> (theY, theX);
443       aPixel.r() = aColor.r();
444       aPixel.g() = aColor.g();
445       aPixel.b() = aColor.b();
446       return;
447     }
448     case Image_Format_BGRF:
449     {
450       Image_ColorBGRF& aPixel = ChangeValue<Image_ColorBGRF> (theY, theX);
451       aPixel.r() = aColor.r();
452       aPixel.g() = aColor.g();
453       aPixel.b() = aColor.b();
454       return;
455     }
456     case Image_Format_RGF_half:
457     {
458       NCollection_Vec2<uint16_t>& aPixel = ChangeValue<NCollection_Vec2<uint16_t>> (theY, theX);
459       aPixel.x() = ConvertToHalfFloat (aColor.r());
460       aPixel.y() = ConvertToHalfFloat (aColor.g());
461       return;
462     }
463     case Image_Format_RGBAF_half:
464     {
465       NCollection_Vec4<uint16_t>& aPixel = ChangeValue<NCollection_Vec4<uint16_t>> (theY, theX);
466       aPixel.r() = ConvertToHalfFloat (aColor.r());
467       aPixel.g() = ConvertToHalfFloat (aColor.g());
468       aPixel.b() = ConvertToHalfFloat (aColor.b());
469       aPixel.a() = ConvertToHalfFloat (aColor.a());
470       return;
471     }
472     case Image_Format_RGBA:
473     {
474       Image_ColorRGBA& aPixel = ChangeValue<Image_ColorRGBA> (theY, theX);
475       if (theToDeLinearize)
476       {
477         aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
478         aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
479         aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
480       }
481       else
482       {
483         aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
484         aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
485         aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
486       }
487       aPixel.a() = Standard_Byte(aColor.a() * 255.0f);
488       return;
489     }
490     case Image_Format_BGRA:
491     {
492       Image_ColorBGRA& aPixel = ChangeValue<Image_ColorBGRA> (theY, theX);
493       if (theToDeLinearize)
494       {
495         aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
496         aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
497         aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
498       }
499       else
500       {
501         aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
502         aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
503         aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
504       }
505       aPixel.a() = Standard_Byte(aColor.a() * 255.0f);
506       return;
507     }
508     case Image_Format_RGB32:
509     {
510       Image_ColorRGB32& aPixel = ChangeValue<Image_ColorRGB32> (theY, theX);
511       if (theToDeLinearize)
512       {
513         aPixel.r()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
514         aPixel.g()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
515         aPixel.b()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
516       }
517       else
518       {
519         aPixel.r()  = Standard_Byte(aColor.r() * 255.0f);
520         aPixel.g()  = Standard_Byte(aColor.g() * 255.0f);
521         aPixel.b()  = Standard_Byte(aColor.b() * 255.0f);
522       }
523       aPixel.a_() = 255;
524       return;
525     }
526     case Image_Format_BGR32:
527     {
528       Image_ColorBGR32& aPixel = ChangeValue<Image_ColorBGR32> (theY, theX);
529       if (theToDeLinearize)
530       {
531         aPixel.r()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
532         aPixel.g()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
533         aPixel.b()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
534       }
535       else
536       {
537         aPixel.r()  = Standard_Byte(aColor.r() * 255.0f);
538         aPixel.g()  = Standard_Byte(aColor.g() * 255.0f);
539         aPixel.b()  = Standard_Byte(aColor.b() * 255.0f);
540       }
541       aPixel.a_() = 255;
542       return;
543     }
544     case Image_Format_RGB:
545     {
546       Image_ColorRGB& aPixel = ChangeValue<Image_ColorRGB> (theY, theX);
547       if (theToDeLinearize)
548       {
549         aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
550         aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
551         aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
552       }
553       else
554       {
555         aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
556         aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
557         aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
558       }
559       return;
560     }
561     case Image_Format_BGR:
562     {
563       Image_ColorBGR& aPixel = ChangeValue<Image_ColorBGR> (theY, theX);
564       if (theToDeLinearize)
565       {
566         aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
567         aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
568         aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
569       }
570       else
571       {
572         aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
573         aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
574         aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
575       }
576       return;
577     }
578     case Image_Format_Gray:
579     {
580       ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(aColor.r() * 255.0f);
581       return;
582     }
583     case Image_Format_Alpha:
584     {
585       ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(aColor.a() * 255.0f);
586       return;
587     }
588     case Image_Format_UNKNOWN:
589     {
590       return;
591     }
592   }
593 }
594 
595 // =======================================================================
596 // function : SwapRgbaBgra
597 // purpose  :
598 // =======================================================================
SwapRgbaBgra(Image_PixMap & theImage)599 bool Image_PixMap::SwapRgbaBgra (Image_PixMap& theImage)
600 {
601   switch (theImage.Format())
602   {
603     case Image_Format_BGR32:
604     case Image_Format_RGB32:
605     case Image_Format_BGRA:
606     case Image_Format_RGBA:
607     {
608       const bool toResetAlpha = theImage.Format() == Image_Format_BGR32
609                              || theImage.Format() == Image_Format_RGB32;
610       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
611       {
612         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
613         {
614           Image_ColorRGBA& aPixel     = theImage.ChangeValue<Image_ColorRGBA> (aRow, aCol);
615           Image_ColorBGRA  aPixelCopy = theImage.Value      <Image_ColorBGRA> (aRow, aCol);
616           aPixel.r() = aPixelCopy.r();
617           aPixel.g() = aPixelCopy.g();
618           aPixel.b() = aPixelCopy.b();
619           if (toResetAlpha)
620           {
621             aPixel.a() = 255;
622           }
623         }
624       }
625       return true;
626     }
627     case Image_Format_BGR:
628     case Image_Format_RGB:
629     {
630       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
631       {
632         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
633         {
634           Image_ColorRGB& aPixel     = theImage.ChangeValue<Image_ColorRGB> (aRow, aCol);
635           Image_ColorBGR  aPixelCopy = theImage.Value      <Image_ColorBGR> (aRow, aCol);
636           aPixel.r() = aPixelCopy.r();
637           aPixel.g() = aPixelCopy.g();
638           aPixel.b() = aPixelCopy.b();
639         }
640       }
641       return true;
642     }
643     case Image_Format_BGRF:
644     case Image_Format_RGBF:
645     case Image_Format_BGRAF:
646     case Image_Format_RGBAF:
647     {
648       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
649       {
650         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
651         {
652           Image_ColorRGBF& aPixel     = theImage.ChangeValue<Image_ColorRGBF> (aRow, aCol);
653           Image_ColorBGRF  aPixelCopy = theImage.Value      <Image_ColorBGRF> (aRow, aCol);
654           aPixel.r() = aPixelCopy.r();
655           aPixel.g() = aPixelCopy.g();
656           aPixel.b() = aPixelCopy.b();
657         }
658       }
659       return true;
660     }
661     default: return false;
662   }
663 }
664 
665 // =======================================================================
666 // function : ToBlackWhite
667 // purpose  :
668 // =======================================================================
ToBlackWhite(Image_PixMap & theImage)669 void Image_PixMap::ToBlackWhite (Image_PixMap& theImage)
670 {
671   switch (theImage.Format())
672   {
673     case Image_Format_Gray:
674     case Image_Format_Alpha:
675     {
676       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
677       {
678         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
679         {
680           unsigned char& aPixel = theImage.ChangeValue<unsigned char> (aRow, aCol);
681           if (aPixel != 0)
682           {
683             aPixel = 255;
684           }
685         }
686       }
687       break;
688     }
689     case Image_Format_RGB:
690     case Image_Format_BGR:
691     case Image_Format_RGB32:
692     case Image_Format_BGR32:
693     case Image_Format_RGBA:
694     case Image_Format_BGRA:
695     {
696       const NCollection_Vec3<unsigned char> aWhite24 (255, 255, 255);
697       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
698       {
699         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
700         {
701           NCollection_Vec3<unsigned char>& aPixel = theImage.ChangeValue< NCollection_Vec3<unsigned char> > (aRow, aCol);
702           if (aPixel[0] != 0
703            || aPixel[1] != 0
704            || aPixel[2] != 0)
705           {
706             aPixel = aWhite24;
707           }
708         }
709       }
710       break;
711     }
712     default:
713     {
714       const Quantity_ColorRGBA aWhiteRgba (1.0f, 1.0f, 1.0f, 1.0f);
715       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
716       {
717         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
718         {
719           const Quantity_ColorRGBA       aPixelRgba = theImage.PixelColor (Standard_Integer(aCol), Standard_Integer(aRow));
720           const NCollection_Vec4<float>& aPixel     = aPixelRgba;
721           if (aPixel[0] != 0.0f
722            || aPixel[1] != 0.0f
723            || aPixel[2] != 0.0f)
724           {
725             theImage.SetPixelColor (int(aCol), int(aRow), aWhiteRgba);
726           }
727         }
728       }
729       break;
730     }
731   }
732 }
733 
734 // =======================================================================
735 // function : InitCopy
736 // purpose  :
737 // =======================================================================
FlipY(Image_PixMap & theImage)738 bool Image_PixMap::FlipY (Image_PixMap& theImage)
739 {
740   if (theImage.IsEmpty()
741    || theImage.SizeX() == 0
742    || theImage.SizeY() == 0)
743   {
744     return false;
745   }
746 
747   NCollection_Buffer aTmp (NCollection_BaseAllocator::CommonBaseAllocator());
748   const size_t aRowSize = theImage.SizeRowBytes();
749   if (!aTmp.Allocate (aRowSize))
750   {
751     return false;
752   }
753 
754   // for odd height middle row should be left as is
755   Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
756   for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
757   {
758     Standard_Byte* aTop = theImage.ChangeRow (aRowT);
759     Standard_Byte* aBot = theImage.ChangeRow (aRowB);
760     memcpy (aTmp.ChangeData(), aTop, aRowSize);
761     memcpy (aTop, aBot, aRowSize);
762     memcpy (aBot, aTmp.Data(), aRowSize);
763   }
764   return true;
765 }
766