我想用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);
});
答案 0 :(得分:54)
如果你仍然需要使用长版本的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的出色工作,你应该相信他的工作。
答案 1 :(得分:30)
有一个JavaScript画布调整大小库,可以解决在iOS设备上在画布上绘制缩放图像时遇到的子采样和垂直壁球问题: http://github.com/stomita/ios-imagefile-megapixel
在使用Alpha通道缩放图像时(因为它使用alpha通道进行问题检测)和尝试调整现有画布元素的大小时,存在一些副作用,但是这是我发现的第一个解决方案手。
stomita也是StackOverflow用户,并在此处发布了他的解决方案: https://stackoverflow.com/a/12615436/644048
答案 2 :(得分:6)
看起来这是iOS 6的错误。这方面没有理由从你的代码中解脱出来。我有同样的问题,只在iOS 6中引入。似乎他们的子采样例程给出了错误的高度。我向Apple提交了一份错误报告,您应该这样做。他们获得的bug报告越多越好。
答案 3 :(得分:2)
我遇到了同样的问题。这似乎是iOS限制,超过200万像素的jpg是二次采样。
答案 4 :(得分:-1)
上述代码的修改版本。
编辑:在http://jsfiddle.net/gWY2a/24/看到了L0LN1NJ4的代码..猜一个好一点......
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
}
}