1919#endif
2020#include < FreeImage.h>
2121
22+ #include < cstdint>
2223#include < cstring>
2324#include < string>
2425
@@ -37,7 +38,7 @@ namespace gz
3738 class Image ::Implementation
3839 {
3940 // / \brief bitmap data
40- public: FIBITMAP *bitmap;
41+ public: FIBITMAP *bitmap{ nullptr } ;
4142
4243 // / \brief path name of the image file
4344 public: std::string fullName;
@@ -48,6 +49,12 @@ namespace gz
4849 public: void DataImpl (unsigned char **_data, unsigned int &_count,
4950 FIBITMAP *_img) const ;
5051
52+ // / \brief Color type for this image
53+ public: FREE_IMAGE_COLOR_TYPE colorType{FIC_RGB};
54+
55+ // / \brief Image type, i.e. pixel format
56+ public: FREE_IMAGE_TYPE imageType{FIT_UNKNOWN};
57+
5158 // / \brief Implementation of Data, returns vector of bytes
5259 public: std::vector<unsigned char > DataImpl (FIBITMAP *_img) const ;
5360
@@ -156,6 +163,9 @@ int Image::Load(const std::string &_filename)
156163 return -1 ;
157164 }
158165
166+ this ->dataPtr ->colorType = FreeImage_GetColorType (this ->dataPtr ->bitmap );
167+ this ->dataPtr ->imageType = FreeImage_GetImageType (this ->dataPtr ->bitmap );
168+
159169 return 0 ;
160170 }
161171
@@ -263,6 +273,8 @@ void Image::SetFromData(const unsigned char *_data,
263273 this ->Height ());
264274 FreeImage_Unload (toDelete);
265275 }
276+ this ->dataPtr ->colorType = FreeImage_GetColorType (this ->dataPtr ->bitmap );
277+ this ->dataPtr ->imageType = FreeImage_GetImageType (this ->dataPtr ->bitmap );
266278}
267279
268280// ////////////////////////////////////////////////
@@ -291,6 +303,8 @@ void Image::SetFromCompressedData(unsigned char *_data,
291303 FIMEMORY *fiMem = FreeImage_OpenMemory (_data, _size);
292304 this ->dataPtr ->bitmap = FreeImage_LoadFromMemory (format, fiMem);
293305 FreeImage_CloseMemory (fiMem);
306+ this ->dataPtr ->colorType = FreeImage_GetColorType (this ->dataPtr ->bitmap );
307+ this ->dataPtr ->imageType = FreeImage_GetImageType (this ->dataPtr ->bitmap );
294308 }
295309 else
296310 {
@@ -521,16 +535,22 @@ math::Color Image::Pixel(unsigned int _x, unsigned int _y) const
521535 if (!this ->Valid ())
522536 return clr;
523537
524- FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType (this ->dataPtr ->bitmap );
538+ if (_x >= this ->Width () || _y >= this ->Height ())
539+ {
540+ gzerr << " Image: Coordinates out of range["
541+ << _x << " , " << _y << " ] \n " ;
542+ return clr;
543+ }
525544
526- if (type == FIC_RGB || type == FIC_RGBALPHA)
545+ if ((this ->dataPtr ->colorType == FIC_RGB ||
546+ this ->dataPtr ->colorType == FIC_RGBALPHA) &&
547+ (this ->dataPtr ->imageType == FIT_BITMAP))
527548 {
528549 RGBQUAD firgb;
529-
530550 if (FreeImage_GetPixelColor (this ->dataPtr ->bitmap , _x, _y, &firgb) == FALSE )
531551 {
532- gzerr << " Image: Coordinates out of range ["
533- << _x << " " << _y << " ] \n " ;
552+ gzerr << " Failed to get pixel value at ["
553+ << _x << " , " << _y << " ] \n " ;
534554 return clr;
535555 }
536556 clr.Set (firgb.rgbRed / 255 .0f , firgb.rgbGreen / 255 .0f ,
@@ -541,8 +561,8 @@ math::Color Image::Pixel(unsigned int _x, unsigned int _y) const
541561 if (this ->dataPtr ->PixelIndex (
542562 this ->dataPtr ->bitmap , _x, _y, clr) == FALSE )
543563 {
544- gzerr << " Image: Coordinates out of range ["
545- << _x << " " << _y << " ] \n " ;
564+ gzerr << " Failed to get pixel value at ["
565+ << _x << " , " << _y << " ] \n " ;
546566 return clr;
547567 }
548568 }
@@ -579,64 +599,20 @@ math::Color Image::AvgColor() const
579599// ////////////////////////////////////////////////
580600math::Color Image::MaxColor () const
581601{
582- unsigned int x, y;
583- math::Color clr;
584602 math::Color maxClr;
585603
586- maxClr.Set (0 , 0 , 0 , 0 );
587-
588604 if (!this ->Valid ())
589- return clr;
590-
591- FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType (this ->dataPtr ->bitmap );
592-
593- if (type == FIC_RGB || type == FIC_RGBALPHA)
594- {
595- RGBQUAD firgb;
605+ return maxClr;
596606
597- for (y = 0 ; y < this ->Height (); y++)
598- {
599- for (x = 0 ; x < this ->Width (); x++)
600- {
601- clr.Set (0 , 0 , 0 , 0 );
602-
603- if (FALSE ==
604- FreeImage_GetPixelColor (this ->dataPtr ->bitmap , x, y, &firgb))
605- {
606- gzerr << " Image: Coordinates out of range["
607- << x << " " << y << " ] \n " ;
608- continue ;
609- }
610- clr.Set (firgb.rgbRed / 255 .0f , firgb.rgbGreen / 255 .0f ,
611- firgb.rgbBlue / 255 .0f );
612-
613- if (clr.R () + clr.G () + clr.B () > maxClr.R () + maxClr.G () + maxClr.B ())
614- {
615- maxClr = clr;
616- }
617- }
618- }
619- }
620- else
607+ maxClr.Set (0 , 0 , 0 , 0 );
608+ for (unsigned int y = 0 ; y < this ->Height (); y++)
621609 {
622- for (y = 0 ; y < this ->Height (); y ++)
610+ for (unsigned int x = 0 ; x < this ->Width (); x ++)
623611 {
624- for (x = 0 ; x < this ->Width (); x++)
612+ math::Color clr = this ->Pixel (x, y);
613+ if (clr.R () + clr.G () + clr.B () > maxClr.R () + maxClr.G () + maxClr.B ())
625614 {
626- clr.Set (0 , 0 , 0 , 0 );
627-
628- if (this ->dataPtr ->PixelIndex (
629- this ->dataPtr ->bitmap , x, y, clr) == FALSE )
630- {
631- gzerr << " Image: Coordinates out of range ["
632- << x << " " << y << " ] \n " ;
633- continue ;
634- }
635-
636- if (clr.R () + clr.G () + clr.B () > maxClr.R () + maxClr.G () + maxClr.B ())
637- {
638- maxClr = clr;
639- }
615+ maxClr = clr;
640616 }
641617 }
642618 }
@@ -651,9 +627,11 @@ BOOL Image::Implementation::PixelIndex(
651627 if (!_dib)
652628 return FALSE ;
653629
654- FREE_IMAGE_TYPE imageType = FreeImage_GetImageType (_dib);
630+ if (_x >= FreeImage_GetWidth (_dib) || _y >= FreeImage_GetHeight (_dib))
631+ return FALSE ;
632+
655633 // 8 bit images
656- if (imageType == FIT_BITMAP)
634+ if (this -> imageType == FIT_BITMAP)
657635 {
658636 BYTE byteValue;
659637 // FreeImage_GetPixelIndex should also work with 1 and 4 bit images
@@ -669,21 +647,51 @@ BOOL Image::Implementation::PixelIndex(
669647 _color.Set (value, value, value);
670648 }
671649 // 16 bit images
672- else if (imageType == FIT_UINT16)
650+ else if (this -> imageType == FIT_UINT16)
673651 {
674- if ((_x < FreeImage_GetWidth (_dib)) && (_y < FreeImage_GetHeight (_dib)))
675- {
676- WORD *bits = reinterpret_cast <WORD *>(FreeImage_GetScanLine (_dib, _y));
677- uint16_t word = static_cast <uint16_t >(bits[_x]);
678- // convert to float value between 0-1
679- float value = word / static_cast <float >(math::MAX_UI16);
680- _color.Set (value, value, value);
681- }
682- else
683- {
684- return FALSE ;
685- }
652+ WORD *bits = reinterpret_cast <WORD *>(FreeImage_GetScanLine (_dib, _y));
653+ uint16_t word = static_cast <uint16_t >(bits[_x]);
654+ // convert to float value between 0-1
655+ float value = word / static_cast <float >(math::MAX_UI16);
656+ _color.Set (value, value, value);
657+ }
658+ else if (this ->imageType == FIT_INT16)
659+ {
660+ WORD *bits = reinterpret_cast <WORD *>(FreeImage_GetScanLine (_dib, _y));
661+ int16_t word = static_cast <int16_t >(bits[_x]);
662+ // convert to float value between 0-1
663+ float value = word / static_cast <float >(math::MAX_I16);
664+ _color.Set (value, value, value);
686665 }
666+ else if (this ->imageType == FIT_RGB16)
667+ {
668+ const unsigned int channels = 3u ;
669+ WORD *bits = reinterpret_cast <WORD *>(FreeImage_GetScanLine (_dib, _y));
670+ uint16_t r = static_cast <uint16_t >(bits[_x * channels]);
671+ uint16_t g = static_cast <uint16_t >(bits[_x * channels + 1 ]);
672+ uint16_t b = static_cast <uint16_t >(bits[_x * channels + 2 ]);
673+ // convert to float value between 0-1
674+ float valueR = r / static_cast <float >(math::MAX_UI16);
675+ float valueG = g / static_cast <float >(math::MAX_UI16);
676+ float valueB = b / static_cast <float >(math::MAX_UI16);
677+ _color.Set (valueR, valueG, valueB);
678+ }
679+ else if (this ->imageType == FIT_RGBA16)
680+ {
681+ const unsigned int channels = 4u ;
682+ WORD *bits = reinterpret_cast <WORD *>(FreeImage_GetScanLine (_dib, _y));
683+ uint16_t r = static_cast <uint16_t >(bits[_x * channels]);
684+ uint16_t g = static_cast <uint16_t >(bits[_x * channels + 1 ]);
685+ uint16_t b = static_cast <uint16_t >(bits[_x * channels + 2 ]);
686+ uint16_t a = static_cast <uint16_t >(bits[_x * channels + 3 ]);
687+ // convert to float value between 0-1
688+ float valueR = r / static_cast <float >(math::MAX_UI16);
689+ float valueG = g / static_cast <float >(math::MAX_UI16);
690+ float valueB = b / static_cast <float >(math::MAX_UI16);
691+ float valueA = a / static_cast <float >(math::MAX_UI16);
692+ _color.Set (valueR, valueG, valueB, valueA);
693+ }
694+
687695 return TRUE ;
688696}
689697
0 commit comments