Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix memory corruption & leaks in Image #240

Merged
merged 1 commit into from
Aug 23, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 36 additions & 6 deletions graphics/src/Image.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ namespace ignition
public: void DataImpl(unsigned char **_data, unsigned int &_count,
FIBITMAP *_img) const;

/// \brief Returns true if SwapRedBlue can and should be called
/// If it returns false, it may not be safe to call SwapRedBlue
/// (it could lead to memory corruption!). See CanSwapRedBlue
/// \return True if we should call SwapRedBlue
public: bool ShouldSwapRedBlue() const;

/// \brief Returns true if SwapRedBlue is safe to be called
/// \return False if it is NOT safe to call SwapRedBlue
public: bool CanSwapRedBlue() const;

/// \brief Swap red and blue pixels
/// \param[in] _width Width of the image
/// \param[in] _height Height of the image
Expand Down Expand Up @@ -223,10 +233,12 @@ void Image::SetFromData(const unsigned char *_data,
this->dataPtr->bitmap = FreeImage_ConvertFromRawBits(const_cast<BYTE*>(_data),
_width, _height, scanlineBytes, bpp, redmask, greenmask, bluemask, true);

if (FREEIMAGE_COLORORDER != FREEIMAGE_COLORORDER_RGB)
if (this->dataPtr->ShouldSwapRedBlue())
{
FIBITMAP *toDelete = this->dataPtr->bitmap;
this->dataPtr->bitmap = this->dataPtr->SwapRedBlue(this->Width(),
this->Height());
this->Height());
FreeImage_Unload(toDelete);
}
}

Expand All @@ -240,22 +252,27 @@ int Image::Pitch() const
void Image::RGBData(unsigned char **_data, unsigned int &_count)
{
FIBITMAP *tmp = this->dataPtr->bitmap;
if (FREEIMAGE_COLORORDER != FREEIMAGE_COLORORDER_RGB)
FIBITMAP *tmp2 = nullptr;
if (this->dataPtr->ShouldSwapRedBlue())
{
tmp = this->dataPtr->SwapRedBlue(this->Width(), this->Height());
tmp2 = tmp;
}
tmp = FreeImage_ConvertTo24Bits(tmp);
this->dataPtr->DataImpl(_data, _count, tmp);
FreeImage_Unload(tmp);
if (tmp2)
FreeImage_Unload(tmp2);
}

//////////////////////////////////////////////////
void Image::Data(unsigned char **_data, unsigned int &_count)
{
if (FREEIMAGE_COLORORDER != FREEIMAGE_COLORORDER_RGB)
if (this->dataPtr->ShouldSwapRedBlue())
{
this->dataPtr->DataImpl(_data, _count, this->dataPtr->SwapRedBlue(
this->Width(), this->Height()));
FIBITMAP *tmp = this->dataPtr->SwapRedBlue(this->Width(), this->Height());
this->dataPtr->DataImpl(_data, _count, tmp);
FreeImage_Unload(tmp);
}
else
{
Expand Down Expand Up @@ -550,6 +567,19 @@ Image::PixelFormatType Image::ConvertPixelFormat(const std::string &_format)
return UNKNOWN_PIXEL_FORMAT;
}

//////////////////////////////////////////////////
bool Image::Implementation::ShouldSwapRedBlue() const
{
return CanSwapRedBlue() && FREEIMAGE_COLORORDER != FREEIMAGE_COLORORDER_RGB;
}

//////////////////////////////////////////////////
bool Image::Implementation::CanSwapRedBlue() const
{
const unsigned bpp = FreeImage_GetBPP(this->bitmap);
return bpp == 24u || bpp == 32u;
}

//////////////////////////////////////////////////
FIBITMAP* Image::Implementation::SwapRedBlue(const unsigned int &_width,
const unsigned int &_height)
Expand Down