Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gamma aware ? resize algo ? #1

Open
Kuranes opened this issue Sep 19, 2012 · 9 comments
Open

Gamma aware ? resize algo ? #1

Kuranes opened this issue Sep 19, 2012 · 9 comments

Comments

@Kuranes
Copy link

Kuranes commented Sep 19, 2012

As many browser doesn't do gamma-aware resize, you might want to do a gamma aware resize by yourself (a matter of converting pixels using a pow(gamma) before & the contrary after resize.

http://filmicgames.com/archives/354
http://www.4p8.com/eric.brasseur/gamma.html

Why not multiple resize algorithms, nearest, cubic, etc...

http://www.codinghorror.com/blog/2007/07/better-image-resizing.html
http://en.wikipedia.org/wiki/Image_scaling
http://en.wikipedia.org/wiki/Lanczos_resampling
or even hqx (in case of pixel art)

@josefrichter
Copy link
Owner

Thanks for that. This was just a proof of concept, but surely implementing better scaling algorithm might be needed sometimes. Thanks for the links, very useful!

p.s. feel free to fork me, add the algorithms, and send the pull request :-)

@josefrichter
Copy link
Owner

btw. I tried Lanczos on this branch https://github.com/josefrichter/resize/tree/lanczos but the results are horrible (chrome on mac)

@Kuranes
Copy link
Author

Kuranes commented Sep 21, 2012

Indeed chrome does have better/clever filters ( read some code there for ideas http://src.chromium.org/svn/trunk/src/skia/ext/convolver.cc http://src.chromium.org/svn/trunk/src/skia/ext/image_operations.cc )

But that's not the case with firefox for example, your Lanczos filter is better. Browser dependant code needed...

Now the problem is that all have the incorrect gamma problem... try 0.5 scale with that image http://www.4p8.com/eric.brasseur/gamma-1.0-or-2.2.png (from eric brasseur link above)

Here's some basic code you can add to the new branch:

var gamma        = 2.2;
var gamma_invert = 1 / gamma;

function imgOrCanvasToLinear(img)
{
    var inputImg, inputCtx, scaledCanvas;
    if (!(img instanceof HTMLCanvasElement)){
        inputImg = document.createElement('canvas');
        inputImg.width = img.width;
        inputImg.height = img.height;
        inputCtx = inputImg.getContext('2d');
        inputCtx.drawImage( img, 0, 0, img.width, img.height, 0, 0, img.width, img.height);
    }
    else{
        inputCtx = inputImg.getContext('2d');
        inputImg = img;
    }
    var inPixels = inputCtx.getImageData(0, 0, inputImg.width, inputImg.height).data;
    // convert it to linear         
    var len = img.height*img.width*4;
    var linearInPixel = {};//new Float32Array(len),
    var gamma        = 2.2

    for (var pix = 0; pix < len; pix++)
    {
        linearInPixel[pix] = Math.pow(inPixels[pix], gamma);
    }
    return { data: linearInPixel, width: img.width, height: img.height, length : len};      
}

function linearToImgCanvas(imgOutPut)
{
    outputCanvas = document.createElement('canvas');
    outputCanvas.width = imgOutPut.width;
    outputCanvas.height = imgOutPut.height;
    var outputCtx = outputCanvas.getContext('2d');
    var outputPixels = outputCtx.getImageData( 0, 0, imgOutPut.width, imgOutPut.height );
    var outputPixelsData = outputPixels.data;

    for( var pix = 0; pix < imgOutPut.length; pix++ ) 
    {
        outputPixels.data[pix] = Math.pow(imgOutPut.data[pix], gamma_invert);
    }
    outputCtx.putImageData( outputPixels, 0, 0 );

    return outputCanvas;
}

Apply "imgOrCanvasToLinear" before the filter (beginning of "thumbnailer")
And "linearToImgCanvas" at the end and get a canvas element with the correct gamma. ("process2")
It should work because your filter code doesn't do clamping to 0,255 or store to uint8
(the settimeout call are strange and slowing down the code... without any real use. why not remove them? )

@josefrichter
Copy link
Owner

Thanks! I added the functions (see updated code) but don't fully understand how to use them. What to pass them and what I am getting back. Therefore not sure where and how exactly to use them. Can you help me with this, please? I tried to put them in based on your instructions, but always getting various errors. Thanks.

@josefrichter
Copy link
Owner

thanks for pull reuqest. still getting 'linearImg is not defined' on line 142 though.

@Kuranes
Copy link
Author

Kuranes commented Sep 21, 2012

s/linearImg/img/
s/max_width/sx/

@Kuranes
Copy link
Author

Kuranes commented Sep 21, 2012

well, let me 5mn, time to test the code locally...

@josefrichter
Copy link
Owner

ok, thanks

@Kuranes
Copy link
Author

Kuranes commented Sep 21, 2012

sorry for the mess, should have known that pure code never work out of the box, always typos hiding everywhere..., the latest should be the one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants