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); }); 

有一个JavaScriptcanvas大小调整库,它在iOS设备的canvas上绘制缩放图像时遇到的subsampling和vertical squash问题: http : //github.com/stomita/ios-imagefile-megapixel

当使用alpha通道缩放图像时(因为它使用Alpha通道进行问题检测),以及在尝试调整现有的canvas元素的大小时,存在侧面的问题,但是,这是我发现的第一个解决scheme,实际上可以解决手头的问题。

stomita也是一个StackOverflow用户,并张贴他的解决scheme在这里: 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的伟大工作,你应该在他的工作中信任他。

看起来这是一个iOS 6的错误。 这个方面没有任何理由从你的代码中解脱出来。 我有同样的问题,这只是在iOS 6中引入的。似乎他们的子采样例程给出了错误的高度。 我向苹果提交了一个错误报告,你也应该这样做。 他们得到的错误报告越多越好。

我遇到了同样的问题。 看来,这是一个iOS的限制,jpg超过200万像素二次采样。

请参阅在iPhone上为Safari创build兼容的Web内容

上述代码的修改版本。

编辑:看到L0LN1NJ4的代码在http://jsfiddle.net/gWY2a/24/ ..猜测,一个更好一点…

 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 } }