Fix Trim command when top-left corner is non-transparent (fix #1659)

This commit is contained in:
Gaspar Capello 2019-10-11 11:51:28 -03:00 committed by David Capello
parent 536a4c5d3a
commit 695d85e566
2 changed files with 113 additions and 4 deletions

View File

@ -324,11 +324,59 @@ void DocApi::trimSprite(Sprite* sprite, const bool byGrid)
for (frame_t frame(0); frame<sprite->totalFrames(); ++frame) {
render.renderSprite(image, sprite, frame);
// TODO configurable (what color pixel to use as "refpixel",
// here we are using the top-left pixel by default)
gfx::Rect frameBounds;
if (doc::algorithm::shrink_bounds(image, frameBounds, get_pixel(image, 0, 0)))
// Before this fix, we did use the top-left corner pixel by default as "refColor" in
// doc::algorithm::shrink_bounds(image, frameBounds, refColor).
// Now, we are looking for one color whole border (i.e: solid color border)
// searching on the sprite square contour.
//
// If the algorithm finds a transparentColor pixel on border frame,
// automatically "refColor" turns to transparentColor and it goes directly to
// shrink_bounds function.
// If the borders don't contain transparentColor, the algorithm keeps checking:
// It search for a solid color border (top border first), then it checks
// the opposite border (bottom border), then:
// 1- If the opposite border color is equal to the first border,
// this color will be the "refColor".
// 2- If the color of the opposite border is solid, BUT different to the first
// border we have to trigger a dialog, delegating the choise to the user.
// 3- If opposite border contains differents colors, we choose the first border color as
// "refColor".
// 4- It repeat analisys to sprite left and right columns pixels.
// If no border has solid color, trimSprite do nothing.
bool skipTrim = false;
bool analizeMoreBorders = true;
color_t refColor = get_pixel(image, 0, 0);
bool firstBorderIsSolidColor = true;
bool secondBorderIsSolidColor = true;
const color_t probableRefColor1 = refColor;
const color_t probableRefColor2 = get_pixel(image, sprite->width() - 1, sprite->height() - 1);
if (analizeFrameSpritePixels(image, sprite, refColor,
firstBorderIsSolidColor,
secondBorderIsSolidColor, true)) {
// Here, we know that analizeFrameSpritePixels did not find transparent pixels on top and bottom borders.
if (!firstBorderIsSolidColor && secondBorderIsSolidColor)
refColor = probableRefColor2;
else if (firstBorderIsSolidColor && secondBorderIsSolidColor && probableRefColor1 != probableRefColor2) {
// Both border are solids colors but different, so we have to trigger the dialog
skipTrim = true;
analizeMoreBorders = false;
}
if (analizeMoreBorders && analizeFrameSpritePixels(image, sprite, refColor,
firstBorderIsSolidColor,
secondBorderIsSolidColor, false)) {
if (!firstBorderIsSolidColor && secondBorderIsSolidColor)
refColor = probableRefColor2;
else if (firstBorderIsSolidColor && secondBorderIsSolidColor && probableRefColor1 != probableRefColor2)
// Both border are solids colors but different, so we have to trigger the dialog
skipTrim = true;
}
}
if (!skipTrim && doc::algorithm::shrink_bounds(image, frameBounds, refColor))
bounds = bounds.createUnion(frameBounds);
// TODO merge this code with the code in DocExporter::captureSamples()
@ -351,6 +399,61 @@ void DocApi::trimSprite(Sprite* sprite, const bool byGrid)
cropSprite(sprite, bounds);
}
bool DocApi::analizeFrameSpritePixels(Image* image,
const Sprite* sprite,
color_t& refColor,
bool& firstBorderIsSolidColor,
bool& secondBorderIsSolidColor,
bool topBottomLookUp) {
firstBorderIsSolidColor = true;
secondBorderIsSolidColor = true;
int spriteW = sprite->width();
int spriteH = sprite->height();
const color_t probableRefColor1 = get_pixel(image, 0, 0);
const color_t probableRefColor2 = get_pixel(image, spriteW - 1, spriteH - 1);
if (!topBottomLookUp) {
int aux = spriteW;
spriteW = spriteH;
spriteH = aux;
}
color_t currentPixel = 0;
color_t transparentColor = sprite->transparentColor();
if (probableRefColor1 == transparentColor || probableRefColor2 == transparentColor) {
refColor = transparentColor;
return false;
}
for (int i=0; i < spriteW; i++) {
if (topBottomLookUp)
currentPixel = get_pixel(image, i, 0);
else
currentPixel = get_pixel(image, 0, i);
if (currentPixel != probableRefColor1) {
firstBorderIsSolidColor = false;
if (currentPixel == transparentColor) {
refColor = transparentColor;
return false;
}
}
}
for (int i=0; i < spriteW; i++) {
if (topBottomLookUp)
currentPixel = get_pixel(image, i, spriteH - 1);
else
currentPixel = get_pixel(image, spriteH - 1, i);
if (currentPixel != probableRefColor2) {
secondBorderIsSolidColor = false;
if (currentPixel == transparentColor) {
refColor = transparentColor;
return false;
}
}
}
return true;
}
void DocApi::addFrame(Sprite* sprite, frame_t newFrame)
{
copyFrame(sprite, newFrame-1, newFrame,

View File

@ -117,6 +117,12 @@ namespace app {
void setPalette(Sprite* sprite, frame_t frame, const Palette* newPalette);
private:
bool analizeFrameSpritePixels(Image* image,
const Sprite* sprite,
color_t& refColor,
bool& firstBorderIsSolidColor,
bool& secondBorderIsSolidColor,
bool topBottomLookUp);
void cropImageLayer(LayerImage* layer,
const gfx::Rect& bounds,
const bool trimOutside);