Question

I'm trying to test something which I might later use in a more complex application however I'm struggling to find why this following code is not working. I'm not that familiar with javascript however I have noticed that there is no such thing as casting?

I have the following piece of code which in Java if casted should work however in this following script, it doesn't. To be more specific the following error gets returned:

Uncaught TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': No function was found that matched the signature provided. test.html:16
window.onload

Here is the code

        <script>
    window.onload = function(){
        var canvas = document.getElementById("myCanvas");
        var ctx = canvas.getContext("2d");
        var imageObject = ctx.getImageData(0,0,100,200);
        var stringed = JSON.stringify(imageObject);

        var nowShouldBeImage = JSON.parse(stringed);
        ctx.putImageData(nowShouldBeImage,0,0);
    }

    </script>

My question is why is it that the object after being parsed is not getting recognised correctly? What am I missing here? And how would I tackle the lack of this functionality in javascript? ( Maybe not lack of functionality but rather difference from Java)

Was it helpful?

Solution

The JSON object parses files into simple structures.
You're basically getting an array of channel values back, I believe.

.putImageData doesn't work with arrays, but rather with ImageData objects (which may behave like arrays, but are not).

You've got multiple solutions, here, if what you're interested in is sending something to / loading something from the server.

If you want to use XHR, then you can use base64 to go back and forth.

var canvas     = getMyCanvas(),
    ctx        = canvas.getContext("2d"),
    encImgData = canvas.toDataURL();

var img = new Image();
img.src = encImgData;

ctx.drawImage(img, 0, 0);

If you want to go through and manually edit that image's pixel-range thereafter, draw it to an offscreen canvas, .getImageData() to match the width and height of the image you cared about, edit the pixels, and .putImageData() using the edited object.

But JSON isn't going to marshal things into specific types for you.
It takes simple data structures, puts them in strings, and outputs those structures into other simple structures.

You can also write a node-modifying function which will be called as each node in the structure is being rebuilt.
If you specifically want to write a function which checks if the node is an array and it's filled with what you assume are per-channel values, and then use ctx.createImageData, and manually loop through and fill each channel of each pixel with the array value, and then return the constructed ImageData object, you can do that, too, I suppose. But that's not going to do you any favours regarding speed.

OTHER TIPS

  1. Java ≠ Javascript, not use javascript as java.
  2. this step seems useless:

    var stringed = JSON.stringify(imageObject); //object to string
    var nowShouldBeImage = JSON.parse(stringed); //same string to JSON?!?! nothing change... why?!!?
    
  3. remove the useless step:

    var imageObject = ctx.getImageData(0,0,100,200);
    //var stringed = JSON.stringify(imageObject); remove this two line
    //var nowShouldBeImage = JSON.parse(stringed);
    ctx.putImageData(imageObject,0,0);
    

The object nowShouldBeImage isn't the same of imageObject because inside of this object there are some properties that are particular because are the result of getImageData() that after JSON.stringify are lost (nowShouldBeImage is an instance of Object, imageObject is an instance of ImageData)

You are serializing binary data with JSON. If you really need to do that, try encoding the ImageData object from getImageData() as base64 first.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top