cneeds
cneeds

Reputation: 319

is it possible to gather several image layers into one canvas?

i have a div with several images fixed in position that i want to put into a single canvas so that i can save the composite picture. is this possible?

i read through the canvas tutorial at w3schools and i checked out the API with MDN and came up with the following code that does nothing...

<div id="pics" >
<img id="i1" class="images"
src="http://chris.chrisjneeds.com/images/stars/stars01.jpg" width="300" height="277" style="position: fixed;">
<img id="i2" class="images" 
src="http://chris.chrisjneeds.com/images/ships/ships26.png" width="300" height="277" style="position: fixed;">
</div>

<canvas id="myCanvas" width="250" height="300"
style="border:1px solid #d3d3d3; horizontal-align: right; float: right">
Your browser does not support the HTML5 canvas tag.</canvas>

<script>
function myCanvas() {
var aImages = document.getElementsByClassName('images'),
      nImgsLen = aImages.length;
var oCanvas = document.getElementById("myCanvas");
var oCtx = oCanvas.getContext("2d");

for (var oImgData, nImgId = 0; nImgId < nImgsLen; nImgId++) {
  oImgData = oCtx.getImageData(0, 0, 300, 277); 
  oCtx.putImageData(oImgData, 0, 0);
}
var img=new Image();
img.src = oCanvas.toDataURL();
oCtx.drawImage(img,10,10);

}

i'm expecting the composite image in the canvas but so far i don't get anything. please help

Upvotes: 1

Views: 294

Answers (2)

cneeds
cneeds

Reputation: 319

the second part of my question is "so that i can save the composite picture"

this is what i found from HOW TO SAVE AN IMAGE TO DISK FROM A CANVAS

here is the complete code (i hope it helps someone)

function getImgs4Canvas() {
    var aImages=$("#cloneimages img");
    var oCanvas = document.getElementById("imgCanvas");
    var oCtx = oCanvas.getContext("2d");
    for (var oimg of aImages) {
        oCtx.drawImage(oimg, 0, 0, oimg.width, oimg.height);
    }
    var jpgFile = oCanvas.toDataURL('image/jpeg', 1.0);
    // save the image as a jpg 'blob' in the user's download (default) directoy
    ImageSaver.download_data_uri(jpgFile, "downloadimgtest");
}

var ImageSaver = {
    // function to force-download from a data uri as a filename
    // NB the download="filename" attribute isn't yet supported by safari
    download_data_uri: function(dataURI, fileName) {
        var tempUrl = ImageSaver.make_url_from_data(dataURI);
        var link = $('<a href="' + tempUrl + '" id="download" download="' + fileName + '" target="_blank"> </a>');
        $("body").append(link);
        $("#download").get(0).click();
    },

    // function to generate a temporary browser index url for a datauri
    // if a data-uri is larger than 2mb, chrome's address bar can't handle it.
    // fortunately, you can blob it and then use a temporary blob url
    make_url_from_data: function(dataURI) {
        var blob = ImageSaver.make_blob(dataURI);
        var tempUrl = URL.createObjectURL(blob);
        return tempUrl;
    },

    // function to convert a datauri to a blob
    // Blobs are temporary data structures that can hold binary data, and make that data accessible through a short url. They can probably do other things too; I have no idea.
    make_blob: function(dataURI) {
        // convert base64 to raw binary data held in a string
        // doesn't handle URLEncoded DataURIs
        var byteString;
        if (dataURI.split(',')[0].indexOf('base64') >= 0)
            byteString = atob(dataURI.split(',')[1]);
        else
            byteString = unescape(dataURI.split(',')[1]);
        // separate out the mime component
        var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

        // write the bytes of the string to an ArrayBuffer
        var ab = new ArrayBuffer(byteString.length);
        var ia = new Uint8Array(ab);
        for (var i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        };

        // write the ArrayBuffer to a blob, and you're done
        return new Blob([ab], {
            type: mimeString
        });
    }
}

Upvotes: 0

hindmost
hindmost

Reputation: 7195

Sure, it is possible, but not that way like in your code.

getImageData/putImageData methods are intended for pixel manipulation and absolutely useless for your problem. Your code just copies an area of just created canvas into itself (i.e. does nothing). But what you actually need is draw your images one by one onto the canvas using drawImage method. Also note that you don't need to use toDataURL method (it's mostly used for images sending/saving) cause you with drawImage calls you'll already have needed composite image in the canvas.

So your code should look like this:

...
var aImages = document.getElementsByClassName('images');
var oCanvas = document.getElementById("myCanvas");
var oCtx = oCanvas.getContext("2d");
for (var img of aImages) {
  oCtx.drawImage(img, 0, 0, img.width, img.height);
}

Upvotes: 2

Related Questions