0

I have a question about images in a canvas.

HTML1: I try to create an image in an canvas (HTML1). After I create the image (in this case some random pixels), I replace my canvas with an image (toDataURL()) and save the image using right-click and "save as"-browser function. I save it as "Download.png" in the same directory as HTML2-file. At the end of my drawImage-function, I make an console.log(img.data); for debugging the image-data (important for my question!).

HTML2: I load the image (Download.png) from HTML1 into my canvas and try to get the image-data again (ctx.getImageData(...)). Now, the data is different from the data in HTML1, but it is the same image. For example: Output HTML1:

[47, 42, 27, 49, 45, 54, 45, 57, 56, 48, 48, 32, 48, 48, 43, 48, 48, 43, 48, 48, 49, 49, 25, 42, 38, 11, 0, 47, 41, 29, 46, 106, 111, 98, 94, 115, 101, 41, 104, 81, 116, 97, 114, 121, 46, 105, 109, 117, 91, 108, 119, 45, 39, 39, 50, 46, 49, 44, 107, 105, 109, 43, 102, 115, 41, 29, 46, 106, 111, 98, 94, 115, 100, 44, 83, 105, 115, 112, 47, 87, 101, 96, 47, 104, 101, 104, 109, 101, 111, 43, 102, 115, 41, 29, 46, 106, 111, 98, 94, 115…]

Output HTML2:

[211, 150, 67, 46, 5, 156, 196, 103, 250, 61, 235, 217, 131, 19, 71, 162, 160, 117, 115, 242, 190, 157, 33, 39, 0, 39, 59, 26, 226, 66, 45, 62, 55, 87, 47, 223, 216, 50, 213, 97, 227, 47, 214, 81, 163, 215, 176, 240, 25, 16, 151, 113, 131, 179, 158, 224, 147, 209, 200, 237, 239, 178, 136, 222, 80, 240, 169, 236, 123, 52, 143, 89, 8, 92, 66, 194, 64, 32, 69, 48, 38, 143, 53, 68, 213, 221, 99, 186, 172, 117, 193, 168, 0, 0, 0, 0, 79, 157, 255, 237…]

Why? Can somebody explain this to me? Why is the image.data different? As far as I have understood it, it should return the same rgba-data as in HTML1-example. How can I fix this behaviour? I want to have exactly the same data.

Thank you in advance!

I have created following testcase and I hope everybody will understand my problem.

HTML1:

    <canvas id="canvas" height="100" width="100"></canvas>
    <script type="text/javascript">

        (function(){


            var canvas = document.getElementById('canvas'),
                ctx = canvas.getContext("2d");

                drawImage(ctx);
                replace_canvas_with_img();


        })();


        function drawImage(ctx) {
            var color = [],
                img = ctx.createImageData(canvas.width,canvas.height);

            for (var i=img.data.length;i--;) {

                //generate random color (rgba)
                for (var c = 4; c--;) {
                    color[c] = ''+Math.floor(Math.random() * (255 - 0 + 1));
                }

                //add random color to image.data;
                for (var ci = color.length; ci--;) {
                    img.data[i+ci] = color[ci];
                }

                color.length = 0;
            }
            ctx.putImageData(img, 0, 0);
            console.log(img.data);

        }               

        function replace_canvas_with_img() {
            document.write('<img src="' + canvas.toDataURL('image/png', 1) + '" />');
            canvas.parentNode.removeChild(canvas);

        }

    </script>

HTML2:

    <canvas id="canvas" height="100" width="100"></canvas>
    <script type="text/javascript">

        (function(){

            var myImg = new Image();
            myImg.src = 'Download.png';
            myImg.onload = function() {
                var canvas = document.getElementById('canvas'), 
                    ctx;

                canvas.width = myImg.width;
                canvas.height = myImg.height;

                ctx = canvas.getContext("2d");
                ctx.drawImage(this, 0,0);

                var imgData = ctx.getImageData(0,0,canvas.width, canvas.height);

                console.log(imgData.data);



            }   

        })();

    </script>
Newbie
  • 1,644
  • 5
  • 29
  • 40
  • in a first time, test with a uniform (single color) image. Beware of the browser cache . – GameAlchemist May 02 '14 at 21:21
  • putImageData can by lossy see this question... http://stackoverflow.com/questions/10912069/html5-getimagedata-then-putimagedata-results-in-fading-image – Charles May 02 '14 at 21:31

1 Answers1

0

The large differences in the two array's in our questions are probably user error. HTML1 was probably refreshed before you compared with the Downloaded png.

You will see small differences in the two array's because of the lossy nature of putPixelData.

See: This SO question and this or the HTML5 Canvas Spec

You can see the small differences clearly if you put the pixel get and get the pixel data in the same HTML file. I.e. add this line to HTML1 after your first console.log statement.

console.log(ctx.getImageData(0,0,canvas.width, canvas.height).data);
Community
  • 1
  • 1
Charles
  • 1,820
  • 13
  • 16
  • Hi Charles, no, I did not refresh HTML1 after image-creation. I saved the image to my disk and opend a new tab with HTML2 (including the image saved from HTML1). But I think you are right - it seems to be the lossy nature of putPixelData. Is there any workaround or do I have to loop over my array for putting all the pixels, one for one, to my canvas? – Newbie May 03 '14 at 07:31
  • If the changes you are seeing are really that large, then something horribly wrong is going on. get/put PixelData should not result in visible changes. You could experiment with other methods, perhaps using drawImage would work? Perhaps you're asking the wrong question, what's the higher level problem you are trying to solve that requires lossless image encoding/decoding? Canvas may not be the right tool for the job. – Charles May 03 '14 at 20:57
  • The images look exactly the same. But I have to read the image.data verifying that it is the same image and if the image.data is different, I can't verify it. – Newbie May 05 '14 at 07:34