Fixing the ios7 squished image in canvas, with rotation and scaling

匆匆过客 提交于 2019-12-22 10:27:46

问题


I am having problems with images being squished in iOS7 using canvas. I have found the following post which seems to be headed in the right direction:

HTML5 Canvas drawImage ratio bug iOS

However, I am beyond the simple case of drawing an image, I am also rotating and scaling the context (for thumbnails with EXIF orientation data) before drawing the image. The code runs, but there is no image data in my thumbnails. I'm guessing this has to do with the canvas rotation and scaling. However, I'm having a hard time understanding why the thumbnail does not create properly when my squish factor is 1 (on an iOS device that does not have the bug).

Here is my full "onload()" code:

        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");

            }
          }

来源:https://stackoverflow.com/questions/26130560/fixing-the-ios7-squished-image-in-canvas-with-rotation-and-scaling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!