blueimp-load-image-rails 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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));