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