Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
323 views
in Technique[技术] by (71.8m points)

javascript - HTML 5 canvas getImageData from an externally-loaded image

I know it is not possible to do it straightaway due to security reasons. However, I have heard there are some image-hosting websites that allow their images to be used in a similar manner (Google Picasa?). I could be all wrong, but I would like to know if this is true and if so, how can I get image data from such an image.

Thank you in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Yes, there are public hosts that serve images that can be used in canvas’ getImageData

Dropbox is one of them: http://www.dropbox.com

To use those images, you must use the context.crossOrigin=’anonymous’ flag when loading the image:

var image=document.createElement("img");  // Chrome bug prevents var image=new Image();
image.onload=function(){

        // in Chrome+Mozilla you can use context.getImageData

        // but IE still throws the CORS security error

}
image.crossOrigin = "Anonymous";
image.src="www.CrossOriginSite.com/anyImage.png";

One remaining "Gotcha" is that the IE browser still does not honor the crossOrigin flag, so IE still will not let you use these images with getImageData.

Chrome and Mozilla allow getImageData access.

For example...

This Fiddle will succeed when viewed in Chrome or Mozilla, but will still fail in IE:

http://jsfiddle.net/m1erickson/czmms/

Here is code:

<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var canvasCORS=document.getElementById("canvasCORS");
    var ctxCORS=canvasCORS.getContext("2d");
    var canvasAnonymous=document.getElementById("canvasAnonymous");
    var ctxAnonymous=canvasAnonymous.getContext("2d");

    // Using image WITHOUT crossOrigin=anonymous
    // Fails in all browsers
    var externalImage1=document.createElement("img");  // chrome bug prevents new Image();
    externalImage1.onload=function(){
        canvas.width=externalImage1.width;
        canvas.height=externalImage1.height;
        ctx.drawImage(externalImage1,0,0);
        // use getImageData to replace blue with yellow
        var imageData=recolorImage(externalImage1,0,0,255,255,255,0);
        // put the altered data back on the canvas  
        // this will FAIL on a CORS violation
        ctxCORS.putImageData(imageData,0,0);    
    }
    externalImage1.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/colorhouse.png";

    // Using image WITH crossOrigin=anonymous
    // Succeeds in Chrome+Mozilla, Still fails in IE
    var externalImage2=new Image();
    externalImage2.onload=function(){
        canvas.width=externalImage2.width;
        canvas.height=externalImage2.height;
        ctx.drawImage(externalImage2,0,0);
        // use getImageData to replace blue with yellow
        var imageData=recolorImage(externalImage2,0,0,255,255,255,0);
        // put the altered data back on the canvas  
        // this will FAIL on a CORS violation
        ctxAnonymous.putImageData(imageData,0,0);    
    }
    externalImage2.crossOrigin = "Anonymous";
    externalImage2.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/colorhouse.png";


    function recolorImage(img,oldRed,oldGreen,oldBlue,newRed,newGreen,newBlue){
        var c = document.createElement('canvas');
        var ctx=c.getContext("2d");
        var w = img.width;
        var h = img.height;
        c.width = w;
        c.height = h;

        // draw the image on the temporary canvas
        ctx.drawImage(img, 0, 0, w, h);

        // pull the entire image into an array of pixel data
        var imageData = ctx.getImageData(0, 0, w, h);

        // examine every pixel, 
        // change any old rgb to the new-rgb
        for (var i=0;i<imageData.data.length;i+=4)
          {
              // is this pixel the old rgb?
              if(imageData.data[i]==oldRed &&
                 imageData.data[i+1]==oldGreen &&
                 imageData.data[i+2]==oldBlue
              ){
                  // change to your new rgb
                  imageData.data[i]=newRed;
                  imageData.data[i+1]=newGreen;
                  imageData.data[i+2]=newBlue;
              }
          }
        return(imageData);
    }


}); // end $(function(){});
</script>

</head>

<body>
    <p>Original external image</p>
    <canvas id="canvas" width=140 height=140></canvas>
    <p>.getImageData with .crossOrigin='anonymous'
    <p>[Succeeds in Chrome+Mozilla, still fails in IE]</p>
    <canvas id="canvasAnonymous" width=140 height=140></canvas>
    <p>.getImageData without .crossOrigin='anonymous'
    <p>[Fails on all browsers]</p>
    <canvas id="canvasCORS" width=140 height=140></canvas>
</body>
</html>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...