|
1 | 1 | /*
|
2 |
| - * JavaScript Load Image 1.2.1 |
| 2 | + * JavaScript Load Image 1.2.2 |
3 | 3 | * https://github.com/blueimp/JavaScript-Load-Image
|
4 | 4 | *
|
5 | 5 | * Copyright 2011, Sebastian Tschan
|
6 | 6 | * https://blueimp.net
|
7 | 7 | *
|
| 8 | + * iOS image scaling fixes based on |
| 9 | + * https://github.com/stomita/ios-imagefile-megapixel |
| 10 | + * |
8 | 11 | * Licensed under the MIT license:
|
9 | 12 | * http://www.opensource.org/licenses/MIT
|
10 | 13 | */
|
11 | 14 |
|
12 |
| -/*jslint nomen: true */ |
| 15 | +/*jslint nomen: true, bitwise: true */ |
13 | 16 | /*global window, document, URL, webkitURL, Blob, File, FileReader, define */
|
14 | 17 |
|
15 | 18 | (function ($) {
|
|
34 | 37 | // (Firefox 3.6) support the File API but not Blobs:
|
35 | 38 | (window.File && file instanceof File)) {
|
36 | 39 | url = oUrl = loadImage.createObjectURL(file);
|
| 40 | + // Store the file type for resize processing: |
| 41 | + img._type = file.type; |
37 | 42 | } else {
|
38 | 43 | url = file;
|
39 | 44 | }
|
|
51 | 56 | (window.URL && URL.revokeObjectURL && URL) ||
|
52 | 57 | (window.webkitURL && webkitURL);
|
53 | 58 |
|
| 59 | + // Detects subsampling in JPEG images: |
| 60 | + loadImage.detectSubsampling = function (img) { |
| 61 | + var iw = img.width, |
| 62 | + ih = img.height, |
| 63 | + canvas, |
| 64 | + ctx; |
| 65 | + if (iw * ih > 1024 * 1024) { // only consider mexapixel images |
| 66 | + canvas = document.createElement('canvas'); |
| 67 | + canvas.width = canvas.height = 1; |
| 68 | + ctx = canvas.getContext('2d'); |
| 69 | + ctx.drawImage(img, -iw + 1, 0); |
| 70 | + // subsampled image becomes half smaller in rendering size. |
| 71 | + // check alpha channel value to confirm image is covering edge pixel or not. |
| 72 | + // if alpha value is 0 image is not covering, hence subsampled. |
| 73 | + return ctx.getImageData(0, 0, 1, 1).data[3] === 0; |
| 74 | + } |
| 75 | + return false; |
| 76 | + }; |
| 77 | + |
| 78 | + // Detects vertical squash in JPEG images: |
| 79 | + loadImage.detectVerticalSquash = function (img, ih) { |
| 80 | + var canvas = document.createElement('canvas'), |
| 81 | + ctx = canvas.getContext('2d'), |
| 82 | + data, |
| 83 | + sy, |
| 84 | + ey, |
| 85 | + py, |
| 86 | + alpha; |
| 87 | + canvas.width = 1; |
| 88 | + canvas.height = ih; |
| 89 | + ctx.drawImage(img, 0, 0); |
| 90 | + data = ctx.getImageData(0, 0, 1, ih).data; |
| 91 | + // search image edge pixel position in case it is squashed vertically: |
| 92 | + sy = 0; |
| 93 | + ey = ih; |
| 94 | + py = ih; |
| 95 | + while (py > sy) { |
| 96 | + alpha = data[(py - 1) * 4 + 3]; |
| 97 | + if (alpha === 0) { |
| 98 | + ey = py; |
| 99 | + } else { |
| 100 | + sy = py; |
| 101 | + } |
| 102 | + py = (ey + sy) >> 1; |
| 103 | + } |
| 104 | + return py / ih; |
| 105 | + }; |
| 106 | + |
| 107 | + // Renders image to canvas while working around iOS image scaling bugs: |
| 108 | + // https://github.com/blueimp/JavaScript-Load-Image/issues/13 |
| 109 | + loadImage.renderImageToCanvas = function (img, canvas, width, height) { |
| 110 | + var iw = img.width, |
| 111 | + ih = img.height, |
| 112 | + ctx = canvas.getContext('2d'), |
| 113 | + vertSquashRatio, |
| 114 | + d = 1024, // size of tiling canvas |
| 115 | + tmpCanvas = document.createElement('canvas'), |
| 116 | + tmpCtx, |
| 117 | + sy, |
| 118 | + sh, |
| 119 | + sx, |
| 120 | + sw; |
| 121 | + ctx.save(); |
| 122 | + if (loadImage.detectSubsampling(img)) { |
| 123 | + iw /= 2; |
| 124 | + ih /= 2; |
| 125 | + } |
| 126 | + vertSquashRatio = loadImage.detectVerticalSquash(img, ih); |
| 127 | + tmpCanvas.width = tmpCanvas.height = d; |
| 128 | + tmpCtx = tmpCanvas.getContext('2d'); |
| 129 | + sy = 0; |
| 130 | + while (sy < ih) { |
| 131 | + sh = sy + d > ih ? ih - sy : d; |
| 132 | + sx = 0; |
| 133 | + while (sx < iw) { |
| 134 | + sw = sx + d > iw ? iw - sx : d; |
| 135 | + tmpCtx.clearRect(0, 0, d, d); |
| 136 | + tmpCtx.drawImage(img, -sx, -sy); |
| 137 | + ctx.drawImage( |
| 138 | + tmpCanvas, |
| 139 | + 0, |
| 140 | + 0, |
| 141 | + sw, |
| 142 | + sh, |
| 143 | + Math.floor(sx * width / iw), |
| 144 | + Math.floor(sy * height / ih / vertSquashRatio), |
| 145 | + Math.ceil(sw * width / iw), |
| 146 | + Math.ceil(sh * height / ih / vertSquashRatio) |
| 147 | + ); |
| 148 | + sx += d; |
| 149 | + } |
| 150 | + sy += d; |
| 151 | + } |
| 152 | + ctx.restore(); |
| 153 | + tmpCanvas = tmpCtx = null; |
| 154 | + }; |
| 155 | + |
54 | 156 | // Scales the given image (img or canvas HTML element)
|
55 | 157 | // using the given options.
|
56 | 158 | // Returns a canvas object if the browser supports canvas
|
|
80 | 182 | if (img.getContext || (options.canvas && canvas.getContext)) {
|
81 | 183 | canvas.width = width;
|
82 | 184 | canvas.height = height;
|
83 |
| - canvas.getContext('2d') |
84 |
| - .drawImage(img, 0, 0, width, height); |
| 185 | + if (img._type === 'image/jpeg') { |
| 186 | + loadImage |
| 187 | + .renderImageToCanvas(img, canvas, width, height); |
| 188 | + } else { |
| 189 | + canvas.getContext('2d') |
| 190 | + .drawImage(img, 0, 0, width, height); |
| 191 | + } |
85 | 192 | return canvas;
|
86 | 193 | }
|
87 | 194 | img.width = width;
|
|
0 commit comments