Reparar la image aplastada ios7 en canvas, con rotation y escalado.

Estoy teniendo problemas con imágenes aplastadas en iOS7 usando canvas. Encontré la siguiente publicación que parece estar en la dirección correcta:

HTML5 Lienzo drawImage ratio bug iOS

Sin embargo, estoy más allá del simple caso de dibujar una image, también estoy rotando y escalando el context (para miniaturas con datos de orientación EXIF) antes de dibujar la image. El código se ejecuta, pero no hay datos de image en mis miniaturas. Supongo que esto tiene que ver con la rotation y el escalamiento del canvas. Sin embargo, estoy teniendo dificultades para entender por qué la miniatura no se crea correctamente cuando mi factor Squish es 1 (en un dispositivo iOS que no tiene el error).

Aquí está mi código completo "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 restre the co-ords to how they were when we began ctx.restre(); 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"); } }