1

I'm working on a Webworks app where I need to resize an image for upload to a server. I'm using JQuery Mobile, the app needs to run on OS6 and up. The user can either use the camera or select an image off the device. The relevant code is as follows:

function handleOpenedFile(fullPath, blobData) {
            var image = new Image();
            image.src = fullPath; //path to image
            image.onload = function () {
                var resized = resizeMe(image); // send it to canvas
                //Do stuff with the DataURL returned from resizeMe()
            };
    }

function resizeMe(img) {

        var canvas = document.createElement('canvas');
        var width = Math.round(img.width / 2);
        var height = Math.round(img.height / 2);
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0, width, height);
        return canvas.toDataURL("image/jpeg", 0.8);
    }

I then use the Base64 in the DataURL for uploading to the server. The images get scaled but they come out garbled. Parts of the image are shifted around and colours come out strange. It's not the scaling per se that messes up the image as it comes out garbled if you draw it on the canvas without any scaling.

I've searched both SO and the BB Dev forums extensively with no luck.

Does anyone have any idea how to fix this or have an alternative suggestion for resizing an image for upload?

Iyashu5040
  • 49
  • 1
  • 7
  • Man, oh man. This issue was a nasty one for me. iOS 6 came out last fall, adding the ability to capture from the camera/camera roll. I also had the need to resize with a Canvas. Canvas resizing was causing severe problems when performing resizing / rotations. Check out this post: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios. In the end, I wrote a small library that fixed the issues, similar to this (but before this came out): https://github.com/stomita/ios-imagefile-megapixel. – p e p Jul 19 '13 at 18:25
  • Sorry, laptop died before I could submit my much more relevant comment. On iOS, the issue was only happening due to subsampling on large images. A quick google search shows that on blackberry, at least one person had some issues with large images http://supportforums.blackberry.com/t5/Web-and-WebWorks-Development/Problem-JavaScript-amp-Canvas-cannot-process-Large-Images-gt/td-p/2128847. You could download a small image (say 100 x 100 px) onto your device, select that image, and see if that is having the same issues. – p e p Jul 19 '13 at 18:45
  • Thank you for your suggestions, I looked at that BB forums thread, and tried out that megapixel library with no success. I've answered my own question with the solution I found. – Iyashu5040 Jul 22 '13 at 09:59
  • Awesome, glad you found your solution. These issues seem to have odd solutions on iOS as well.. and on Android we are seeing problems with toDataURL not consistently including the MIME type in the Data URL. It would be so great if they all just worked like they are supposed to :) – p e p Jul 22 '13 at 19:07

2 Answers2

1

I've managed to solve the problem although why it works eludes me. Simply replace

return canvas.toDataURL("image/jpeg", 0.8);

with

return canvas.toDataURL();

This returns a base64 encoded string with the properly resized image without any strange visual artifacts.

Iyashu5040
  • 49
  • 1
  • 7
0

Cannot help with JQuery mobile, apps running on OS6 or using Base64 in the DataURL for uploading to a server but your code for the function resizeMe does not place the canvas in the HTML document anywhere.

Required line added below.

function resizeMe(img) {

    var canvas = document.createElement('canvas');
    var width = Math.round(img.width / 2);
    var height = Math.round(img.height / 2);
    canvas.width = width;
    canvas.height = height;
    var ctx = canvas.getContext("2d");
    document.body.appendChild(canvas);   //append canvas child to body <<<<-----------
    ctx.drawImage(img, 0, 0, width, height);
    return canvas.toDataURL("image/jpeg", 0.8);
}

If this extra line is missed out in the jsfiddle below you get no image at all, with it you get a scaled image properly formed. The fiddle works on my andriod smart phone.

http://jsfiddle.net/FeALQ/

jing3142
  • 1,821
  • 1
  • 11
  • 16
  • I never actually want to display the image, I simply use the canvas to make the image smaller to minimize data costs when uploading it. Will give it a try though and let you know what happens. – Iyashu5040 Jul 22 '13 at 06:41
  • Thank you for your suggestion jing, it helped me realize that the toDataURL method was the culprit in this situation. Would upvote if I could :) – Iyashu5040 Jul 22 '13 at 09:57