IT TIP

HTML5 Canvas drawImage 비율 버그 iOS

itqueen 2021. 1. 7. 20:15
반응형

HTML5 Canvas drawImage 비율 버그 iOS


HTML5 Canvas를 사용하여 클라이언트 측의 iOS 카메라에서 가져온 이미지의 크기를 조정하고 싶지만 ~ 1.5MB보다 크면 이미지 비율이 잘못된이 이상한 버그에서 계속 실행됩니다.

데스크톱에서는 작동하지만 미디어 업로드 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);
});

iOS 장치에서 캔버스에 크기 조정 된 이미지를 그릴 때 발생하는 서브 샘플링 및 수직 스쿼시 문제를 해결하는 JavaScript 캔버스 크기 조정 라이브러리가 있습니다. http://github.com/stomita/ios-imagefile-megapixel

알파 채널을 사용하여 이미지 크기를 조정할 때 (문제 감지를 위해 알파 채널을 사용하기 때문에) 부수적 인 문제가 있지만 기존 캔버스 요소의 크기를 조정하려고 할 때 실제로 문제를 해결하는 첫 번째 해결책입니다.

stomita는 StackOverflow 사용자이기도하며 여기에 솔루션을 게시했습니다. https://stackoverflow.com/a/12615436/644048


drawImage 함수의 긴 버전을 계속 사용해야하는 경우 다음을 변경할 수 있습니다.

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

이에:

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

다음 두 가지 기능을 어딘가에 포함하면됩니다.

/**
 * 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 의 위대한 업적을 기반으로하며 작업 에서 그를 인정해야합니다.


It looks like this is an iOS 6 bug. There is no reason for the aspect to get out of whack from your code. I have the same problem which was only introduced in iOS 6. It seems that their sub-sampling routine gives the wrong height. I submitted a bug report to Apple, and you should do the same. The more bug reports they get for this the better.


I've experienced the same problem. It seems that this is an iOS limitation, jpg over 2 megapixel are subsampled.

See Creating Compatible Web Content for Safari on IPhone


A modified version of the above code.

Edit: saw L0LN1NJ4's code at http://jsfiddle.net/gWY2a/24/ .. guess that one's a bit better...

function drawImageIOSFix (ctx, img) {
 var vertSquashRatio = detectVerticalSquash (img)
 var arg_count = arguments.length
 switch (arg_count) {
  case 4  : ctx.drawImage (img, arguments[2], arguments[3] / vertSquashRatio); break
  case 6  : ctx.drawImage (img, arguments[2], arguments[3], arguments[4], arguments[5] / vertSquashRatio); break
  case 8  : ctx.drawImage (img, arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7] / vertSquashRatio); break
  case 10 : ctx.drawImage (img, arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9] / vertSquashRatio); break
 }

 // Detects 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 (and IOS7) 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, ey = ih, 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
 }
}

ReferenceURL : https://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios

반응형