55

HTML5 Canvas を使用してクライアント側の iOS カメラから取得した画像のサイズを変更したいのですが、1.5 MB を超えると画像の比率が間違っているという奇妙なバグが発生し続けます。

デスクトップでは動作しますが、メディア アップロード API を使用する最新の iOS バージョンでは動作しません。

ここで例を見ることができます: http://jsbin.com/ekuros/1

これを修正する方法はありますか?これはメモリの問題ですか?

$('#file').on('change', function (e) {
    var file = e.currentTarget.files[0];
    var reader = new FileReader();
    reader.onload = function (e) {
        var image = $('<img/>');
        image.on('load', function () {
            var square = 320;
            var canvas = document.createElement('canvas');

            canvas.width = square;
            canvas.height = square;

            var context = canvas.getContext('2d');
            context.clearRect(0, 0, square, square);
            var imageWidth;
            var imageHeight;
            var offsetX = 0;
            var offsetY = 0;

            if (this.width > this.height) {
                imageWidth = Math.round(square * this.width / this.height);
                imageHeight = square;
                offsetX = - Math.round((imageWidth - square) / 2);
            } else {
                imageHeight = Math.round(square * this.height / this.width);
                imageWidth = square;    
                offsetY = - Math.round((imageHeight - square) / 2);            
            }

            context.drawImage(this, offsetX, offsetY, imageWidth, imageHeight);
            var data = canvas.toDataURL('image/jpeg');

            var thumb = $('<img/>');
            thumb.attr('src', data);
            $('body').append(thumb);
        });
        image.attr('src', e.target.result);
    };
    reader.readAsDataURL(file);
});
4

5 に答える 5

54

drawImage 関数の長いバージョンを使用する必要がある場合は、これを変更できます。

context.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);

これに:

drawImageIOSFix(context, img, sx, sy, sw, sh, dx, dy, dw, dh);

次の 2 つの関数をどこかに含める必要があります。

/**
 * Detecting vertical squash in loaded image.
 * Fixes a bug which squash image vertically while drawing into canvas for some images.
 * This is a bug in iOS6 devices. This function from https://github.com/stomita/ios-imagefile-megapixel
 * 
 */
function detectVerticalSquash(img) {
    var iw = img.naturalWidth, ih = img.naturalHeight;
    var canvas = document.createElement('canvas');
    canvas.width = 1;
    canvas.height = ih;
    var ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0);
    var data = ctx.getImageData(0, 0, 1, ih).data;
    // search image edge pixel position in case it is squashed vertically.
    var sy = 0;
    var ey = ih;
    var py = ih;
    while (py > sy) {
        var alpha = data[(py - 1) * 4 + 3];
        if (alpha === 0) {
            ey = py;
        } else {
            sy = py;
        }
        py = (ey + sy) >> 1;
    }
    var ratio = (py / ih);
    return (ratio===0)?1:ratio;
}

/**
 * A replacement for context.drawImage
 * (args are for source and destination).
 */
function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
    var vertSquashRatio = detectVerticalSquash(img);
 // Works only if whole image is displayed:
 // ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
 // The following works correct also when only a part of the image is displayed:
    ctx.drawImage(img, sx * vertSquashRatio, sy * vertSquashRatio, 
                       sw * vertSquashRatio, sh * vertSquashRatio, 
                       dx, dy, dw, dh );
}

これは、iOS またはその他のプラットフォームで実行されているかどうかに関係なく、正常に機能します。

これは、 stomitaによる偉大な作品に基づいており、あなたの作品に彼の功績を認めるべきです。

于 2013-06-13T11:49:18.200 に答える
30

iOS デバイスのキャンバスにスケーリングされた画像を描画するときに発生するサブサンプリングと垂直スカッシュの問題を回避する JavaScript キャンバス サイズ変更ライブラリがあります: http://github.com/stomita/ios-imagefile-megapixel

アルファ チャネルを使用して画像をスケーリングするとき (問題の検出にアルファ チャネルを使用するため)、および既存のキャンバス要素のサイズを変更しようとするときに副次的な問題がありますが、実際に目前の問題で機能することがわかった最初の解決策です。

stomita も StackOverflow ユーザーであり、彼のソリューションをここに投稿しました: https://stackoverflow.com/a/12615436/644048

于 2012-10-10T09:46:07.213 に答える
6

これはiOS6のバグのようです。アスペクトがコードから抜け出す理由はありません。iOS 6でのみ発生した同じ問題があります。それらのサブサンプリングルーチンでは、高さが間違っているようです。私はAppleにバグレポートを提出しました、そしてあなたは同じことをするべきです。彼らがこれについて得るバグレポートが多ければ多いほど良い。

于 2012-09-26T17:45:35.063 に答える
2

私は同じ問題を経験しました。これは iOS の制限のようで、2 メガピクセルを超える jpg はサブサンプリングされます。

IPhone の Safari と互換性のある Web コンテンツの作成を参照してください。

于 2012-09-23T09:13:55.260 に答える