| 4 |
lars |
1 |
/*
|
|
|
2 |
* jQuery File Upload Image Preview & Resize Plugin
|
|
|
3 |
* https://github.com/blueimp/jQuery-File-Upload
|
|
|
4 |
*
|
|
|
5 |
* Copyright 2013, Sebastian Tschan
|
|
|
6 |
* https://blueimp.net
|
|
|
7 |
*
|
|
|
8 |
* Licensed under the MIT license:
|
|
|
9 |
* https://opensource.org/licenses/MIT
|
|
|
10 |
*/
|
|
|
11 |
|
|
|
12 |
/* global define, require */
|
|
|
13 |
|
|
|
14 |
(function (factory) {
|
|
|
15 |
'use strict';
|
|
|
16 |
if (typeof define === 'function' && define.amd) {
|
|
|
17 |
// Register as an anonymous AMD module:
|
|
|
18 |
define([
|
|
|
19 |
'jquery',
|
|
|
20 |
'load-image',
|
|
|
21 |
'load-image-meta',
|
|
|
22 |
'load-image-scale',
|
|
|
23 |
'load-image-exif',
|
|
|
24 |
'load-image-orientation',
|
|
|
25 |
'canvas-to-blob',
|
|
|
26 |
'./jquery.fileupload-process'
|
|
|
27 |
], factory);
|
|
|
28 |
} else if (typeof exports === 'object') {
|
|
|
29 |
// Node/CommonJS:
|
|
|
30 |
factory(
|
|
|
31 |
require('jquery'),
|
|
|
32 |
require('blueimp-load-image/js/load-image'),
|
|
|
33 |
require('blueimp-load-image/js/load-image-meta'),
|
|
|
34 |
require('blueimp-load-image/js/load-image-scale'),
|
|
|
35 |
require('blueimp-load-image/js/load-image-exif'),
|
|
|
36 |
require('blueimp-load-image/js/load-image-orientation'),
|
|
|
37 |
require('blueimp-canvas-to-blob'),
|
|
|
38 |
require('./jquery.fileupload-process')
|
|
|
39 |
);
|
|
|
40 |
} else {
|
|
|
41 |
// Browser globals:
|
|
|
42 |
factory(window.jQuery, window.loadImage);
|
|
|
43 |
}
|
|
|
44 |
})(function ($, loadImage) {
|
|
|
45 |
'use strict';
|
|
|
46 |
|
|
|
47 |
// Prepend to the default processQueue:
|
|
|
48 |
$.blueimp.fileupload.prototype.options.processQueue.unshift(
|
|
|
49 |
{
|
|
|
50 |
action: 'loadImageMetaData',
|
|
|
51 |
maxMetaDataSize: '@',
|
|
|
52 |
disableImageHead: '@',
|
|
|
53 |
disableMetaDataParsers: '@',
|
|
|
54 |
disableExif: '@',
|
|
|
55 |
disableExifOffsets: '@',
|
|
|
56 |
includeExifTags: '@',
|
|
|
57 |
excludeExifTags: '@',
|
|
|
58 |
disableIptc: '@',
|
|
|
59 |
disableIptcOffsets: '@',
|
|
|
60 |
includeIptcTags: '@',
|
|
|
61 |
excludeIptcTags: '@',
|
|
|
62 |
disabled: '@disableImageMetaDataLoad'
|
|
|
63 |
},
|
|
|
64 |
{
|
|
|
65 |
action: 'loadImage',
|
|
|
66 |
// Use the action as prefix for the "@" options:
|
|
|
67 |
prefix: true,
|
|
|
68 |
fileTypes: '@',
|
|
|
69 |
maxFileSize: '@',
|
|
|
70 |
noRevoke: '@',
|
|
|
71 |
disabled: '@disableImageLoad'
|
|
|
72 |
},
|
|
|
73 |
{
|
|
|
74 |
action: 'resizeImage',
|
|
|
75 |
// Use "image" as prefix for the "@" options:
|
|
|
76 |
prefix: 'image',
|
|
|
77 |
maxWidth: '@',
|
|
|
78 |
maxHeight: '@',
|
|
|
79 |
minWidth: '@',
|
|
|
80 |
minHeight: '@',
|
|
|
81 |
crop: '@',
|
|
|
82 |
orientation: '@',
|
|
|
83 |
forceResize: '@',
|
|
|
84 |
disabled: '@disableImageResize',
|
|
|
85 |
imageSmoothingQuality: '@imageSmoothingQuality'
|
|
|
86 |
},
|
|
|
87 |
{
|
|
|
88 |
action: 'saveImage',
|
|
|
89 |
quality: '@imageQuality',
|
|
|
90 |
type: '@imageType',
|
|
|
91 |
disabled: '@disableImageResize'
|
|
|
92 |
},
|
|
|
93 |
{
|
|
|
94 |
action: 'saveImageMetaData',
|
|
|
95 |
disabled: '@disableImageMetaDataSave'
|
|
|
96 |
},
|
|
|
97 |
{
|
|
|
98 |
action: 'resizeImage',
|
|
|
99 |
// Use "preview" as prefix for the "@" options:
|
|
|
100 |
prefix: 'preview',
|
|
|
101 |
maxWidth: '@',
|
|
|
102 |
maxHeight: '@',
|
|
|
103 |
minWidth: '@',
|
|
|
104 |
minHeight: '@',
|
|
|
105 |
crop: '@',
|
|
|
106 |
orientation: '@',
|
|
|
107 |
thumbnail: '@',
|
|
|
108 |
canvas: '@',
|
|
|
109 |
disabled: '@disableImagePreview'
|
|
|
110 |
},
|
|
|
111 |
{
|
|
|
112 |
action: 'setImage',
|
|
|
113 |
name: '@imagePreviewName',
|
|
|
114 |
disabled: '@disableImagePreview'
|
|
|
115 |
},
|
|
|
116 |
{
|
|
|
117 |
action: 'deleteImageReferences',
|
|
|
118 |
disabled: '@disableImageReferencesDeletion'
|
|
|
119 |
}
|
|
|
120 |
);
|
|
|
121 |
|
|
|
122 |
// The File Upload Resize plugin extends the fileupload widget
|
|
|
123 |
// with image resize functionality:
|
|
|
124 |
$.widget('blueimp.fileupload', $.blueimp.fileupload, {
|
|
|
125 |
options: {
|
|
|
126 |
// The regular expression for the types of images to load:
|
|
|
127 |
// matched against the file type:
|
|
|
128 |
loadImageFileTypes: /^image\/(gif|jpeg|png|svg\+xml)$/,
|
|
|
129 |
// The maximum file size of images to load:
|
|
|
130 |
loadImageMaxFileSize: 10000000, // 10MB
|
|
|
131 |
// The maximum width of resized images:
|
|
|
132 |
imageMaxWidth: 1920,
|
|
|
133 |
// The maximum height of resized images:
|
|
|
134 |
imageMaxHeight: 1080,
|
|
|
135 |
// Defines the image orientation (1-8) or takes the orientation
|
|
|
136 |
// value from Exif data if set to true:
|
|
|
137 |
imageOrientation: true,
|
|
|
138 |
// Define if resized images should be cropped or only scaled:
|
|
|
139 |
imageCrop: false,
|
|
|
140 |
// Disable the resize image functionality by default:
|
|
|
141 |
disableImageResize: true,
|
|
|
142 |
// The maximum width of the preview images:
|
|
|
143 |
previewMaxWidth: 80,
|
|
|
144 |
// The maximum height of the preview images:
|
|
|
145 |
previewMaxHeight: 80,
|
|
|
146 |
// Defines the preview orientation (1-8) or takes the orientation
|
|
|
147 |
// value from Exif data if set to true:
|
|
|
148 |
previewOrientation: true,
|
|
|
149 |
// Create the preview using the Exif data thumbnail:
|
|
|
150 |
previewThumbnail: true,
|
|
|
151 |
// Define if preview images should be cropped or only scaled:
|
|
|
152 |
previewCrop: false,
|
|
|
153 |
// Define if preview images should be resized as canvas elements:
|
|
|
154 |
previewCanvas: true
|
|
|
155 |
},
|
|
|
156 |
|
|
|
157 |
processActions: {
|
|
|
158 |
// Loads the image given via data.files and data.index
|
|
|
159 |
// as img element, if the browser supports the File API.
|
|
|
160 |
// Accepts the options fileTypes (regular expression)
|
|
|
161 |
// and maxFileSize (integer) to limit the files to load:
|
|
|
162 |
loadImage: function (data, options) {
|
|
|
163 |
if (options.disabled) {
|
|
|
164 |
return data;
|
|
|
165 |
}
|
|
|
166 |
var that = this,
|
|
|
167 |
file = data.files[data.index],
|
|
|
168 |
// eslint-disable-next-line new-cap
|
|
|
169 |
dfd = $.Deferred();
|
|
|
170 |
if (
|
|
|
171 |
($.type(options.maxFileSize) === 'number' &&
|
|
|
172 |
file.size > options.maxFileSize) ||
|
|
|
173 |
(options.fileTypes && !options.fileTypes.test(file.type)) ||
|
|
|
174 |
!loadImage(
|
|
|
175 |
file,
|
|
|
176 |
function (img) {
|
|
|
177 |
if (img.src) {
|
|
|
178 |
data.img = img;
|
|
|
179 |
}
|
|
|
180 |
dfd.resolveWith(that, [data]);
|
|
|
181 |
},
|
|
|
182 |
options
|
|
|
183 |
)
|
|
|
184 |
) {
|
|
|
185 |
return data;
|
|
|
186 |
}
|
|
|
187 |
return dfd.promise();
|
|
|
188 |
},
|
|
|
189 |
|
|
|
190 |
// Resizes the image given as data.canvas or data.img
|
|
|
191 |
// and updates data.canvas or data.img with the resized image.
|
|
|
192 |
// Also stores the resized image as preview property.
|
|
|
193 |
// Accepts the options maxWidth, maxHeight, minWidth,
|
|
|
194 |
// minHeight, canvas and crop:
|
|
|
195 |
resizeImage: function (data, options) {
|
|
|
196 |
if (options.disabled || !(data.canvas || data.img)) {
|
|
|
197 |
return data;
|
|
|
198 |
}
|
|
|
199 |
// eslint-disable-next-line no-param-reassign
|
|
|
200 |
options = $.extend({ canvas: true }, options);
|
|
|
201 |
var that = this,
|
|
|
202 |
// eslint-disable-next-line new-cap
|
|
|
203 |
dfd = $.Deferred(),
|
|
|
204 |
img = (options.canvas && data.canvas) || data.img,
|
|
|
205 |
resolve = function (newImg) {
|
|
|
206 |
if (
|
|
|
207 |
newImg &&
|
|
|
208 |
(newImg.width !== img.width ||
|
|
|
209 |
newImg.height !== img.height ||
|
|
|
210 |
options.forceResize)
|
|
|
211 |
) {
|
|
|
212 |
data[newImg.getContext ? 'canvas' : 'img'] = newImg;
|
|
|
213 |
}
|
|
|
214 |
data.preview = newImg;
|
|
|
215 |
dfd.resolveWith(that, [data]);
|
|
|
216 |
},
|
|
|
217 |
thumbnail,
|
|
|
218 |
thumbnailBlob;
|
|
|
219 |
if (data.exif && options.thumbnail) {
|
|
|
220 |
thumbnail = data.exif.get('Thumbnail');
|
|
|
221 |
thumbnailBlob = thumbnail && thumbnail.get('Blob');
|
|
|
222 |
if (thumbnailBlob) {
|
|
|
223 |
options.orientation = data.exif.get('Orientation');
|
|
|
224 |
loadImage(thumbnailBlob, resolve, options);
|
|
|
225 |
return dfd.promise();
|
|
|
226 |
}
|
|
|
227 |
}
|
|
|
228 |
if (data.orientation) {
|
|
|
229 |
// Prevent orienting the same image twice:
|
|
|
230 |
delete options.orientation;
|
|
|
231 |
} else {
|
|
|
232 |
data.orientation = options.orientation || loadImage.orientation;
|
|
|
233 |
}
|
|
|
234 |
if (img) {
|
|
|
235 |
resolve(loadImage.scale(img, options, data));
|
|
|
236 |
return dfd.promise();
|
|
|
237 |
}
|
|
|
238 |
return data;
|
|
|
239 |
},
|
|
|
240 |
|
|
|
241 |
// Saves the processed image given as data.canvas
|
|
|
242 |
// inplace at data.index of data.files:
|
|
|
243 |
saveImage: function (data, options) {
|
|
|
244 |
if (!data.canvas || options.disabled) {
|
|
|
245 |
return data;
|
|
|
246 |
}
|
|
|
247 |
var that = this,
|
|
|
248 |
file = data.files[data.index],
|
|
|
249 |
// eslint-disable-next-line new-cap
|
|
|
250 |
dfd = $.Deferred();
|
|
|
251 |
if (data.canvas.toBlob) {
|
|
|
252 |
data.canvas.toBlob(
|
|
|
253 |
function (blob) {
|
|
|
254 |
if (!blob.name) {
|
|
|
255 |
if (file.type === blob.type) {
|
|
|
256 |
blob.name = file.name;
|
|
|
257 |
} else if (file.name) {
|
|
|
258 |
blob.name = file.name.replace(
|
|
|
259 |
/\.\w+$/,
|
|
|
260 |
'.' + blob.type.substr(6)
|
|
|
261 |
);
|
|
|
262 |
}
|
|
|
263 |
}
|
|
|
264 |
// Don't restore invalid meta data:
|
|
|
265 |
if (file.type !== blob.type) {
|
|
|
266 |
delete data.imageHead;
|
|
|
267 |
}
|
|
|
268 |
// Store the created blob at the position
|
|
|
269 |
// of the original file in the files list:
|
|
|
270 |
data.files[data.index] = blob;
|
|
|
271 |
dfd.resolveWith(that, [data]);
|
|
|
272 |
},
|
|
|
273 |
options.type || file.type,
|
|
|
274 |
options.quality
|
|
|
275 |
);
|
|
|
276 |
} else {
|
|
|
277 |
return data;
|
|
|
278 |
}
|
|
|
279 |
return dfd.promise();
|
|
|
280 |
},
|
|
|
281 |
|
|
|
282 |
loadImageMetaData: function (data, options) {
|
|
|
283 |
if (options.disabled) {
|
|
|
284 |
return data;
|
|
|
285 |
}
|
|
|
286 |
var that = this,
|
|
|
287 |
// eslint-disable-next-line new-cap
|
|
|
288 |
dfd = $.Deferred();
|
|
|
289 |
loadImage.parseMetaData(
|
|
|
290 |
data.files[data.index],
|
|
|
291 |
function (result) {
|
|
|
292 |
$.extend(data, result);
|
|
|
293 |
dfd.resolveWith(that, [data]);
|
|
|
294 |
},
|
|
|
295 |
options
|
|
|
296 |
);
|
|
|
297 |
return dfd.promise();
|
|
|
298 |
},
|
|
|
299 |
|
|
|
300 |
saveImageMetaData: function (data, options) {
|
|
|
301 |
if (
|
|
|
302 |
!(
|
|
|
303 |
data.imageHead &&
|
|
|
304 |
data.canvas &&
|
|
|
305 |
data.canvas.toBlob &&
|
|
|
306 |
!options.disabled
|
|
|
307 |
)
|
|
|
308 |
) {
|
|
|
309 |
return data;
|
|
|
310 |
}
|
|
|
311 |
var that = this,
|
|
|
312 |
file = data.files[data.index],
|
|
|
313 |
// eslint-disable-next-line new-cap
|
|
|
314 |
dfd = $.Deferred();
|
|
|
315 |
if (data.orientation === true && data.exifOffsets) {
|
|
|
316 |
// Reset Exif Orientation data:
|
|
|
317 |
loadImage.writeExifData(data.imageHead, data, 'Orientation', 1);
|
|
|
318 |
}
|
|
|
319 |
loadImage.replaceHead(file, data.imageHead, function (blob) {
|
|
|
320 |
blob.name = file.name;
|
|
|
321 |
data.files[data.index] = blob;
|
|
|
322 |
dfd.resolveWith(that, [data]);
|
|
|
323 |
});
|
|
|
324 |
return dfd.promise();
|
|
|
325 |
},
|
|
|
326 |
|
|
|
327 |
// Sets the resized version of the image as a property of the
|
|
|
328 |
// file object, must be called after "saveImage":
|
|
|
329 |
setImage: function (data, options) {
|
|
|
330 |
if (data.preview && !options.disabled) {
|
|
|
331 |
data.files[data.index][options.name || 'preview'] = data.preview;
|
|
|
332 |
}
|
|
|
333 |
return data;
|
|
|
334 |
},
|
|
|
335 |
|
|
|
336 |
deleteImageReferences: function (data, options) {
|
|
|
337 |
if (!options.disabled) {
|
|
|
338 |
delete data.img;
|
|
|
339 |
delete data.canvas;
|
|
|
340 |
delete data.preview;
|
|
|
341 |
delete data.imageHead;
|
|
|
342 |
}
|
|
|
343 |
return data;
|
|
|
344 |
}
|
|
|
345 |
}
|
|
|
346 |
});
|
|
|
347 |
});
|