Open GoogleCodeExporter opened 8 years ago
RotSprite does look useful.
Not so sure about scaling algorithms as they tend to produce antialiased
results.
Original comment by ilija.melentijevic
on 4 Dec 2010 at 11:36
I was studying this (again) recently. RotSprite would indeed be a very valuable
addition, either as a Lua script or a replacement of the current brush rotate
tool.
But the program is closed-source, and even with the author's explaination
(http://forums.sonicretro.org/index.php?showtopic=8848&st=15&p=159754&#entry1597
54) I haven't made much progress.
Original comment by yrizoud
on 4 Dec 2010 at 2:35
I was talking with him on Pixelation forums, and this is what he said. Hope it
helps, yrizoud.
Hi. I saw your post here. Just wanted to let you know that I'm willing to
provide help on this. I won't show the source (honestly, it wouldn't help you
much anyway) but let me know if you have any specific questions or any code of
your own that you want me to review.
I believe the only part I left unspecified in my description of the algorithm
was how exactly the enlargement was performed, i.e. I didn't explain what I
meant by two colors being "more similar" to each other. You probably found
something reasonable already (maybe it's better, for all I know), but in case
you're looking to reproduce what I did, here's how that part worked:
Code:
// rotsprite 2x enlargement algorithm:
// suppose we are looking at input pixel cE which is surrounded by 8 other
pixels:
// cA cB cC
// cD cE cF
// cG cH cI
// and for that 1 input pixel cE we want to output 4 pixels oA, oB, oC, and oD:
// oA oB
// oC oD
// this is the operation performed per pixel:
{
// I find that this simple measurement of color distance gives better results for sprites than other fancier methods like luminosity comparison
#define distance(c1, c2) (((c1)==(c2)) ? 0 : abs((c1).red - (c2).red) + abs((c1).green - (c2).green) + abs((c1).blue - (c2).blue))
// the "similar" macro checks to see if two colors are less different from each other than either is from the current reference color
#define similar(c1,c2) ((c1)==(c2) || (distance(c1,c2) <= distance(cE,c2) && distance(c1,c2) <= distance(cE,c1)))
#define different(c1,c2) (!similar(c1,c2))
if (different(cD,cF)
&& different(cH,cB)
&& ((similar(cE,cD) || similar(cE,cH) || similar(cE,cF) || similar(cE,cB) ||
((different(cA,cI) || similar(cE,cG) || similar(cE,cC)) &&
(different(cG,cC) || similar(cE,cA) || similar(cE,cI))))))
{
oA = ((similar(cB,cD) && ((different(cE,cA) || different(cB,bakcol)) && (different(cE,cA) || different(cE,cI) || different(cB,cC) || different(cD,cG)))) ? cB : cE);
oB = ((similar(cF,cB) && ((different(cE,cC) || different(cF,bakcol)) && (different(cE,cC) || different(cE,cG) || different(cF,cI) || different(cB,cA)))) ? cF : cE);
oC = ((similar(cD,cH) && ((different(cE,cG) || different(cD,bakcol)) && (different(cE,cG) || different(cE,cC) || different(cD,cA) || different(cH,cI)))) ? cD : cE);
oD = ((similar(cH,cF) && ((different(cE,cI) || different(cH,bakcol)) && (different(cE,cI) || different(cE,cA) || different(cH,cG) || different(cF,cC)))) ? cH : cE);
}
else
{
oA = cE;
oB = cE;
oC = cE;
oD = cE;
}
}
Also, for the code you're writing, keep in mind that "scale" should be an input
parameter in addition to the "angle" (e.g. scale by targetScale/8 instead of
1/8). This is because the user might want to rotate and scale something, and
letting the algorithm do both of those things simultaneously gives much
higher-quality results than doing them separately (because it's a single lossy
operation instead of two consecutive lossy operations). Occasionally the only
way to make a sprite look good rotated is to scale it up slightly too... plus
the scaling is actually pretty good on its own (I often use it just to scale a
sprite 1.25x without any rotation, for example).
And one trick about actually using this algorithm: there is always a little bit
of touch-up work required, but the algorithm is chaotic enough that sometimes
changing the rotation angle a tiny amount (like 0.1 degrees) gives a
better-looking result. So when I need a really clean looking result at a single
angle (even if that angle is 0 degrees!) what I do is batch export 16 or so
variants between -0.1 and 0.1 degrees from that angle and then choose the one
that looks least-weird as a starting point, instead of trying to use the first
thing that comes out. It's occurred to me to try getting the algorithm to do
this automatically too, but I doubt I would be able to code up a good-enough
definition of "least-weird" for that to be useful.
Original comment by 00a...@gmail.com
on 4 Dec 2010 at 9:13
scale2x and rotsprite doesn't add extra colors, so there's no antialiasing.
2xSAI and Eagle do that, so they are less practical for us.
Rotate+scale may be good, but not sure about the UI for that...
Original comment by pulkoma...@gmail.com
on 8 Dec 2010 at 7:16
I'm very tempted to implement RotSprite as the new default for "Rotate brush"
tool. The upscaling is only a one-time cost (when you select the tool) and then
you can "try" as many angles as you want and the rotation will be as fast as
before. The current rotation algorithm is already able to upscale/downscale at
no cost, the only limitation is that the 4 corners of the rotated image are
"snapped" to the center of their target pixels. For very small images, this
limitation means that you can't tweak the rotation super-finely. I can't fix
this because the current code is completely foreign to me.
Rotscale requires 80 times more memory as normal rotation (during upscaling
from 4x to 8x : 4x4+8*8) If this is a problem, we can put safety limits that
automatically limit the upscaling to x4 or x2 or even x1.
Original comment by yrizoud
on 10 Dec 2010 at 6:20
Here's attached a Lua script that performs Scale2x rotation (on current brush).
Works pretty well.
Original comment by yrizoud
on 10 Dec 2010 at 11:09
Attachments:
Awesome, thanks, gonna try this this weekend :)
Original comment by eh...@gmx.de
on 11 Dec 2010 at 9:14
Original comment by pulkoma...@gmail.com
on 20 Jan 2011 at 8:58
Original comment by pulkoma...@gmail.com
on 10 Apr 2011 at 8:43
Arbitering issues that make it to v2.4
Original comment by yrizoud
on 8 Mar 2012 at 7:18
Original issue reported on code.google.com by
eh...@gmx.de
on 12 Sep 2010 at 5:19