blueimp-load-image-rails 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,174 @@
1
+ /*
2
+ * JavaScript Load Image iOS scaling fixes 1.0.0
3
+ * https://github.com/blueimp/JavaScript-Load-Image
4
+ *
5
+ * Copyright 2013, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * iOS image scaling fixes based on
9
+ * https://github.com/stomita/ios-imagefile-megapixel
10
+ *
11
+ * Licensed under the MIT license:
12
+ * http://www.opensource.org/licenses/MIT
13
+ */
14
+
15
+ /*jslint nomen: true, bitwise: true */
16
+ /*global define, window, document */
17
+
18
+ (function (factory) {
19
+ 'use strict';
20
+ if (typeof define === 'function' && define.amd) {
21
+ // Register as an anonymous AMD module:
22
+ define(['load-image'], factory);
23
+ } else {
24
+ // Browser globals:
25
+ factory(window.loadImage);
26
+ }
27
+ }(function (loadImage) {
28
+ 'use strict';
29
+
30
+ // Only apply fixes on the iOS platform:
31
+ if (!window.navigator || !window.navigator.platform ||
32
+ !(/iP(hone|od|ad)/).test(window.navigator.platform)) {
33
+ return;
34
+ }
35
+
36
+ var originalRenderMethod = loadImage.renderImageToCanvas;
37
+
38
+ // Detects subsampling in JPEG images:
39
+ loadImage.detectSubsampling = function (img) {
40
+ var canvas,
41
+ context;
42
+ if (img.width * img.height > 1024 * 1024) { // only consider mexapixel images
43
+ canvas = document.createElement('canvas');
44
+ canvas.width = canvas.height = 1;
45
+ context = canvas.getContext('2d');
46
+ context.drawImage(img, -img.width + 1, 0);
47
+ // subsampled image becomes half smaller in rendering size.
48
+ // check alpha channel value to confirm image is covering edge pixel or not.
49
+ // if alpha value is 0 image is not covering, hence subsampled.
50
+ return context.getImageData(0, 0, 1, 1).data[3] === 0;
51
+ }
52
+ return false;
53
+ };
54
+
55
+ // Detects vertical squash in JPEG images:
56
+ loadImage.detectVerticalSquash = function (img, correctedHeight) {
57
+ var canvas = document.createElement('canvas'),
58
+ context = canvas.getContext('2d'),
59
+ data,
60
+ sy,
61
+ ey,
62
+ py,
63
+ alpha;
64
+ canvas.width = 1;
65
+ canvas.height = correctedHeight;
66
+ context.drawImage(img, 0, 0);
67
+ data = context.getImageData(0, 0, 1, correctedHeight).data;
68
+ // search image edge pixel position in case it is squashed vertically:
69
+ sy = 0;
70
+ ey = correctedHeight;
71
+ py = correctedHeight;
72
+ while (py > sy) {
73
+ alpha = data[(py - 1) * 4 + 3];
74
+ if (alpha === 0) {
75
+ ey = py;
76
+ } else {
77
+ sy = py;
78
+ }
79
+ py = (ey + sy) >> 1;
80
+ }
81
+ return (py / correctedHeight) || 1;
82
+ };
83
+
84
+ // Renders image to canvas while working around iOS image scaling bugs:
85
+ // https://github.com/blueimp/JavaScript-Load-Image/issues/13
86
+ loadImage.renderImageToCanvas = function (
87
+ canvas,
88
+ img,
89
+ sourceX,
90
+ sourceY,
91
+ sourceWidth,
92
+ sourceHeight,
93
+ destX,
94
+ destY,
95
+ destWidth,
96
+ destHeight
97
+ ) {
98
+ if (img._type === 'image/jpeg') {
99
+ var context = canvas.getContext('2d'),
100
+ tmpCanvas = document.createElement('canvas'),
101
+ tileSize = 1024,
102
+ tmpContext = tmpCanvas.getContext('2d'),
103
+ subSampled,
104
+ vertSquashRatio,
105
+ tileX,
106
+ tileY;
107
+ tmpCanvas.width = tileSize;
108
+ tmpCanvas.height = tileSize;
109
+ context.save();
110
+ subSampled = loadImage.detectSubsampling(img);
111
+ if (subSampled) {
112
+ sourceWidth /= 2;
113
+ sourceHeight /= 2;
114
+ }
115
+ vertSquashRatio = loadImage.detectVerticalSquash(img, sourceHeight);
116
+ if (subSampled && vertSquashRatio !== 1) {
117
+ destWidth = Math.ceil(tileSize * destWidth / sourceWidth);
118
+ destHeight = Math.ceil(
119
+ tileSize * destHeight / sourceHeight / vertSquashRatio
120
+ );
121
+ destY = 0;
122
+ tileY = 0;
123
+ while (tileY < sourceHeight) {
124
+ destX = 0;
125
+ tileX = 0;
126
+ while (tileX < sourceWidth) {
127
+ tmpContext.clearRect(0, 0, tileSize, tileSize);
128
+ tmpContext.drawImage(
129
+ img,
130
+ sourceX,
131
+ sourceY,
132
+ sourceWidth,
133
+ sourceHeight,
134
+ -tileX,
135
+ -tileY,
136
+ sourceWidth,
137
+ sourceHeight
138
+ );
139
+ context.drawImage(
140
+ tmpCanvas,
141
+ 0,
142
+ 0,
143
+ tileSize,
144
+ tileSize,
145
+ destX,
146
+ destY,
147
+ destWidth,
148
+ destHeight
149
+ );
150
+ tileX += tileSize;
151
+ destX += destWidth;
152
+ }
153
+ tileY += tileSize;
154
+ destY += destHeight;
155
+ }
156
+ context.restore();
157
+ return canvas;
158
+ }
159
+ }
160
+ return originalRenderMethod(
161
+ canvas,
162
+ img,
163
+ sourceX,
164
+ sourceY,
165
+ sourceWidth,
166
+ sourceHeight,
167
+ destX,
168
+ destY,
169
+ destWidth,
170
+ destHeight
171
+ );
172
+ };
173
+
174
+ }));
@@ -0,0 +1,137 @@
1
+ /*
2
+ * JavaScript Load Image Meta 1.0.1
3
+ * https://github.com/blueimp/JavaScript-Load-Image
4
+ *
5
+ * Copyright 2013, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Image meta data handling implementation
9
+ * based on the help and contribution of
10
+ * Achim Stöhr.
11
+ *
12
+ * Licensed under the MIT license:
13
+ * http://www.opensource.org/licenses/MIT
14
+ */
15
+
16
+ /*jslint continue:true */
17
+ /*global define, window, DataView, Blob, Uint8Array, console */
18
+
19
+ (function (factory) {
20
+ 'use strict';
21
+ if (typeof define === 'function' && define.amd) {
22
+ // Register as an anonymous AMD module:
23
+ define(['load-image'], factory);
24
+ } else {
25
+ // Browser globals:
26
+ factory(window.loadImage);
27
+ }
28
+ }(function (loadImage) {
29
+ 'use strict';
30
+
31
+ var hasblobSlice = window.Blob && (Blob.prototype.slice ||
32
+ Blob.prototype.webkitSlice || Blob.prototype.mozSlice);
33
+
34
+ loadImage.blobSlice = hasblobSlice && function () {
35
+ var slice = this.slice || this.webkitSlice || this.mozSlice;
36
+ return slice.apply(this, arguments);
37
+ };
38
+
39
+ loadImage.metaDataParsers = {
40
+ jpeg: {
41
+ 0xffe1: [] // APP1 marker
42
+ }
43
+ };
44
+
45
+ // Parses image meta data and calls the callback with an object argument
46
+ // with the following properties:
47
+ // * imageHead: The complete image head as ArrayBuffer (Uint8Array for IE10)
48
+ // The options arguments accepts an object and supports the following properties:
49
+ // * maxMetaDataSize: Defines the maximum number of bytes to parse.
50
+ // * disableImageHead: Disables creating the imageHead property.
51
+ loadImage.parseMetaData = function (file, callback, options) {
52
+ options = options || {};
53
+ var that = this,
54
+ // 256 KiB should contain all EXIF/ICC/IPTC segments:
55
+ maxMetaDataSize = options.maxMetaDataSize || 262144,
56
+ data = {},
57
+ noMetaData = !(window.DataView && file && file.size >= 12 &&
58
+ file.type === 'image/jpeg' && loadImage.blobSlice);
59
+ if (noMetaData || !loadImage.readFile(
60
+ loadImage.blobSlice.call(file, 0, maxMetaDataSize),
61
+ function (e) {
62
+ // Note on endianness:
63
+ // Since the marker and length bytes in JPEG files are always
64
+ // stored in big endian order, we can leave the endian parameter
65
+ // of the DataView methods undefined, defaulting to big endian.
66
+ var buffer = e.target.result,
67
+ dataView = new DataView(buffer),
68
+ offset = 2,
69
+ maxOffset = dataView.byteLength - 4,
70
+ headLength = offset,
71
+ markerBytes,
72
+ markerLength,
73
+ parsers,
74
+ i;
75
+ // Check for the JPEG marker (0xffd8):
76
+ if (dataView.getUint16(0) === 0xffd8) {
77
+ while (offset < maxOffset) {
78
+ markerBytes = dataView.getUint16(offset);
79
+ // Search for APPn (0xffeN) and COM (0xfffe) markers,
80
+ // which contain application-specific meta-data like
81
+ // Exif, ICC and IPTC data and text comments:
82
+ if ((markerBytes >= 0xffe0 && markerBytes <= 0xffef) ||
83
+ markerBytes === 0xfffe) {
84
+ // The marker bytes (2) are always followed by
85
+ // the length bytes (2), indicating the length of the
86
+ // marker segment, which includes the length bytes,
87
+ // but not the marker bytes, so we add 2:
88
+ markerLength = dataView.getUint16(offset + 2) + 2;
89
+ if (offset + markerLength > dataView.byteLength) {
90
+ console.log('Invalid meta data: Invalid segment size.');
91
+ break;
92
+ }
93
+ parsers = loadImage.metaDataParsers.jpeg[markerBytes];
94
+ if (parsers) {
95
+ for (i = 0; i < parsers.length; i += 1) {
96
+ parsers[i].call(
97
+ that,
98
+ dataView,
99
+ offset,
100
+ markerLength,
101
+ data,
102
+ options
103
+ );
104
+ }
105
+ }
106
+ offset += markerLength;
107
+ headLength = offset;
108
+ } else {
109
+ // Not an APPn or COM marker, probably safe to
110
+ // assume that this is the end of the meta data
111
+ break;
112
+ }
113
+ }
114
+ // Meta length must be longer than JPEG marker (2)
115
+ // plus APPn marker (2), followed by length bytes (2):
116
+ if (!options.disableImageHead && headLength > 6) {
117
+ if (buffer.slice) {
118
+ data.imageHead = buffer.slice(0, headLength);
119
+ } else {
120
+ // Workaround for IE10, which does not yet
121
+ // support ArrayBuffer.slice:
122
+ data.imageHead = new Uint8Array(buffer)
123
+ .subarray(0, headLength);
124
+ }
125
+ }
126
+ } else {
127
+ console.log('Invalid JPEG file: Missing JPEG marker.');
128
+ }
129
+ callback(data);
130
+ },
131
+ 'readAsArrayBuffer'
132
+ )) {
133
+ callback(data);
134
+ }
135
+ };
136
+
137
+ }));
@@ -0,0 +1,289 @@
1
+ /*
2
+ * JavaScript Load Image 1.8.0
3
+ * https://github.com/blueimp/JavaScript-Load-Image
4
+ *
5
+ * Copyright 2011, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Licensed under the MIT license:
9
+ * http://www.opensource.org/licenses/MIT
10
+ */
11
+
12
+ /*jslint nomen: true */
13
+ /*global define, window, document, URL, webkitURL, Blob, File, FileReader */
14
+
15
+ (function ($) {
16
+ 'use strict';
17
+
18
+ // Loads an image for a given File object.
19
+ // Invokes the callback with an img or optional canvas
20
+ // element (if supported by the browser) as parameter:
21
+ var loadImage = function (file, callback, options) {
22
+ var img = document.createElement('img'),
23
+ url,
24
+ oUrl;
25
+ img.onerror = callback;
26
+ img.onload = function () {
27
+ if (oUrl && !(options && options.noRevoke)) {
28
+ loadImage.revokeObjectURL(oUrl);
29
+ }
30
+ if (callback) {
31
+ callback(loadImage.scale(img, options));
32
+ }
33
+ };
34
+ if (loadImage.isInstanceOf('Blob', file) ||
35
+ // Files are also Blob instances, but some browsers
36
+ // (Firefox 3.6) support the File API but not Blobs:
37
+ loadImage.isInstanceOf('File', file)) {
38
+ url = oUrl = loadImage.createObjectURL(file);
39
+ // Store the file type for resize processing:
40
+ img._type = file.type;
41
+ } else if (typeof file === 'string') {
42
+ url = file;
43
+ if (options && options.crossOrigin) {
44
+ img.crossOrigin = options.crossOrigin;
45
+ }
46
+ } else {
47
+ return false;
48
+ }
49
+ if (url) {
50
+ img.src = url;
51
+ return img;
52
+ }
53
+ return loadImage.readFile(file, function (e) {
54
+ var target = e.target;
55
+ if (target && target.result) {
56
+ img.src = target.result;
57
+ } else {
58
+ if (callback) {
59
+ callback(e);
60
+ }
61
+ }
62
+ });
63
+ },
64
+ // The check for URL.revokeObjectURL fixes an issue with Opera 12,
65
+ // which provides URL.createObjectURL but doesn't properly implement it:
66
+ urlAPI = (window.createObjectURL && window) ||
67
+ (window.URL && URL.revokeObjectURL && URL) ||
68
+ (window.webkitURL && webkitURL);
69
+
70
+ loadImage.isInstanceOf = function (type, obj) {
71
+ // Cross-frame instanceof check
72
+ return Object.prototype.toString.call(obj) === '[object ' + type + ']';
73
+ };
74
+
75
+ // Transform image orientation based on the given EXIF orientation data:
76
+ loadImage.transformCoordinates = function (canvas, orientation) {
77
+ var ctx = canvas.getContext('2d'),
78
+ width = canvas.width,
79
+ height = canvas.height;
80
+ if (orientation > 4) {
81
+ canvas.width = height;
82
+ canvas.height = width;
83
+ }
84
+ switch (orientation) {
85
+ case 2:
86
+ // horizontal flip
87
+ ctx.translate(width, 0);
88
+ ctx.scale(-1, 1);
89
+ break;
90
+ case 3:
91
+ // 180 rotate left
92
+ ctx.translate(width, height);
93
+ ctx.rotate(Math.PI);
94
+ break;
95
+ case 4:
96
+ // vertical flip
97
+ ctx.translate(0, height);
98
+ ctx.scale(1, -1);
99
+ break;
100
+ case 5:
101
+ // vertical flip + 90 rotate right
102
+ ctx.rotate(0.5 * Math.PI);
103
+ ctx.scale(1, -1);
104
+ break;
105
+ case 6:
106
+ // 90 rotate right
107
+ ctx.rotate(0.5 * Math.PI);
108
+ ctx.translate(0, -height);
109
+ break;
110
+ case 7:
111
+ // horizontal flip + 90 rotate right
112
+ ctx.rotate(0.5 * Math.PI);
113
+ ctx.translate(width, -height);
114
+ ctx.scale(-1, 1);
115
+ break;
116
+ case 8:
117
+ // 90 rotate left
118
+ ctx.rotate(-0.5 * Math.PI);
119
+ ctx.translate(-width, 0);
120
+ break;
121
+ }
122
+ };
123
+
124
+ // Canvas render method, allows to override the
125
+ // rendering e.g. to work around issues on iOS:
126
+ loadImage.renderImageToCanvas = function (
127
+ canvas,
128
+ img,
129
+ sourceX,
130
+ sourceY,
131
+ sourceWidth,
132
+ sourceHeight,
133
+ destX,
134
+ destY,
135
+ destWidth,
136
+ destHeight
137
+ ) {
138
+ canvas.getContext('2d').drawImage(
139
+ img,
140
+ sourceX,
141
+ sourceY,
142
+ sourceWidth,
143
+ sourceHeight,
144
+ destX,
145
+ destY,
146
+ destWidth,
147
+ destHeight
148
+ );
149
+ return canvas;
150
+ };
151
+
152
+ // Scales the given image (img or canvas HTML element)
153
+ // using the given options.
154
+ // Returns a canvas object if the browser supports canvas
155
+ // and the canvas or crop option is true or a canvas object
156
+ // is passed as image, else the scaled image:
157
+ loadImage.scale = function (img, options) {
158
+ options = options || {};
159
+ var canvas = document.createElement('canvas'),
160
+ useCanvas = img.getContext ||
161
+ ((options.canvas || options.crop || options.orientation) &&
162
+ canvas.getContext),
163
+ width = img.width,
164
+ height = img.height,
165
+ sourceWidth = width,
166
+ sourceHeight = height,
167
+ sourceX = 0,
168
+ sourceY = 0,
169
+ destX = 0,
170
+ destY = 0,
171
+ maxWidth,
172
+ maxHeight,
173
+ minWidth,
174
+ minHeight,
175
+ destWidth,
176
+ destHeight,
177
+ scaleUp = function () {
178
+ var scale = Math.max(
179
+ (minWidth || destWidth) / destWidth,
180
+ (minHeight || destHeight) / destHeight
181
+ );
182
+ if (scale > 1) {
183
+ destWidth = Math.ceil(destWidth * scale);
184
+ destHeight = Math.ceil(destHeight * scale);
185
+ }
186
+ },
187
+ scaleDown = function () {
188
+ var scale = Math.min(
189
+ (maxWidth || destWidth) / destWidth,
190
+ (maxHeight || destHeight) / destHeight
191
+ );
192
+ if (scale < 1) {
193
+ destWidth = Math.ceil(destWidth * scale);
194
+ destHeight = Math.ceil(destHeight * scale);
195
+ }
196
+ };
197
+ if (useCanvas && options.orientation > 4) {
198
+ maxWidth = options.maxHeight;
199
+ maxHeight = options.maxWidth;
200
+ minWidth = options.minHeight;
201
+ minHeight = options.minWidth;
202
+ } else {
203
+ maxWidth = options.maxWidth;
204
+ maxHeight = options.maxHeight;
205
+ minWidth = options.minWidth;
206
+ minHeight = options.minHeight;
207
+ }
208
+ if (useCanvas && maxWidth && maxHeight && options.crop) {
209
+ destWidth = maxWidth;
210
+ destHeight = maxHeight;
211
+ if (width / height < maxWidth / maxHeight) {
212
+ sourceHeight = maxHeight * width / maxWidth;
213
+ sourceY = (height - sourceHeight) / 2;
214
+ } else {
215
+ sourceWidth = maxWidth * height / maxHeight;
216
+ sourceX = (width - sourceWidth) / 2;
217
+ }
218
+ } else {
219
+ if (options.contain || options.cover) {
220
+ minWidth = maxWidth = maxWidth || minWidth;
221
+ minHeight = maxHeight = maxHeight || minHeight;
222
+ }
223
+ destWidth = width;
224
+ destHeight = height;
225
+ if (options.cover) {
226
+ scaleDown();
227
+ scaleUp();
228
+ } else {
229
+ scaleUp();
230
+ scaleDown();
231
+ }
232
+ }
233
+ if (useCanvas) {
234
+ canvas.width = destWidth;
235
+ canvas.height = destHeight;
236
+ loadImage.transformCoordinates(
237
+ canvas,
238
+ options.orientation
239
+ );
240
+ return loadImage.renderImageToCanvas(
241
+ canvas,
242
+ img,
243
+ sourceX,
244
+ sourceY,
245
+ sourceWidth,
246
+ sourceHeight,
247
+ destX,
248
+ destY,
249
+ destWidth,
250
+ destHeight
251
+ );
252
+ }
253
+ img.width = destWidth;
254
+ img.height = destHeight;
255
+ return img;
256
+ };
257
+
258
+ loadImage.createObjectURL = function (file) {
259
+ return urlAPI ? urlAPI.createObjectURL(file) : false;
260
+ };
261
+
262
+ loadImage.revokeObjectURL = function (url) {
263
+ return urlAPI ? urlAPI.revokeObjectURL(url) : false;
264
+ };
265
+
266
+ // Loads a given File object via FileReader interface,
267
+ // invokes the callback with the event object (load or error).
268
+ // The result can be read via event.target.result:
269
+ loadImage.readFile = function (file, callback, method) {
270
+ if (window.FileReader) {
271
+ var fileReader = new FileReader();
272
+ fileReader.onload = fileReader.onerror = callback;
273
+ method = method || 'readAsDataURL';
274
+ if (fileReader[method]) {
275
+ fileReader[method](file);
276
+ return fileReader;
277
+ }
278
+ }
279
+ return false;
280
+ };
281
+
282
+ if (typeof define === 'function' && define.amd) {
283
+ define(function () {
284
+ return loadImage;
285
+ });
286
+ } else {
287
+ $.loadImage = loadImage;
288
+ }
289
+ }(this));