0030700: Visualization, TKOpenGl - support PBR Metallic-Roughness shading model
[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_RGF:
51       return sizeof(float) * 2;
52     case Image_Format_RGBAF:
53     case Image_Format_BGRAF:
54       return sizeof(float) * 4;
55     case Image_Format_RGBF:
56     case Image_Format_BGRF:
57       return sizeof(float) * 3;
58     case Image_Format_RGBA:
59     case Image_Format_BGRA:
60       return 4;
61     case Image_Format_RGB32:
62     case Image_Format_BGR32:
63       return 4;
64     case Image_Format_RGB:
65     case Image_Format_BGR:
66       return 3;
67     case Image_Format_Gray:
68     case Image_Format_Alpha:
69       return 1;
70     case Image_Format_UNKNOWN:
71       return 1;
72   }
73   return 1;
74 }
75
76 // =======================================================================
77 // function : SetFormat
78 // purpose  :
79 // =======================================================================
80 void Image_PixMap::SetFormat (Image_Format thePixelFormat)
81 {
82   if (myImgFormat == thePixelFormat)
83   {
84     return;
85   }
86
87   if (!IsEmpty()
88     && SizePixelBytes (myImgFormat) != SizePixelBytes (thePixelFormat))
89   {
90     throw Standard_ProgramError("Image_PixMap::SetFormat() - incompatible pixel format");
91     return;
92   }
93
94   myImgFormat = thePixelFormat;
95 }
96
97 // =======================================================================
98 // function : InitWrapper
99 // purpose  :
100 // =======================================================================
101 bool Image_PixMap::InitWrapper (Image_Format        thePixelFormat,
102                                 Standard_Byte*      theDataPtr,
103                                 const Standard_Size theSizeX,
104                                 const Standard_Size theSizeY,
105                                 const Standard_Size theSizeRowBytes)
106 {
107   Clear();
108   myImgFormat = thePixelFormat;
109   if ((theSizeX == 0) || (theSizeY == 0) || (theDataPtr == NULL))
110   {
111     return false;
112   }
113
114   Handle(NCollection_BaseAllocator) anEmptyAlloc;
115   myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (thePixelFormat),
116                theSizeX, theSizeY, theSizeRowBytes, theDataPtr);
117   return true;
118 }
119
120 // =======================================================================
121 // function : InitTrash
122 // purpose  :
123 // =======================================================================
124 bool Image_PixMap::InitTrash (Image_Format        thePixelFormat,
125                               const Standard_Size theSizeX,
126                               const Standard_Size theSizeY,
127                               const Standard_Size theSizeRowBytes)
128 {
129   Clear();
130   myImgFormat = thePixelFormat;
131   if ((theSizeX == 0) || (theSizeY == 0))
132   {
133     return false;
134   }
135
136   // use argument only if it greater
137   const Standard_Size aSizeRowBytes = std::max (theSizeRowBytes, theSizeX * SizePixelBytes (thePixelFormat));
138   Handle(NCollection_BaseAllocator) anAlloc = new NCollection_AlignedAllocator (16);
139   myData.Init (anAlloc, Image_PixMap::SizePixelBytes (thePixelFormat),
140                theSizeX, theSizeY, aSizeRowBytes, NULL);
141   return !myData.IsEmpty();
142 }
143
144 // =======================================================================
145 // function : InitZero
146 // purpose  :
147 // =======================================================================
148 bool Image_PixMap::InitZero (Image_Format        thePixelFormat,
149                              const Standard_Size theSizeX,
150                              const Standard_Size theSizeY,
151                              const Standard_Size theSizeRowBytes,
152                              const Standard_Byte theValue)
153 {
154   if (!InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes))
155   {
156     return false;
157   }
158   memset (myData.ChangeData(), (int )theValue, SizeBytes());
159   return true;
160 }
161
162 // =======================================================================
163 // function : InitCopy
164 // purpose  :
165 // =======================================================================
166 bool Image_PixMap::InitCopy (const Image_PixMap& theCopy)
167 {
168   if (&theCopy == this)
169   {
170     // self-copying disallowed
171     return false;
172   }
173   if (InitTrash (theCopy.myImgFormat, theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
174   {
175     memcpy (myData.ChangeData(), theCopy.myData.Data(), theCopy.SizeBytes());
176     return true;
177   }
178   return false;
179 }
180
181 // =======================================================================
182 // function : Clear
183 // purpose  :
184 // =======================================================================
185 void Image_PixMap::Clear()
186 {
187   Handle(NCollection_BaseAllocator) anEmptyAlloc;
188   myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (myImgFormat),
189                0, 0, 0, NULL);
190 }
191
192 // =======================================================================
193 // function : PixelColor
194 // purpose  :
195 // =======================================================================
196 Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
197                                              const Standard_Integer theY,
198                                              const Standard_Boolean theToLinearize) const
199 {
200   if (IsEmpty()
201    || theX < 0 || (Standard_Size )theX >= SizeX()
202    || theY < 0 || (Standard_Size )theY >= SizeY())
203   {
204     return Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 0.0f); // transparent
205   }
206
207   switch (myImgFormat)
208   {
209     case Image_Format_GrayF:
210     {
211       const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
212       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel, aPixel, aPixel, 1.0f)); // opaque
213     }
214     case Image_Format_AlphaF:
215     {
216       const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
217       return Quantity_ColorRGBA (NCollection_Vec4<float> (1.0f, 1.0f, 1.0f, aPixel));
218     }
219     case Image_Format_RGF:
220     {
221       const Image_ColorRGF& aPixel = Value<Image_ColorRGF> (theY, theX);
222       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), 0.0f, 1.0f));
223     }
224     case Image_Format_RGBAF:
225     {
226       const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX);
227       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), aPixel.a()));
228     }
229     case Image_Format_BGRAF:
230     {    
231       const Image_ColorBGRAF& aPixel = Value<Image_ColorBGRAF> (theY, theX);
232       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), aPixel.a()));
233     }
234     case Image_Format_RGBF:
235     {
236       const Image_ColorRGBF& aPixel = Value<Image_ColorRGBF> (theY, theX);
237       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), 1.0f)); // opaque
238     }
239     case Image_Format_BGRF:
240     {
241       const Image_ColorBGRF& aPixel = Value<Image_ColorBGRF> (theY, theX);
242       return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), 1.0f)); // opaque
243     }
244     case Image_Format_RGBA:
245     {
246       const Image_ColorRGBA& aPixel = Value<Image_ColorRGBA> (theY, theX);
247       return theToLinearize
248            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
249                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
250                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f),
251                                  float(aPixel.a()) / 255.0f)
252            : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, float(aPixel.a()) / 255.0f);
253     }
254     case Image_Format_BGRA:
255     {
256       const Image_ColorBGRA& aPixel = Value<Image_ColorBGRA> (theY, theX);
257       return theToLinearize
258            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
259                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
260                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f),
261                                  float(aPixel.a()) / 255.0f)
262            : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, float(aPixel.a()) / 255.0f);
263     }
264     case Image_Format_RGB32:
265     {
266       const Image_ColorRGB32& aPixel = Value<Image_ColorRGB32> (theY, theX);
267       return theToLinearize
268            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
269                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
270                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f), 1.0f)
271            : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f);
272     }
273     case Image_Format_BGR32:
274     {
275       const Image_ColorBGR32& aPixel = Value<Image_ColorBGR32> (theY, theX);
276       return theToLinearize
277            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
278                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
279                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f), 1.0f)
280            : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f);
281     }
282     case Image_Format_RGB:
283     {
284       const Image_ColorRGB& aPixel = Value<Image_ColorRGB> (theY, theX);
285       return theToLinearize
286            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
287                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
288                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f), 1.0f)
289            : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f);
290     }
291     case Image_Format_BGR:
292     {
293       const Image_ColorBGR& aPixel = Value<Image_ColorBGR> (theY, theX);
294       return theToLinearize
295            ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
296                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
297                                  Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f), 1.0f)
298            : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f);
299     }
300     case Image_Format_Gray:
301     {
302       const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
303       return Quantity_ColorRGBA (float(aPixel) / 255.0f, float(aPixel) / 255.0f, float(aPixel) / 255.0f, 1.0f); // opaque
304     }
305     case Image_Format_Alpha:
306     {
307       const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX);
308       return Quantity_ColorRGBA (1.0f, 1.0f, 1.0f, float(aPixel) / 255.0f);
309     }
310     case Image_Format_UNKNOWN:
311     {
312       break;
313     }
314   }
315
316   // unsupported image type
317   return Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 0.0f); // transparent
318 }
319
320 // =======================================================================
321 // function : SetPixelColor
322 // purpose  :
323 // =======================================================================
324 void Image_PixMap::SetPixelColor (const Standard_Integer theX,
325                                   const Standard_Integer theY,
326                                   const Quantity_ColorRGBA& theColor,
327                                   const Standard_Boolean theToDeLinearize)
328 {
329   if (IsEmpty()
330    || theX < 0 || Standard_Size(theX) >= SizeX()
331    || theY < 0 || Standard_Size(theY) >= SizeY())
332   {
333     return;
334   }
335
336   const NCollection_Vec4<float>& aColor = theColor;
337   switch (myImgFormat)
338   {
339     case Image_Format_GrayF:
340     {
341       ChangeValue<Standard_ShortReal> (theY, theX) = aColor.r();
342       return;
343     }
344     case Image_Format_AlphaF:
345     {
346       ChangeValue<Standard_ShortReal> (theY, theX) = aColor.a();
347       return;
348     }
349     case Image_Format_RGF:
350     {
351       Image_ColorRGF& aPixel = ChangeValue<Image_ColorRGF> (theY, theX);
352       aPixel.r() = aColor.r();
353       aPixel.g() = aColor.g();
354       return;
355     }
356     case Image_Format_RGBAF:
357     {
358       Image_ColorRGBAF& aPixel = ChangeValue<Image_ColorRGBAF> (theY, theX);
359       aPixel.r() = aColor.r();
360       aPixel.g() = aColor.g();
361       aPixel.b() = aColor.b();
362       aPixel.a() = aColor.a();
363       return;
364     }
365     case Image_Format_BGRAF:
366     {
367       Image_ColorBGRAF& aPixel = ChangeValue<Image_ColorBGRAF> (theY, theX);
368       aPixel.r() = aColor.r();
369       aPixel.g() = aColor.g();
370       aPixel.b() = aColor.b();
371       aPixel.a() = aColor.a();
372       return;
373     }
374     case Image_Format_RGBF:
375     {
376       Image_ColorRGBF& aPixel = ChangeValue<Image_ColorRGBF> (theY, theX);
377       aPixel.r() = aColor.r();
378       aPixel.g() = aColor.g();
379       aPixel.b() = aColor.b();
380       return;
381     }
382     case Image_Format_BGRF:
383     {
384       Image_ColorBGRF& aPixel = ChangeValue<Image_ColorBGRF> (theY, theX);
385       aPixel.r() = aColor.r();
386       aPixel.g() = aColor.g();
387       aPixel.b() = aColor.b();
388       return;
389     }
390     case Image_Format_RGBA:
391     {
392       Image_ColorRGBA& aPixel = ChangeValue<Image_ColorRGBA> (theY, theX);
393       if (theToDeLinearize)
394       {
395         aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
396         aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
397         aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
398       }
399       else
400       {
401         aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
402         aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
403         aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
404       }
405       aPixel.a() = Standard_Byte(aColor.a() * 255.0f);
406       return;
407     }
408     case Image_Format_BGRA:
409     {
410       Image_ColorBGRA& aPixel = ChangeValue<Image_ColorBGRA> (theY, theX);
411       if (theToDeLinearize)
412       {
413         aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
414         aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
415         aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
416       }
417       else
418       {
419         aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
420         aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
421         aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
422       }
423       aPixel.a() = Standard_Byte(aColor.a() * 255.0f);
424       return;
425     }
426     case Image_Format_RGB32:
427     {
428       Image_ColorRGB32& aPixel = ChangeValue<Image_ColorRGB32> (theY, theX);
429       if (theToDeLinearize)
430       {
431         aPixel.r()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
432         aPixel.g()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
433         aPixel.b()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
434       }
435       else
436       {
437         aPixel.r()  = Standard_Byte(aColor.r() * 255.0f);
438         aPixel.g()  = Standard_Byte(aColor.g() * 255.0f);
439         aPixel.b()  = Standard_Byte(aColor.b() * 255.0f);
440       }
441       aPixel.a_() = 255;
442       return;
443     }
444     case Image_Format_BGR32:
445     {
446       Image_ColorBGR32& aPixel = ChangeValue<Image_ColorBGR32> (theY, theX);
447       if (theToDeLinearize)
448       {
449         aPixel.r()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
450         aPixel.g()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
451         aPixel.b()  = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
452       }
453       else
454       {
455         aPixel.r()  = Standard_Byte(aColor.r() * 255.0f);
456         aPixel.g()  = Standard_Byte(aColor.g() * 255.0f);
457         aPixel.b()  = Standard_Byte(aColor.b() * 255.0f);
458       }
459       aPixel.a_() = 255;
460       return;
461     }
462     case Image_Format_RGB:
463     {
464       Image_ColorRGB& aPixel = ChangeValue<Image_ColorRGB> (theY, theX);
465       if (theToDeLinearize)
466       {
467         aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
468         aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
469         aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
470       }
471       else
472       {
473         aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
474         aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
475         aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
476       }
477       return;
478     }
479     case Image_Format_BGR:
480     {
481       Image_ColorBGR& aPixel = ChangeValue<Image_ColorBGR> (theY, theX);
482       if (theToDeLinearize)
483       {
484         aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
485         aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
486         aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
487       }
488       else
489       {
490         aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
491         aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
492         aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
493       }
494       return;
495     }
496     case Image_Format_Gray:
497     {
498       ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(aColor.r() * 255.0f);
499       return;
500     }
501     case Image_Format_Alpha:
502     {
503       ChangeValue<Standard_Byte> (theY, theX) = Standard_Byte(aColor.a() * 255.0f);
504       return;
505     }
506     case Image_Format_UNKNOWN:
507     {
508       return;
509     }
510   }
511 }
512
513 // =======================================================================
514 // function : SwapRgbaBgra
515 // purpose  :
516 // =======================================================================
517 bool Image_PixMap::SwapRgbaBgra (Image_PixMap& theImage)
518 {
519   switch (theImage.Format())
520   {
521     case Image_Format_BGR32:
522     case Image_Format_RGB32:
523     case Image_Format_BGRA:
524     case Image_Format_RGBA:
525     {
526       const bool toResetAlpha = theImage.Format() == Image_Format_BGR32
527                              || theImage.Format() == Image_Format_RGB32;
528       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
529       {
530         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
531         {
532           Image_ColorRGBA& aPixel     = theImage.ChangeValue<Image_ColorRGBA> (aRow, aCol);
533           Image_ColorBGRA  aPixelCopy = theImage.Value      <Image_ColorBGRA> (aRow, aCol);
534           aPixel.r() = aPixelCopy.r();
535           aPixel.g() = aPixelCopy.g();
536           aPixel.b() = aPixelCopy.b();
537           if (toResetAlpha)
538           {
539             aPixel.a() = 255;
540           }
541         }
542       }
543       return true;
544     }
545     case Image_Format_BGR:
546     case Image_Format_RGB:
547     {
548       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
549       {
550         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
551         {
552           Image_ColorRGB& aPixel     = theImage.ChangeValue<Image_ColorRGB> (aRow, aCol);
553           Image_ColorBGR  aPixelCopy = theImage.Value      <Image_ColorBGR> (aRow, aCol);
554           aPixel.r() = aPixelCopy.r();
555           aPixel.g() = aPixelCopy.g();
556           aPixel.b() = aPixelCopy.b();
557         }
558       }
559       return true;
560     }
561     case Image_Format_BGRF:
562     case Image_Format_RGBF:
563     case Image_Format_BGRAF:
564     case Image_Format_RGBAF:
565     {
566       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
567       {
568         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
569         {
570           Image_ColorRGBF& aPixel     = theImage.ChangeValue<Image_ColorRGBF> (aRow, aCol);
571           Image_ColorBGRF  aPixelCopy = theImage.Value      <Image_ColorBGRF> (aRow, aCol);
572           aPixel.r() = aPixelCopy.r();
573           aPixel.g() = aPixelCopy.g();
574           aPixel.b() = aPixelCopy.b();
575         }
576       }
577       return true;
578     }
579     default: return false;
580   }
581 }
582
583 // =======================================================================
584 // function : ToBlackWhite
585 // purpose  :
586 // =======================================================================
587 void Image_PixMap::ToBlackWhite (Image_PixMap& theImage)
588 {
589   switch (theImage.Format())
590   {
591     case Image_Format_Gray:
592     case Image_Format_Alpha:
593     {
594       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
595       {
596         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
597         {
598           unsigned char& aPixel = theImage.ChangeValue<unsigned char> (aRow, aCol);
599           if (aPixel != 0)
600           {
601             aPixel = 255;
602           }
603         }
604       }
605       break;
606     }
607     case Image_Format_RGB:
608     case Image_Format_BGR:
609     case Image_Format_RGB32:
610     case Image_Format_BGR32:
611     case Image_Format_RGBA:
612     case Image_Format_BGRA:
613     {
614       const NCollection_Vec3<unsigned char> aWhite24 (255, 255, 255);
615       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
616       {
617         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
618         {
619           NCollection_Vec3<unsigned char>& aPixel = theImage.ChangeValue< NCollection_Vec3<unsigned char> > (aRow, aCol);
620           if (aPixel[0] != 0
621            || aPixel[1] != 0
622            || aPixel[2] != 0)
623           {
624             aPixel = aWhite24;
625           }
626         }
627       }
628       break;
629     }
630     default:
631     {
632       const Quantity_ColorRGBA aWhiteRgba (1.0f, 1.0f, 1.0f, 1.0f);
633       for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
634       {
635         for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
636         {
637           const Quantity_ColorRGBA       aPixelRgba = theImage.PixelColor (Standard_Integer(aCol), Standard_Integer(aRow));
638           const NCollection_Vec4<float>& aPixel     = aPixelRgba;
639           if (aPixel[0] != 0.0f
640            || aPixel[1] != 0.0f
641            || aPixel[2] != 0.0f)
642           {
643             theImage.SetPixelColor (int(aCol), int(aRow), aWhiteRgba);
644           }
645         }
646       }
647       break;
648     }
649   }
650 }