1 // Created on: 2010-07-18
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2010-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <Image_PixMap.hxx>
18 #include <NCollection_AlignedAllocator.hxx>
19 #include <Standard_ProgramError.hxx>
25 //! Structure defining image pixel format description.
26 struct Image_FormatInfo
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
33 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) {}
36 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) {}
40 #define ImageFormatInfo(theName, theNbComponents, thePixelSize) \
41 Image_FormatInfo(Image_Format_##theName, #theName, theNbComponents, thePixelSize)
43 #define CompressedImageFormatInfo(theName, theNbComponents, thePixelSize) \
44 Image_FormatInfo(Image_CompressedFormat_##theName, #theName, theNbComponents, thePixelSize)
46 //! Table of image pixel formats.
47 static const Image_FormatInfo Image_Table_ImageFormats[Image_CompressedFormat_NB] =
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(GrayF_half, 1, sizeof(uint16_t) * 1),
66 ImageFormatInfo(RGF_half, 2, sizeof(uint16_t) * 2),
67 ImageFormatInfo(RGBAF_half, 4, sizeof(uint16_t) * 4),
68 ImageFormatInfo(Gray16, 1, 2),
69 CompressedImageFormatInfo(RGB_S3TC_DXT1, 3, 1), // DXT1 uses circa half a byte per pixel (64 bits per 4x4 block)
70 CompressedImageFormatInfo(RGBA_S3TC_DXT1, 4, 1),
71 CompressedImageFormatInfo(RGBA_S3TC_DXT3, 4, 1), // DXT3/5 uses circa 1 byte per pixel (128 bits per 4x4 block)
72 CompressedImageFormatInfo(RGBA_S3TC_DXT5, 4, 1)
76 IMPLEMENT_STANDARD_RTTIEXT(Image_PixMapData, NCollection_Buffer)
77 IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap, Standard_Transient)
79 // =======================================================================
80 // function : DefaultAllocator
82 // =======================================================================
83 const Handle(NCollection_BaseAllocator)& Image_PixMap::DefaultAllocator()
85 static const Handle(NCollection_BaseAllocator) THE_ALLOC = new NCollection_AlignedAllocator (16);
89 // =======================================================================
90 // function : ImageFormatToString
92 // =======================================================================
93 Standard_CString Image_PixMap::ImageFormatToString (Image_Format theFormat)
95 return Image_Table_ImageFormats[theFormat].Name;
98 // =======================================================================
99 // function : ImageFormatToString
101 // =======================================================================
102 Standard_CString Image_PixMap::ImageFormatToString (Image_CompressedFormat theFormat)
104 return Image_Table_ImageFormats[theFormat].Name;
107 // =======================================================================
108 // function : Image_PixMap
110 // =======================================================================
111 Image_PixMap::Image_PixMap()
112 : myImgFormat (Image_Format_Gray)
117 // =======================================================================
118 // function : ~Image_PixMap
120 // =======================================================================
121 Image_PixMap::~Image_PixMap()
126 // =======================================================================
127 // function : SizePixelBytes
129 // =======================================================================
130 Standard_Size Image_PixMap::SizePixelBytes (const Image_Format thePixelFormat)
132 return Image_Table_ImageFormats[thePixelFormat].PixelSize;
135 // =======================================================================
136 // function : SetFormat
138 // =======================================================================
139 void Image_PixMap::SetFormat (Image_Format thePixelFormat)
141 if (myImgFormat == thePixelFormat)
147 && SizePixelBytes (myImgFormat) != SizePixelBytes (thePixelFormat))
149 throw Standard_ProgramError("Image_PixMap::SetFormat() - incompatible pixel format");
153 myImgFormat = thePixelFormat;
156 // =======================================================================
157 // function : InitWrapper3D
159 // =======================================================================
160 bool Image_PixMap::InitWrapper3D (Image_Format thePixelFormat,
161 Standard_Byte* theDataPtr,
162 const NCollection_Vec3<Standard_Size>& theSizeXYZ,
163 const Standard_Size theSizeRowBytes)
166 myImgFormat = thePixelFormat;
167 if (theSizeXYZ.x() == 0
168 || theSizeXYZ.y() == 0
169 || theSizeXYZ.z() == 0
170 || theDataPtr == nullptr)
175 Handle(NCollection_BaseAllocator) anEmptyAlloc;
176 myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (thePixelFormat),
177 theSizeXYZ, theSizeRowBytes, theDataPtr);
181 // =======================================================================
182 // function : InitWrapper
184 // =======================================================================
185 bool Image_PixMap::InitWrapper (Image_Format thePixelFormat,
186 Standard_Byte* theDataPtr,
187 const Standard_Size theSizeX,
188 const Standard_Size theSizeY,
189 const Standard_Size theSizeRowBytes)
191 return InitWrapper3D (thePixelFormat, theDataPtr, NCollection_Vec3<Standard_Size> (theSizeX, theSizeY, 1), theSizeRowBytes);
194 // =======================================================================
195 // function : InitTrash3D
197 // =======================================================================
198 bool Image_PixMap::InitTrash3D (Image_Format thePixelFormat,
199 const NCollection_Vec3<Standard_Size>& theSizeXYZ,
200 const Standard_Size theSizeRowBytes)
203 myImgFormat = thePixelFormat;
204 if (theSizeXYZ.x() == 0
205 || theSizeXYZ.y() == 0
206 || theSizeXYZ.z() == 0)
211 // use argument only if it greater
212 const Standard_Size aSizeRowBytes = std::max (theSizeRowBytes, theSizeXYZ.x() * SizePixelBytes (thePixelFormat));
213 myData.Init (DefaultAllocator(), Image_PixMap::SizePixelBytes (thePixelFormat),
214 theSizeXYZ, aSizeRowBytes, NULL);
215 return !myData.IsEmpty();
218 // =======================================================================
219 // function : InitTrash
221 // =======================================================================
222 bool Image_PixMap::InitTrash (Image_Format thePixelFormat,
223 const Standard_Size theSizeX,
224 const Standard_Size theSizeY,
225 const Standard_Size theSizeRowBytes)
227 return InitTrash3D (thePixelFormat, NCollection_Vec3<Standard_Size> (theSizeX, theSizeY, 1), theSizeRowBytes);
230 // =======================================================================
231 // function : InitZero3D
233 // =======================================================================
234 bool Image_PixMap::InitZero3D (Image_Format thePixelFormat,
235 const NCollection_Vec3<Standard_Size>& theSizeXYZ,
236 const Standard_Size theSizeRowBytes,
237 const Standard_Byte theValue)
239 if (theSizeXYZ.z() > 1)
241 if (!InitTrash3D (thePixelFormat, theSizeXYZ, theSizeRowBytes))
248 if (!InitTrash (thePixelFormat, theSizeXYZ.x(), theSizeXYZ.y(), theSizeRowBytes))
253 memset (myData.ChangeData(), (int )theValue, SizeBytes());
257 // =======================================================================
258 // function : InitCopy
260 // =======================================================================
261 bool Image_PixMap::InitCopy (const Image_PixMap& theCopy)
263 if (&theCopy == this)
265 // self-copying disallowed
269 if (theCopy.SizeZ() > 1)
271 if (!InitTrash3D (theCopy.myImgFormat, theCopy.SizeXYZ(), theCopy.SizeRowBytes()))
278 if (!InitTrash (theCopy.myImgFormat, theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
284 memcpy (myData.ChangeData(), theCopy.myData.Data(), theCopy.SizeBytes());
288 // =======================================================================
291 // =======================================================================
292 void Image_PixMap::Clear()
294 Handle(NCollection_BaseAllocator) anEmptyAlloc;
295 myData.Init (anEmptyAlloc, Image_PixMap::SizePixelBytes (myImgFormat),
296 NCollection_Vec3<Standard_Size> (0), 0, nullptr);
299 // =======================================================================
300 // function : ColorFromRawPixel
302 // =======================================================================
303 Quantity_ColorRGBA Image_PixMap::ColorFromRawPixel (const Standard_Byte* theRawValue,
304 const Image_Format theFormat,
305 const Standard_Boolean theToLinearize)
309 case Image_Format_GrayF:
311 const Standard_ShortReal& aPixel = *reinterpret_cast<const Standard_ShortReal*> (theRawValue);
312 return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel, aPixel, aPixel, 1.0f)); // opaque
314 case Image_Format_AlphaF:
316 const Standard_ShortReal& aPixel = *reinterpret_cast<const Standard_ShortReal*> (theRawValue);
317 return Quantity_ColorRGBA (NCollection_Vec4<float> (1.0f, 1.0f, 1.0f, aPixel));
319 case Image_Format_RGF:
321 const Image_ColorRGF& aPixel = *reinterpret_cast<const Image_ColorRGF*> (theRawValue);
322 return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), 0.0f, 1.0f));
324 case Image_Format_RGBAF:
326 const Image_ColorRGBAF& aPixel = *reinterpret_cast<const Image_ColorRGBAF*> (theRawValue);
327 return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), aPixel.a()));
329 case Image_Format_BGRAF:
331 const Image_ColorBGRAF& aPixel = *reinterpret_cast<const Image_ColorBGRAF*> (theRawValue);
332 return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), aPixel.a()));
334 case Image_Format_RGBF:
336 const Image_ColorRGBF& aPixel = *reinterpret_cast<const Image_ColorRGBF*> (theRawValue);
337 return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), 1.0f)); // opaque
339 case Image_Format_BGRF:
341 const Image_ColorBGRF& aPixel = *reinterpret_cast<const Image_ColorBGRF*> (theRawValue);
342 return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), aPixel.b(), 1.0f)); // opaque
344 case Image_Format_GrayF_half:
346 const uint16_t& aPixel = *reinterpret_cast<const uint16_t*> (theRawValue);
347 return Quantity_ColorRGBA (NCollection_Vec4<float> (ConvertFromHalfFloat (aPixel), 0.0f, 0.0f, 1.0f));
349 case Image_Format_RGF_half:
351 const NCollection_Vec2<uint16_t>& aPixel = *reinterpret_cast<const NCollection_Vec2<uint16_t>*> (theRawValue);
352 return Quantity_ColorRGBA (NCollection_Vec4<float> (ConvertFromHalfFloat (aPixel.x()), ConvertFromHalfFloat (aPixel.y()), 0.0f, 1.0f));
354 case Image_Format_RGBAF_half:
356 const NCollection_Vec4<uint16_t>& aPixel = *reinterpret_cast<const NCollection_Vec4<uint16_t>*> (theRawValue);
357 return Quantity_ColorRGBA (NCollection_Vec4<float> (ConvertFromHalfFloat (aPixel.r()), ConvertFromHalfFloat (aPixel.g()),
358 ConvertFromHalfFloat (aPixel.b()), ConvertFromHalfFloat (aPixel.a())));
360 case Image_Format_RGBA:
362 const Image_ColorRGBA& aPixel = *reinterpret_cast<const Image_ColorRGBA*> (theRawValue);
363 return theToLinearize
364 ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
365 Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
366 Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f),
367 float(aPixel.a()) / 255.0f)
368 : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, float(aPixel.a()) / 255.0f);
370 case Image_Format_BGRA:
372 const Image_ColorBGRA& aPixel = *reinterpret_cast<const Image_ColorBGRA*> (theRawValue);
373 return theToLinearize
374 ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
375 Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
376 Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f),
377 float(aPixel.a()) / 255.0f)
378 : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, float(aPixel.a()) / 255.0f);
380 case Image_Format_RGB32:
382 const Image_ColorRGB32& aPixel = *reinterpret_cast<const Image_ColorRGB32*> (theRawValue);
383 return theToLinearize
384 ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
385 Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
386 Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f), 1.0f)
387 : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f);
389 case Image_Format_BGR32:
391 const Image_ColorBGR32& aPixel = *reinterpret_cast<const Image_ColorBGR32*> (theRawValue);
392 return theToLinearize
393 ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
394 Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
395 Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f), 1.0f)
396 : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f);
398 case Image_Format_RGB:
400 const Image_ColorRGB& aPixel = *reinterpret_cast<const Image_ColorRGB*> (theRawValue);
401 return theToLinearize
402 ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
403 Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
404 Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f), 1.0f)
405 : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f);
407 case Image_Format_BGR:
409 const Image_ColorBGR& aPixel = *reinterpret_cast<const Image_ColorBGR*> (theRawValue);
410 return theToLinearize
411 ? Quantity_ColorRGBA (Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.r()) / 255.0f),
412 Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.g()) / 255.0f),
413 Quantity_Color::Convert_sRGB_To_LinearRGB (float(aPixel.b()) / 255.0f), 1.0f)
414 : Quantity_ColorRGBA (float(aPixel.r()) / 255.0f, float(aPixel.g()) / 255.0f, float(aPixel.b()) / 255.0f, 1.0f);
416 case Image_Format_Gray:
418 const Standard_Byte& aPixel = *reinterpret_cast<const Standard_Byte*> (theRawValue);
419 const float anIntensity = float(aPixel) / 255.0f;
420 return Quantity_ColorRGBA (anIntensity, anIntensity, anIntensity, 1.0f); // opaque
422 case Image_Format_Alpha:
424 const Standard_Byte& aPixel = *reinterpret_cast<const Standard_Byte*> (theRawValue);
425 return Quantity_ColorRGBA (1.0f, 1.0f, 1.0f, float(aPixel) / 255.0f);
427 case Image_Format_Gray16:
429 const uint16_t& aPixel = *reinterpret_cast<const uint16_t*> (theRawValue);
430 const float anIntensity = float(aPixel) / 65535.0f;
431 return Quantity_ColorRGBA (anIntensity, anIntensity, anIntensity, 1.0f); // opaque
433 case Image_Format_UNKNOWN:
439 // unsupported image type
440 return Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 0.0f); // transparent
443 // =======================================================================
444 // function : ColorToRawPixel
446 // =======================================================================
447 void Image_PixMap::ColorToRawPixel (Standard_Byte* theRawValue,
448 const Image_Format theFormat,
449 const Quantity_ColorRGBA& theColor,
450 const Standard_Boolean theToDeLinearize)
452 const NCollection_Vec4<float>& aColor = theColor;
455 case Image_Format_GrayF:
457 *reinterpret_cast<Standard_ShortReal*> (theRawValue) = aColor.r();
460 case Image_Format_AlphaF:
462 *reinterpret_cast<Standard_ShortReal*> (theRawValue) = aColor.a();
465 case Image_Format_RGF:
467 Image_ColorRGF& aPixel = *reinterpret_cast<Image_ColorRGF*> (theRawValue);
468 aPixel.r() = aColor.r();
469 aPixel.g() = aColor.g();
472 case Image_Format_RGBAF:
474 Image_ColorRGBAF& aPixel = *reinterpret_cast<Image_ColorRGBAF*> (theRawValue);
475 aPixel.r() = aColor.r();
476 aPixel.g() = aColor.g();
477 aPixel.b() = aColor.b();
478 aPixel.a() = aColor.a();
481 case Image_Format_BGRAF:
483 Image_ColorBGRAF& aPixel = *reinterpret_cast<Image_ColorBGRAF*> (theRawValue);
484 aPixel.r() = aColor.r();
485 aPixel.g() = aColor.g();
486 aPixel.b() = aColor.b();
487 aPixel.a() = aColor.a();
490 case Image_Format_RGBF:
492 Image_ColorRGBF& aPixel = *reinterpret_cast<Image_ColorRGBF*> (theRawValue);
493 aPixel.r() = aColor.r();
494 aPixel.g() = aColor.g();
495 aPixel.b() = aColor.b();
498 case Image_Format_BGRF:
500 Image_ColorBGRF& aPixel = *reinterpret_cast<Image_ColorBGRF*> (theRawValue);
501 aPixel.r() = aColor.r();
502 aPixel.g() = aColor.g();
503 aPixel.b() = aColor.b();
506 case Image_Format_GrayF_half:
508 uint16_t& aPixel = *reinterpret_cast<uint16_t*> (theRawValue);
509 aPixel = ConvertToHalfFloat (aColor.r());
512 case Image_Format_RGF_half:
514 NCollection_Vec2<uint16_t>& aPixel = *reinterpret_cast<NCollection_Vec2<uint16_t>*> (theRawValue);
515 aPixel.x() = ConvertToHalfFloat (aColor.r());
516 aPixel.y() = ConvertToHalfFloat (aColor.g());
519 case Image_Format_RGBAF_half:
521 NCollection_Vec4<uint16_t>& aPixel = *reinterpret_cast<NCollection_Vec4<uint16_t>*> (theRawValue);
522 aPixel.r() = ConvertToHalfFloat (aColor.r());
523 aPixel.g() = ConvertToHalfFloat (aColor.g());
524 aPixel.b() = ConvertToHalfFloat (aColor.b());
525 aPixel.a() = ConvertToHalfFloat (aColor.a());
528 case Image_Format_RGBA:
530 Image_ColorRGBA& aPixel = *reinterpret_cast<Image_ColorRGBA*> (theRawValue);
531 if (theToDeLinearize)
533 aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
534 aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
535 aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
539 aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
540 aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
541 aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
543 aPixel.a() = Standard_Byte(aColor.a() * 255.0f);
546 case Image_Format_BGRA:
548 Image_ColorBGRA& aPixel = *reinterpret_cast<Image_ColorBGRA*> (theRawValue);
549 if (theToDeLinearize)
551 aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
552 aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
553 aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
557 aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
558 aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
559 aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
561 aPixel.a() = Standard_Byte(aColor.a() * 255.0f);
564 case Image_Format_RGB32:
566 Image_ColorRGB32& aPixel = *reinterpret_cast<Image_ColorRGB32*> (theRawValue);
567 if (theToDeLinearize)
569 aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
570 aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
571 aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
575 aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
576 aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
577 aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
582 case Image_Format_BGR32:
584 Image_ColorBGR32& aPixel = *reinterpret_cast<Image_ColorBGR32*> (theRawValue);
585 if (theToDeLinearize)
587 aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
588 aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
589 aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
593 aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
594 aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
595 aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
600 case Image_Format_RGB:
602 Image_ColorRGB& aPixel = *reinterpret_cast<Image_ColorRGB*> (theRawValue);
603 if (theToDeLinearize)
605 aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
606 aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
607 aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
611 aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
612 aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
613 aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
617 case Image_Format_BGR:
619 Image_ColorBGR& aPixel = *reinterpret_cast<Image_ColorBGR*> (theRawValue);
620 if (theToDeLinearize)
622 aPixel.r() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.r()) * 255.0f);
623 aPixel.g() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.g()) * 255.0f);
624 aPixel.b() = Standard_Byte(Quantity_Color::Convert_LinearRGB_To_sRGB (aColor.b()) * 255.0f);
628 aPixel.r() = Standard_Byte(aColor.r() * 255.0f);
629 aPixel.g() = Standard_Byte(aColor.g() * 255.0f);
630 aPixel.b() = Standard_Byte(aColor.b() * 255.0f);
634 case Image_Format_Gray:
636 *reinterpret_cast<Standard_Byte*>(theRawValue) = Standard_Byte(aColor.r() * 255.0f);
639 case Image_Format_Alpha:
641 *reinterpret_cast<Standard_Byte*>(theRawValue) = Standard_Byte(aColor.a() * 255.0f);
644 case Image_Format_Gray16:
646 *reinterpret_cast<uint16_t*>(theRawValue) = uint16_t(aColor.r() * 65535.0f);
649 case Image_Format_UNKNOWN:
656 // =======================================================================
657 // function : SwapRgbaBgra
659 // =======================================================================
660 bool Image_PixMap::SwapRgbaBgra (Image_PixMap& theImage)
662 switch (theImage.Format())
664 case Image_Format_BGR32:
665 case Image_Format_RGB32:
666 case Image_Format_BGRA:
667 case Image_Format_RGBA:
669 const bool toResetAlpha = theImage.Format() == Image_Format_BGR32
670 || theImage.Format() == Image_Format_RGB32;
671 for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
673 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
675 for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
677 Image_ColorRGBA& aPixel = theImage.ChangeValueXYZ<Image_ColorRGBA> (aCol, aRow, aSlice);
678 Image_ColorBGRA aPixelCopy = theImage.ValueXYZ <Image_ColorBGRA> (aCol, aRow, aSlice);
679 aPixel.r() = aPixelCopy.r();
680 aPixel.g() = aPixelCopy.g();
681 aPixel.b() = aPixelCopy.b();
691 case Image_Format_BGR:
692 case Image_Format_RGB:
694 for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
696 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
698 for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
700 Image_ColorRGB& aPixel = theImage.ChangeValueXYZ<Image_ColorRGB> (aCol, aRow, aSlice);
701 Image_ColorBGR aPixelCopy = theImage.ValueXYZ <Image_ColorBGR> (aCol, aRow, aSlice);
702 aPixel.r() = aPixelCopy.r();
703 aPixel.g() = aPixelCopy.g();
704 aPixel.b() = aPixelCopy.b();
710 case Image_Format_BGRF:
711 case Image_Format_RGBF:
712 case Image_Format_BGRAF:
713 case Image_Format_RGBAF:
715 for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
717 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
719 for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
721 Image_ColorRGBF& aPixel = theImage.ChangeValueXYZ<Image_ColorRGBF> (aCol, aRow, aSlice);
722 Image_ColorBGRF aPixelCopy = theImage.ValueXYZ <Image_ColorBGRF> (aCol, aRow, aSlice);
723 aPixel.r() = aPixelCopy.r();
724 aPixel.g() = aPixelCopy.g();
725 aPixel.b() = aPixelCopy.b();
731 default: return false;
735 // =======================================================================
736 // function : ToBlackWhite
738 // =======================================================================
739 void Image_PixMap::ToBlackWhite (Image_PixMap& theImage)
741 switch (theImage.Format())
743 case Image_Format_Gray:
744 case Image_Format_Alpha:
746 for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
748 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
750 for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
752 uint8_t& aPixel = theImage.ChangeValueXYZ<uint8_t> (aCol, aRow, aSlice);
762 case Image_Format_Gray16:
764 for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
766 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
768 for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
770 uint16_t& aPixel = theImage.ChangeValueXYZ<uint16_t> (aCol, aRow, aSlice);
780 case Image_Format_RGB:
781 case Image_Format_BGR:
782 case Image_Format_RGB32:
783 case Image_Format_BGR32:
784 case Image_Format_RGBA:
785 case Image_Format_BGRA:
787 const NCollection_Vec3<uint8_t> aWhite24 (255, 255, 255);
788 for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
790 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
792 for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
794 NCollection_Vec3<uint8_t>& aPixel = theImage.ChangeValueXYZ< NCollection_Vec3<uint8_t> > (aCol, aRow, aSlice);
808 const Quantity_ColorRGBA aWhiteRgba (1.0f, 1.0f, 1.0f, 1.0f);
809 for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
811 for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
813 for (Standard_Size aCol = 0; aCol < theImage.SizeX(); ++aCol)
815 Standard_Byte* aRawPixel = theImage.ChangeRawValueXYZ (aCol, aRow, aSlice);
816 const Quantity_ColorRGBA aPixelRgba = ColorFromRawPixel (aRawPixel, theImage.Format());
817 const NCollection_Vec4<float>& aPixel = aPixelRgba;
818 if (aPixel[0] != 0.0f
820 || aPixel[2] != 0.0f)
822 ColorToRawPixel (aRawPixel, theImage.Format(), aWhiteRgba);
832 // =======================================================================
835 // =======================================================================
836 bool Image_PixMap::FlipY (Image_PixMap& theImage)
838 if (theImage.IsEmpty()
839 || theImage.SizeX() == 0
840 || theImage.SizeY() == 0)
845 NCollection_Buffer aTmp (NCollection_BaseAllocator::CommonBaseAllocator());
846 const size_t aRowSize = theImage.SizeRowBytes();
847 if (!aTmp.Allocate (aRowSize))
852 // for odd height middle row should be left as is
853 Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
854 for (Standard_Size aSlice = 0; aSlice < theImage.SizeZ(); ++aSlice)
856 for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
858 Standard_Byte* aTop = theImage.ChangeSliceRow (aSlice, aRowT);
859 Standard_Byte* aBot = theImage.ChangeSliceRow (aSlice, aRowB);
860 memcpy (aTmp.ChangeData(), aTop, aRowSize);
861 memcpy (aTop, aBot, aRowSize);
862 memcpy (aBot, aTmp.Data(), aRowSize);