Соотношение Canvas в HTML5 метода drawImage уязвимость iOS
Я хочу изменить размер изображения, взятого с камеры iOS на стороне клиента с помощью HTML5 Canvas, но я продолжаю работать в этой странной ошибке, где изображение имеет неправильное соотношение, если оно больше ~1,5 Мб
Он работает на рабочем столе, но не в последней версии iOS с API загрузки мультимедиа.
вы можете увидеть пример здесь: 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);
});
5 ответов:
существует библиотека изменения размера JavaScript canvas, которая работает вокруг подвыборки и вертикальных проблем сквоша, возникающих при рисовании масштабированных изображений на холсте на устройствах iOS: 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 и вы должны отдать ему должное в своей работе.
похоже, что это ошибка iOS 6. Нет никаких причин для того, чтобы аспект вышел из строя из вашего кода. У меня есть та же проблема, которая была введена только в iOS 6. Похоже, что их подпрограмма подсчета дает неправильную высоту. Я отправил отчет об ошибке в Apple, и вы должны сделать то же самое. Чем больше сообщений об ошибках они получают для этого, тем лучше.
Я испытал ту же проблему. Кажется, что это ограничение iOS, jpg более 2 мегапикселей являются подвыборкой.
посмотреть создание совместимого веб-контента для Safari на IPhone
измененная версия приведенного выше кода.
Edit: увидел код 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 } }
Comments