在canvas上固定ios7压缩图像,旋转和缩放

我遇到了使用canvas在iOS7中被压扁的问题。 我发现以下post似乎正朝着正确的方向前进:

HTML5 Canvas drawImage比率错误iOS

但是,我超越了绘制图像的简单情况,在绘制图像之前,我也在旋转和缩放上下文(对于带有EXIF方向数据的缩略图)。 代码会运行,但缩略图中没有图像数据。 我猜这与canvas旋转和缩放有关。 但是,我很难理解为什么当我的挤压因子是1(在没有错误的iOS设备上)时,缩略图不能正确创build。

这是我的完整的“onload()”代码:

reader.onloadend = function(evt) { console.log('read file data!'); var tempImg = new Image(); console.log('created new Image'); tempImg.src = evt.target.result; console.log('set canvas to file'); // alert(this); tempImg.onload = function() { console.log('loaded tempImg'); var MAX_WIDTH = 450; var MAX_HEIGHT = 450; var tempW = tempImg.width; var tempH = tempImg.height; if (tempW > tempH) { if (tempW > MAX_WIDTH) { tempH *= MAX_WIDTH / tempW; tempW = MAX_WIDTH; } } else { if (tempH > MAX_HEIGHT) { tempW *= MAX_HEIGHT / tempH; tempH = MAX_HEIGHT; } } var canvas = document.createElement('canvas'); canvas.width = tempW; canvas.height = tempH; var ctx = canvas.getContext("2d"); // save the current co-ordinate system // before we screw with it ctx.save(); // move to the middle of where we want to draw our image ctx.translate(tempW/2, tempH/2); if (exifTags.hasOwnProperty('Orientation')) { // EXIF FORMAT: 0x0112 Orientation int16u IFD0 // 1 = Horizontal (normal) // 2 = Mirror horizontal // 3 = Rotate 180 // 4 = Mirror vertical // 5 = Mirror horizontal and rotate 270 CW // 6 = Rotate 90 CW // 7 = Mirror horizontal and rotate 90 CW // 8 = Rotate 270 CW // Working. See: http://creativejs.com/2012/01/day-10-drawing-rotated-images-into-canvas/ if (exifTags.Orientation == 2) { console.log('orientation: 2 = Mirror horizontal') // flip context horizontally // ctx.translate ctx.scale(-1, 1); } else if (exifTags.Orientation == 3) { console.log('orientation: 3 = Rotate 180') ctx.rotate(180*Math.PI/180); } else if (exifTags.Orientation == 4) { console.log('orientation: 4 = Mirror vertical') // flip context vertically ctx.scale(1, -1); } else if (exifTags.Orientation == 5) { console.log('orientation: Mirror horizontal and rotate 270 CW') // flip context horizontally ctx.rotate(270*Math.PI/180); ctx.scale(-1, 1); } else if (exifTags.Orientation == 6) { console.log('orientation: Rotate 90 CW') ctx.rotate(90*Math.PI/180); } else if (exifTags.Orientation == 7) { console.log('orientation: Mirror horizontal and rotate 90 CW') // flip context horizontally ctx.rotate(90*Math.PI/180); ctx.scale(-1, 1); } else if (exifTags.Orientation == 8) { console.log('orientation: Rotate 270 CW') ctx.rotate(270*Math.PI/180); } else { console.log('unknown orientation: ' + exifTags.Orientation); } } var myImage = this; if ($scope.platform == "iOS") { /* 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); console.log('ratio: ' + vertSquashRatio); // 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 ); } console.log('image to unsquish', myImage); // draw it up and to the left by half the width // and height of the image drawImageIOSFix(ctx, myImage, -tempW/2, -tempH/2, tempW, tempH); } else { // draw it up and to the left by half the width // and height of the image ctx.drawImage(myImage, -tempW/2, -tempH/2, tempW, tempH); } // and restore the co-ords to how they were when we began ctx.restore(); var dataURL = canvas.toDataURL(); // alert('created image!'); var fileName = undefined; if ($scope.platform == "iOS") { // Store only the name for iOS, hard paths are unreliable var timestamp = new Date().getTime(); fileName = timestamp.toString().concat('t.jpg'); var thumbPath = fileSystem.root.toURL() + "/STL/" + fileName; var thumbName = "/STL/" + fileName; } else { var name = file.name var position = name.length-4 fileName = name.substr(0, position) + 't.jpg'; var thumbPath = fileSystem.root.toURL() + "/.STL/" + thumbName; var thumbName = fileName; } $scope.mediaCollection.thumbNames.push(thumbName); $scope.mediaCollection.thumbPaths.push(thumbPath); $scope.mediaCollection.exifData.push(exifTags); $scope.mediaCollection.Orientation.push(exifTags.Orientation); canvas.toBlob(function(blob){ console.log(blob.size + ':' + blob.type); function newFile(fileEntry){ console.log('created new fileEntry'); fileEntry.createWriter(gotFileWriter, fail); } function gotFileWriter(writer) { console.log('got fileWriter'); writer.seek(0); // window.location = blobUrl; writer.write(blob); console.log('wrote blob!'); writeIfReady(); } console.log('about to get Directory'); console.log('fileSystem root: ', fileSystem.root, $scope.iOS_FS); console.log('platform: ', $scope.platform); // can replace if/else with single request using $scope.STL_dir if ($scope.platform = "iOS") { // May need maintenance... fileSystem.root.getDirectory('STL', {create: true}, function(dirEntry) { console.log('got directory, about to create thumbnail file: ' + fileName); dirEntry.getFile(fileName, {create: true, exclusive: true}, newFile, fail); }, fail); } else { fileSystem.root.getDirectory('.STL', {create: true}, function(dirEntry) { dirEntry.getFile(fileName, {create: true, exclusive: true}, newFile, fail); }, fail); } }, "image/jpg"); } }