PhantomAppDevelopment/icon-generator

aliased icons

Closed this issue · 13 comments

Hi, I just tested the app, very nice an easy to use but I think it would be better to enable smoothing when scaling the icon.
I use a 1024x1024 icon as source and all smaller icons are aliased, I think smoothing would fix this.
Or maybe add a checkbox to choose smoothing option ?

Greetings,

Thank you for reporting this issue.

I have uploaded a new build of this app at: http://phantom.im/apps/IconGenerator.air

This build creates the PNG's with smoothing and high quality anti-aliasing.

Please test this build and report back if it fixed the issue.

Hi,

great I think it's much better :)

this app is great, it would be very nice to have also the support for the app screenshots ;-)

One more thing to say, for sizes below or equals to 120px, the icon start to be blurry. I tried with a bicubic interpolation and the results are a little betters for these sizes. Have a look, on the right generated image with your app, and on the left generated image with bicubic interpolation, you will see on smaller size the result is a little less blurry:

image

Here is the script I used for bicubic interpolation:

/**
 * Resize an Image with bicubic interpolation
 * @param width the new desired width
 * @param height the new desired height
 * @param bitmapData the original sized BitmapData
 * @return
 */
public function interpolateBicubic( width:int, height:int, bitmapData:BitmapData ):BitmapData
{
    // same size no need to resize
    if( width == bitmapData.width && height == bitmapData.height )
    {
        return bitmapData.clone();
    }

    var interpolated    :BitmapData = new BitmapData( width, height, true, 0x00000000 );
    var original_copy   :BitmapData = bitmapData.clone();

    var xFactor:Number = bitmapData.width / interpolated.width;
    var yFactor:Number = bitmapData.height / interpolated.height;

    if (xFactor > 1 || yFactor > 1)
        original_copy.applyFilter(original_copy, original_copy.rect, new Point(0, 0), new BlurFilter(1.4*(xFactor/2),1.4*(yFactor/2),BitmapFilterQuality.HIGH));

    var step:int = 0;
    while ( step < interpolated.width )
    {
        for (var y:int = 0; y < interpolated.height; y++){
            interpolated.setPixel32(step, y, getPixelBicubic32(step * xFactor, y * yFactor, original_copy));
        }
        step++;
    }

    return interpolated;
}

private function getPixelBicubic32( x:Number, y:Number, bitmapData:BitmapData ):Number
{
    var i:int = int(x);
    var j:int = int(y);

    if (((i - 1) < 0) || ((j - 1) < 0))
        return bitmapData.getPixel32(i, j);
    else if (((i + 1) >= bitmapData.width) || ((i + 2) >= bitmapData.width) ||
            ((j + 1) >= bitmapData.height) || ((j + 2) >= bitmapData.height))
        return bitmapData.getPixel32(i, j);

    var dx  :Number = x - i;
    var dy  :Number = y - j;
    var asum:Number = 0;
    var rsum:Number = 0;
    var gsum:Number = 0;
    var bsum:Number = 0;

    var Rmdx:Array = new Array(4);
    var Rdyn:Array = new Array(4);
    for( var m:int = -1; m <= 2; ++m )
        Rmdx[m + 1] = A(m - dx);
    for( var n:int = -1; n <= 2; ++n )
        Rdyn[n + 1] = A(dy - n);

    for( m = -1; m <= 2; ++m )
    {
        for (n = -1; n <= 2; ++n)
        {
            var rgb :int = bitmapData.getPixel32(i + m, j + n);
            var a   :int = (rgb >> 24) & 0x0FF;
            var r   :int = (rgb >> 16) & 0x0FF;
            var g   :int = (rgb >>  8) & 0x0FF;
            var b   :int = (rgb >>  0) & 0x0FF;

            var Rres:Number = Rmdx[m + 1] * Rdyn[n + 1];
            asum += a * Rres;
            rsum += r * Rres;
            gsum += g * Rres;
            bsum += b * Rres;
        }
    }

    var alpha:int = (int)(asum + 0.5);
    if(alpha < 0)
        alpha = 0;
    else if(alpha > 255)
        alpha = 255;

    var red:int = (int)(rsum + 0.5);
    if(red < 0)
        red = 0;
    else if(red > 255)
        red = 255;

    var green:int = (int)(gsum + 0.5);
    if(green < 0)
        green = 0;
    else if(green > 255)
        green = 255;

    var blue:int = (int)(bsum + 0.5);
    if(blue < 0)
        blue = 0;
    else if(blue > 255)
        blue = 255;

    return (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
}

private static function A( x:Number ):Number
{
    var p0:Number = ((x + 2) > 0) ? (x + 2) : 0;
    var p1:Number = ((x + 1) > 0) ? (x + 1) : 0;
    var p2:Number = (x > 0) ? x : 0;
    var p3:Number = ((x - 1) > 0) ? (x - 1) : 0;

    return (1 / 6) * (p0 * p0 * p0 - 4 * (p1 * p1 * p1) + 6 * (p2 * p2 * p2) - 4 * (p3 * p3 * p3));
}

@binouze Thank you very much for your in-depth comment. I will be trying this approach as well with another PNGEncoder. I plan to create a new release this weekend.

@pitanello Thanks for the idea! Do you need the app to take screenshots from ADL or only scale them (like the launch images)?

I was thinking about feeding the app with already made screenshots and let it scale in different resolutions.

@pitanello Sure, I will research what sizes are needed and add it to next version.

@binouze Hi, I have been testing with different combinations and I think I found out the best results, you can test it in this link:

http://phantom.im/apps/IconGenerator2.air

Btw, using StageQuality.BEST caused the blurry effect. I have removed that and used another encoder, you can see the new changes in the latest commit.

Hi, the result is better than before but I think the bicubic interpolation is still better (for my icon) ;)
untitled-1

NOTE:
PNG is a lossless format so i don't think changing the PNGEncoder will change the result output

Maybe adding a parameter for choosing the scaling interpolation method ? (like in Photoshop when you make a resize)

Thanks for testing it. I will use your code instead and release a new build afterwards.

It's my first time working with graphics stuff (I'm more of a RPC dev), I really appreciate your input.

Happy to help,
I have made an "app" to make the icons for my games but I did it fast, all params are hard coded and I always have to modify them to generate the icons.

It's nice to see people that take time to built nice util tools like this ;)

Hi,

I have added the Bicubic Interpolation option in the new release.
I noticed when using it, it takes a bit longer to generate the icons, so it's turned off by default, but can easily be turned on in the Settings screen.

While testing it with the Launch Images it took a very long time to generate them, so I'm using the default algorithm for those.

OK, good thing to let the user decides to activate it.
Thanks