Skip to content

Commit cd5cb5c

Browse files
committed
Fixed image scaling on iOS devices - Fixes blueimp#13.
iOS image scaling fixes based on https://github.com/stomita/ios-imagefile-megapixel
1 parent c882fec commit cd5cb5c

File tree

2 files changed

+112
-5
lines changed

2 files changed

+112
-5
lines changed

load-image.js

Lines changed: 111 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
/*
2-
* JavaScript Load Image 1.2.1
2+
* JavaScript Load Image 1.2.2
33
* https://github.com/blueimp/JavaScript-Load-Image
44
*
55
* Copyright 2011, Sebastian Tschan
66
* https://blueimp.net
77
*
8+
* iOS image scaling fixes based on
9+
* https://github.com/stomita/ios-imagefile-megapixel
10+
*
811
* Licensed under the MIT license:
912
* http://www.opensource.org/licenses/MIT
1013
*/
1114

12-
/*jslint nomen: true */
15+
/*jslint nomen: true, bitwise: true */
1316
/*global window, document, URL, webkitURL, Blob, File, FileReader, define */
1417

1518
(function ($) {
@@ -34,6 +37,8 @@
3437
// (Firefox 3.6) support the File API but not Blobs:
3538
(window.File && file instanceof File)) {
3639
url = oUrl = loadImage.createObjectURL(file);
40+
// Store the file type for resize processing:
41+
img._type = file.type;
3742
} else {
3843
url = file;
3944
}
@@ -51,6 +56,103 @@
5156
(window.URL && URL.revokeObjectURL && URL) ||
5257
(window.webkitURL && webkitURL);
5358

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+
54156
// Scales the given image (img or canvas HTML element)
55157
// using the given options.
56158
// Returns a canvas object if the browser supports canvas
@@ -80,8 +182,13 @@
80182
if (img.getContext || (options.canvas && canvas.getContext)) {
81183
canvas.width = width;
82184
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+
}
85192
return canvas;
86193
}
87194
img.width = width;

load-image.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)