ios bug html,HTML5 Canvas drawImage ratio bug iOS

可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):

问题:

I want to resize the image taken from the iOS camera on the client side with HTML5 Canvas but I keep running in this weird bug where the image has a wrong ratio if bigger than ~1.5mb

It works on the desktop but not in the latest iOS version with the media upload API.

You can see an example here: http://jsbin.com/ekuros/1

Any idea how to fix this please? Is this a memory issue? $('#file').on('change', function (e) { var file = e.currentTarget.files[0]; var reader = new FileReader(); reader.onload = function (e) { var image = $('

timg.gif'); 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 = $('

timg.gif'); thumb.attr('src', data); $('body').append(thumb); }); image.attr('src', e.target.result); }; reader.readAsDataURL(file); });

回答1:

There is a JavaScript canvas resize library which works around the subsampling and vertical squash issues encountered when drawing scaled images on canvas on iOS devices: http://github.com/stomita/ios-imagefile-megapixel

There are side issues when scaling images with alpha channel (as it uses the alpha channel for the issues detection) and when trying to resize existing canvas elements, however it's the first solution I've found that actually works with the issue at hand.

stomita is also a StackOverflow user and posted his solution here: https://stackoverflow.com/a/12615436/644048

回答2:

If you still need to use the long version of the drawImage function you can change this: context.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);

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

You just need to include these two functions somewhere: /** * 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 ); }

This will work fine whether it is run on iOS or other platforms.

This is based on the great work by stomita and you should credit him in your work.

回答3:

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.

回答4:

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

回答5:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值