0

I'm using a good library on here to handle some large images coming in through the iphone camera in order to avoid the whole subsampling drama here.

My draw code:

function imageLoaded(img, frontCamera) {

    element = document.getElementById("canvas1");
    var mpImg= new MegaPixImage(img);

    // read the width and height of the canvas- scaled down
    width = element.width; //188  94x2
    height = element.height; //125

    //used for side by side comparison of images
    w2 = width / 2;

    // stamp the image on the left of the canvas
    if (frontCamera) {
        mpImg.render(element, {maxWidth:94, maxHeight:125});} else{
        mpImg.render(element, {maxWidth:94, maxHeight:125});}

    //at this point, i want to grab the imageData drawn to the canvas using 
    //MegaPixImage and continue to do some more image processing, which normally
    //would happen by declaring ctx=element.getContext("2d"); 
//more stuff here
}

The image is drawing fine,...but I cannot seem to find a way of then doing image processing on that image subsequently. How would I get a new context after having drawn that image on the canvas?

Maybe I would either have to run further image processing from within that library so I have context access or strip the context drawing out of the library.

Thanks for the help!

Community
  • 1
  • 1
Chaz
  • 233
  • 2
  • 11

1 Answers1

0

I had a similar issue, and actually found a helpful function to detect subsampling and only use MegaPixImage when subsampling was found.

In my case, for local file reading (iPhone camera, in your case), I called a handleFileSelect function when a <input type="file"> value is changed (i.e. when a file is selected to populate this input). Inside this function, I called a general populateImage JS function that draws the image data to the canvas.

Here's the handleFileSelect function and input binding:

$("#my_file_input").bind('change', function (event) {
    handleFileSelect(event);
});
function handleFileSelect(event) {
    var reader,
        tmp,
        file = event.target.files[0];
    try {
        reader = new FileReader();
        reader.onload = function (e) {
            tmp = e.target.result.toString();
            // In my case, some image data (from Androids, mostly) didn't contain necessary image data, so I added it in
            if (tmp.search("image/jpeg") === -1 && tmp.search("data:base64") !== -1) {
                tmp = tmp.replace("data:", "data:image/jpeg;");
            }
            populateImage(tmp);
        };
        reader.onerror = function (err) {
            // Handle error as you need
        };
        reader.readAsDataURL(file);
    } catch (error) {
        // Handle error as you need
    }
}

Then, my populateImage function (called in the reader.onload function above):

function populateImage(imageURL) {
    var tmpImage = new Image();
    $(tmpImage).load(function () {

        var mpImg, mpImgData;

        // If subsampling found, render using MegaPixImage fix, grab image data, and re-populate so we can use non-subsampled image.
        // Note: imageCanvas is my canvas element.
        if (detectSubsampling(this)) {
            mpImg = new MegaPixImage(this);
            mpImg.render(imageCanvas, {maxWidth: 94, maxHeight: 125});
            mpImgData = imageCanvas.toDataURL("image/jpg");
            populateImage(mpImgData);
            return;
        }

        // Insert regular code to draw image to the canvas
        // Note: ctx is my canvas element's context
        ctx.drawImage(tmpImage, 0, 0, 94, 125); // Or whatever x/y/width/height values you need

    });
    $(tmpImage).error(function (event) {
        // Handle error as you need
    });
    tmpImage.src = imageURL;
}

And last but not least, the detectSubsampling function. Note that this method was found from another source and isn't my own.

function detectSubsampling(img) {
    var iw = img.naturalWidth,
        ih = img.naturalHeight,
        ssCanvas,
        ssCTX;
    if (iw * ih > 1024 * 1024) { // Subsampling may happen over megapixel image
        ssCanvas = document.createElement('canvas');
        ssCanvas.width = ssCanvas.height = 1;
        ssCTX = ssCanvas.getContext('2d');
        ssCTX.drawImage(img, -iw + 1, 0);
        // Subsampled image becomes half smaller in rendering size.
        // Check alpha channel value to confirm image is covering edge pixel or not.
        // If alpha value is 0 image is not covering, hence subsampled.
        return ssCTX.getImageData(0, 0, 1, 1).data[3] === 0;
    }
    return false;
}

This may be more than you bargained for, but like I said, I ran into a similar issue and this solution proved to work across all browsers/devices that were canvas supported.

Hope it helps!

Anthony Hessler
  • 1,459
  • 1
  • 11
  • 10
  • Ah thanks! You answered and then some! Appreciate the help. – Chaz May 10 '13 at 20:11
  • Anthony, running into a small snafu I was hoping you could help me out with. Im drawing the megapix image into a canvas element that is 188x125 so that I can process it and draw the processed image on the other half of the canvas element (both images at 94x125 side by side). When I am coming out of the `if(detectSubsampling...` conditional, its resizing the canvas element at 94x125, per `mp.Img.render(imageCanvas, {maxWidth:94, maxHeight:125});`. Know how I can place the mpImg into a canvas that is twice the width of that image? Thanks – Chaz May 15 '13 at 14:25
  • I think you can just make the `maxWidth` value 188. I thought your canvas was 94x125, but if your canvas is 188x125, try setting the maxWidth to 188. In my project code, I have the `maxWidth` and `maxHeight` set to the size of my canvas element, not half of it as you specified. Hope it helps! – Anthony Hessler May 16 '13 at 18:09
  • Yeah it's strange,...I did that and it really messes up the newly drawn image. I'll try some more stuff out. Thanks for the help – Chaz May 17 '13 at 16:15