mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 23:55:38 +00:00
Added a function to ImageComponent to crop fully transparent areas around an image.
This commit is contained in:
parent
64b112a1b6
commit
aeb74055d0
|
@ -9,6 +9,7 @@
|
|||
#include "components/ImageComponent.h"
|
||||
|
||||
#include "resources/TextureResource.h"
|
||||
#include "utils/CImgUtil.h"
|
||||
#include "Log.h"
|
||||
#include "Settings.h"
|
||||
#include "ThemeData.h"
|
||||
|
@ -264,6 +265,55 @@ void ImageComponent::uncrop()
|
|||
crop(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void ImageComponent::cropTransparentPadding(float maxSizeX, float maxSizeY)
|
||||
{
|
||||
if (mSize == 0)
|
||||
return;
|
||||
|
||||
std::vector<unsigned char> imageRGBA = mTexture.get()->getRawRGBAData();
|
||||
|
||||
if (imageRGBA.size() == 0)
|
||||
return;
|
||||
|
||||
Vector2i imageSize = mTexture.get()->getSize();
|
||||
cimg_library::CImg<unsigned char> imageCImg(imageSize.x(), imageSize.y(), 1, 4, 0);
|
||||
|
||||
int paddingCoords[4] = {};
|
||||
|
||||
// We need to convert our RGBA data to the CImg internal format as CImg does not interleave
|
||||
// the pixels (as in RGBARGBARGBA).
|
||||
Utils::CImg::convertRGBAToCImg(imageRGBA, imageCImg);
|
||||
|
||||
// This will give us the coordinates for the fully transparent areas.
|
||||
Utils::CImg::getTransparentPaddingCoords(imageCImg, paddingCoords);
|
||||
|
||||
Vector2f originalSize = mSize;
|
||||
|
||||
float cropLeft = static_cast<float>(paddingCoords[0]) / static_cast<float>(imageSize.x());
|
||||
float cropTop = static_cast<float>(paddingCoords[1]) / static_cast<float>(imageSize.y());
|
||||
float cropRight = static_cast<float>(paddingCoords[2]) / static_cast<float>(imageSize.x());
|
||||
float cropBottom = static_cast<float>(paddingCoords[3]) / static_cast<float>(imageSize.y());
|
||||
|
||||
crop(cropLeft, cropTop, cropRight, cropBottom);
|
||||
|
||||
// Cropping the image obviously leads to a reduction in size, so we need to determine
|
||||
// how much to scale up after cropping to keep within the max size restrictions that
|
||||
// were passed as arguments.
|
||||
mSize.x() -= mSize.x() * (cropLeft + cropRight);
|
||||
mSize.y() -= mSize.y() * (cropTop + cropBottom);
|
||||
|
||||
float scaleFactor = originalSize.y() / mSize.y();
|
||||
|
||||
if (scaleFactor * mSize.x() > maxSizeX)
|
||||
scaleFactor = maxSizeX / mSize.x();
|
||||
|
||||
if (scaleFactor * mSize.y() > maxSizeY)
|
||||
scaleFactor = maxSizeY / mSize.y();
|
||||
|
||||
setResize(mSize.x() * scaleFactor, mSize.y() * scaleFactor);
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
void ImageComponent::setFlipX(bool flip)
|
||||
{
|
||||
mFlipX = flip;
|
||||
|
@ -314,8 +364,8 @@ void ImageComponent::updateVertices()
|
|||
|
||||
// We go through this mess to make sure everything is properly rounded.
|
||||
// If we just round vertices at the end, edge cases occur near sizes of 0.5.
|
||||
const Vector2f topLeft = { mSize * mTopLeftCrop };
|
||||
const Vector2f bottomRight = { mSize * mBottomRightCrop };
|
||||
const Vector2f topLeft = { 0, 0 };
|
||||
const Vector2f bottomRight = mSize;
|
||||
const float px = mTexture->isTiled() ? mSize.x() / getTextureSize().x() : 1.0f;
|
||||
const float py = mTexture->isTiled() ? mSize.y() / getTextureSize().y() : 1.0f;
|
||||
|
||||
|
|
|
@ -61,6 +61,10 @@ public:
|
|||
void crop(float left, float top, float right, float bot);
|
||||
void uncrop();
|
||||
|
||||
// This crops any entirely transparent areas around the actual image.
|
||||
// The arguments restrict how much the end result is allowed to be scaled.
|
||||
void cropTransparentPadding(float maxSizeX, float maxSizeY);
|
||||
|
||||
// Multiply all pixels in the image by this color when rendering.
|
||||
void setColorShift(unsigned int color) override;
|
||||
void setColorShiftEnd(unsigned int color);
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
// Define a factor for scaling the file when loading it (1.0f = no scaling).
|
||||
void setScaleDuringLoad(float scale) { mScaleDuringLoad = scale; }
|
||||
|
||||
std::vector<unsigned char> getRawRGBAData() { return mDataRGBA; }
|
||||
bool tiled() { return mTile; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -105,6 +105,16 @@ void TextureResource::manualUnload(std::string path, bool tile)
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned char> TextureResource::getRawRGBAData()
|
||||
{
|
||||
std::shared_ptr<TextureData> data = sTextureDataManager.get(this);
|
||||
|
||||
if (data)
|
||||
return data.get()->getRawRGBAData();
|
||||
else
|
||||
return std::vector<unsigned char>(0);
|
||||
}
|
||||
|
||||
const Vector2i TextureResource::getSize() const
|
||||
{
|
||||
return mSize;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <cmath>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class TextureData;
|
||||
|
||||
|
@ -35,6 +36,9 @@ public:
|
|||
virtual void initFromMemory(const char* data, size_t length);
|
||||
static void manualUnload(std::string path, bool tile);
|
||||
|
||||
// Returns the raw pixel values.
|
||||
std::vector<unsigned char> getRawRGBAData();
|
||||
|
||||
// For SVG graphics this function effectively rescales the image to the defined size.
|
||||
// It does unload and re-rasterize the texture though which may cause flickering in some
|
||||
// situations. An alternative is to set a scaling factor directly when loading the texture
|
||||
|
|
Loading…
Reference in a new issue