mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-27 00:25:38 +00:00
Two fixes with SVG rasterizing:
1. Original width/height were being returned as integers, even though they can be floats (see SVGResource::getImageSize()). Function also renamed to be more descriptive (renamed to getSourceImageSize()). 2. Now we always round height and scale width from the rounded height when doing scaling, since SVG rasterization scale is determined from height. This seems to fix some 1px cutoff I was seeing, but I'm not sure if it still works for images with extreme aspect ratios that are taller rather than wider.
This commit is contained in:
parent
d2c7de3802
commit
1e7ced2c66
|
@ -37,12 +37,20 @@ void ImageComponent::resize()
|
||||||
if(!mTexture)
|
if(!mTexture)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const Eigen::Vector2f textureSize((float)getTextureSize().x(), (float)getTextureSize().y());
|
SVGResource* svg = dynamic_cast<SVGResource*>(mTexture.get());
|
||||||
|
|
||||||
|
const Eigen::Vector2f textureSize = svg ? svg->getSourceImageSize() : Eigen::Vector2f((float)mTexture->getSize().x(), (float)mTexture->getSize().y());
|
||||||
|
|
||||||
if(mTexture->isTiled())
|
if(mTexture->isTiled())
|
||||||
{
|
{
|
||||||
mSize = mTargetSize;
|
mSize = mTargetSize;
|
||||||
}else{
|
}else{
|
||||||
|
// SVG rasterization is determined by height (see SVGResource.cpp), and rasterization is done in terms of pixels
|
||||||
|
// if rounding is off enough in the rasterization step (for images with extreme aspect ratios), it can cause cutoff when the aspect ratio breaks
|
||||||
|
// so, we always make sure the resultant height is an integer to make sure cutoff doesn't happen, and scale width from that
|
||||||
|
// (you'll see this scattered throughout the function)
|
||||||
|
// this is probably not the best way, so if you're familiar with this problem and have a better solution, please make a pull request!
|
||||||
|
|
||||||
if(mTargetIsMax)
|
if(mTargetIsMax)
|
||||||
{
|
{
|
||||||
mSize = textureSize;
|
mSize = textureSize;
|
||||||
|
@ -58,27 +66,32 @@ void ImageComponent::resize()
|
||||||
mSize[1] *= resizeScale.y();
|
mSize[1] *= resizeScale.y();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for SVG rasterization, always calculate width from rounded height (see comment above)
|
||||||
|
mSize[1] = round(mSize[1]);
|
||||||
|
mSize[0] = (mSize[1] / textureSize.y()) * textureSize.x();
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
// if both components are set, we just stretch
|
// if both components are set, we just stretch
|
||||||
// if no components are set, we don't resize at all
|
// if no components are set, we don't resize at all
|
||||||
mSize = mTargetSize.isZero() ? textureSize : mTargetSize;
|
mSize = mTargetSize.isZero() ? textureSize : mTargetSize;
|
||||||
|
|
||||||
// if only one component is set, we resize in a way that maintains aspect ratio
|
// if only one component is set, we resize in a way that maintains aspect ratio
|
||||||
|
// for SVG rasterization, we always calculate width from rounded height (see comment above)
|
||||||
if(!mTargetSize.x() && mTargetSize.y())
|
if(!mTargetSize.x() && mTargetSize.y())
|
||||||
{
|
{
|
||||||
mSize[0] = (mTargetSize.y() / textureSize.y()) * textureSize.x();
|
mSize[1] = round(mTargetSize.y());
|
||||||
mSize[1] = mTargetSize.y();
|
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
|
||||||
}else if(mTargetSize.x() && !mTargetSize.y())
|
}else if(mTargetSize.x() && !mTargetSize.y())
|
||||||
{
|
{
|
||||||
mSize[0] = mTargetSize.x();
|
mSize[1] = round((mTargetSize.x() / textureSize.x()) * textureSize.y());
|
||||||
mSize[1] = (mTargetSize.x() / textureSize.x()) * textureSize.y();
|
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SVGResource* svg = dynamic_cast<SVGResource*>(mTexture.get());
|
|
||||||
if(svg)
|
if(svg)
|
||||||
{
|
{
|
||||||
|
// mSize.y() should already be rounded
|
||||||
svg->rasterizeAt((int)round(mSize.x()), (int)round(mSize.y()));
|
svg->rasterizeAt((int)round(mSize.x()), (int)round(mSize.y()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,10 @@ void SVGResource::rasterizeAt(size_t width, size_t height)
|
||||||
mLastHeight = height;
|
mLastHeight = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG(LogInfo) << "Rasterizing \"" << mPath << "\"...";
|
||||||
|
LOG(LogInfo) << " Original width: " << mSVGImage->width << ", original height: " << mSVGImage->height;
|
||||||
|
LOG(LogInfo) << " width: " << width << ", height: " << height << ", scale: " << height / mSVGImage->height;
|
||||||
|
|
||||||
unsigned char* imagePx = (unsigned char*)malloc(width * height * 4);
|
unsigned char* imagePx = (unsigned char*)malloc(width * height * 4);
|
||||||
|
|
||||||
NSVGrasterizer* rast = nsvgCreateRasterizer();
|
NSVGrasterizer* rast = nsvgCreateRasterizer();
|
||||||
|
@ -92,12 +96,12 @@ void SVGResource::rasterizeAt(size_t width, size_t height)
|
||||||
free(imagePx);
|
free(imagePx);
|
||||||
}
|
}
|
||||||
|
|
||||||
Eigen::Vector2i SVGResource::getImageSize() const
|
Eigen::Vector2f SVGResource::getSourceImageSize() const
|
||||||
{
|
{
|
||||||
if(mSVGImage)
|
if(mSVGImage)
|
||||||
return Eigen::Vector2i((int)round(mSVGImage->width), (int)round(mSVGImage->height));
|
return Eigen::Vector2f(mSVGImage->width, mSVGImage->height);
|
||||||
|
|
||||||
return Eigen::Vector2i::Zero();
|
return Eigen::Vector2f::Zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SVGResource::deinitSVG()
|
void SVGResource::deinitSVG()
|
||||||
|
|
|
@ -14,7 +14,7 @@ public:
|
||||||
virtual void initFromMemory(const char* image, size_t length) override;
|
virtual void initFromMemory(const char* image, size_t length) override;
|
||||||
|
|
||||||
void rasterizeAt(size_t width, size_t height);
|
void rasterizeAt(size_t width, size_t height);
|
||||||
Eigen::Vector2i getImageSize() const;
|
Eigen::Vector2f getSourceImageSize() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend TextureResource;
|
friend TextureResource;
|
||||||
|
|
Loading…
Reference in a new issue