Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: ui/file_manager/image_loader/image_loader_util.js

Issue 2634213003: Compile image loader in v2 syntax. (Closed)
Patch Set: Fix a unit test. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 var ImageLoaderUtil = {};
6 * Loads and resizes an image.
7 * @constructor
8 */
9 function ImageLoader() {
10 /**
11 * Persistent cache object.
12 * @type {ImageCache}
13 * @private
14 */
15 this.cache_ = new ImageCache();
16
17 /**
18 * Manages pending requests and runs them in order of priorities.
19 * @type {Scheduler}
20 * @private
21 */
22 this.scheduler_ = new Scheduler();
23
24 /**
25 * Piex loader for RAW images.
26 * @private {!PiexLoader}
27 */
28 this.piexLoader_ = new PiexLoader();
29
30 // Grant permissions to all volumes, initialize the cache and then start the
31 // scheduler.
32 chrome.fileManagerPrivate.getVolumeMetadataList(function(volumeMetadataList) {
33 // Listen for mount events, and grant permissions to volumes being mounted.
34 chrome.fileManagerPrivate.onMountCompleted.addListener(
35 function(event) {
36 if (event.eventType === 'mount' && event.status === 'success') {
37 chrome.fileSystem.requestFileSystem(
38 {volumeId: event.volumeMetadata.volumeId}, function() {});
39 }
40 });
41 var initPromises = volumeMetadataList.map(function(volumeMetadata) {
42 var requestPromise = new Promise(function(callback) {
43 chrome.fileSystem.requestFileSystem(
44 {volumeId: volumeMetadata.volumeId},
45 /** @type {function(FileSystem=)} */(callback));
46 });
47 return requestPromise;
48 });
49 initPromises.push(new Promise(function(resolve, reject) {
50 this.cache_.initialize(resolve);
51 }.bind(this)));
52
53 // After all initialization promises are done, start the scheduler.
54 Promise.all(initPromises).then(this.scheduler_.start.bind(this.scheduler_));
55 }.bind(this));
56
57 // Listen for incoming requests.
58 chrome.runtime.onMessageExternal.addListener(
59 function(request, sender, sendResponse) {
60 if (ImageLoader.ALLOWED_CLIENTS.indexOf(sender.id) !== -1) {
61 // Sending a response may fail if the receiver already went offline.
62 // This is not an error, but a normal and quite common situation.
63 var failSafeSendResponse = function(response) {
64 try {
65 sendResponse(response);
66 }
67 catch (e) {
68 // Ignore the error.
69 }
70 };
71 if (typeof request.orientation === 'number') {
72 request.orientation =
73 ImageOrientation.fromDriveOrientation(request.orientation);
74 } else {
75 request.orientation = new ImageOrientation(1, 0, 0, 1);
76 }
77 return this.onMessage_(sender.id,
78 /** @type {LoadImageRequest} */ (request),
79 failSafeSendResponse);
80 }
81 }.bind(this));
82 }
83
84 /**
85 * List of extensions allowed to perform image requests.
86 *
87 * @const
88 * @type {Array<string>}
89 */
90 ImageLoader.ALLOWED_CLIENTS = [
91 'hhaomjibdihmijegdhdafkllkbggdgoj', // File Manager's extension id.
92 'nlkncpkkdoccmpiclbokaimcnedabhhm', // Gallery's extension id.
93 'jcgeabjmjgoblfofpppfkcoakmfobdko', // Video Player's extension id.
94 ];
95
96 /**
97 * Handles a request. Depending on type of the request, starts or stops
98 * an image task.
99 *
100 * @param {string} senderId Sender's extension id.
101 * @param {!LoadImageRequest} request Request message as a hash array.
102 * @param {function(Object)} callback Callback to be called to return response.
103 * @return {boolean} True if the message channel should stay alive until the
104 * callback is called.
105 * @private
106 */
107 ImageLoader.prototype.onMessage_ = function(senderId, request, callback) {
108 var requestId = senderId + ':' + request.taskId;
109 if (request.cancel) {
110 // Cancel a task.
111 this.scheduler_.remove(requestId);
112 return false; // No callback calls.
113 } else {
114 // Create a request task and add it to the scheduler (queue).
115 var requestTask = new ImageRequest(
116 requestId, this.cache_, this.piexLoader_, request, callback);
117 this.scheduler_.add(requestTask);
118 return true; // Request will call the callback.
119 }
120 };
121
122 /**
123 * Returns the singleton instance.
124 * @return {ImageLoader} ImageLoader object.
125 */
126 ImageLoader.getInstance = function() {
127 if (!ImageLoader.instance_)
128 ImageLoader.instance_ = new ImageLoader();
129 return ImageLoader.instance_;
130 };
131 6
132 /** 7 /**
133 * Checks if the options contain any image processing. 8 * Checks if the options contain any image processing.
134 * 9 *
135 * @param {number} width Source width. 10 * @param {number} width Source width.
136 * @param {number} height Source height. 11 * @param {number} height Source height.
137 * @param {Object} options Resizing options as a hash array. 12 * @param {Object} options Resizing options as a hash array.
138 * @return {boolean} True if yes, false if not. 13 * @return {boolean} True if yes, false if not.
139 */ 14 */
140 ImageLoader.shouldProcess = function(width, height, options) { 15 ImageLoaderUtil.shouldProcess = function(width, height, options) {
141 var targetDimensions = ImageLoader.resizeDimensions(width, height, options); 16 var targetDimensions = ImageLoaderUtil.resizeDimensions(
17 width, height, options);
142 18
143 // Dimensions has to be adjusted. 19 // Dimensions has to be adjusted.
144 if (targetDimensions.width != width || targetDimensions.height != height) 20 if (targetDimensions.width != width || targetDimensions.height != height)
145 return true; 21 return true;
146 22
147 // Orientation has to be adjusted. 23 // Orientation has to be adjusted.
148 if (!options.orientation.isIdentity()) 24 if (!options.orientation.isIdentity())
149 return true; 25 return true;
150 26
151 // Non-standard color space has to be converted. 27 // Non-standard color space has to be converted.
152 if (options.colorSpace && options.colorSpace !== ColorSpace.SRGB) 28 if (options.colorSpace && options.colorSpace !== ColorSpace.SRGB)
153 return true; 29 return true;
154 30
155 // No changes required. 31 // No changes required.
156 return false; 32 return false;
157 }; 33 };
158 34
159 /** 35 /**
160 * Calculates dimensions taking into account resize options, such as: 36 * Calculates dimensions taking into account resize options, such as:
161 * - scale: for scaling, 37 * - scale: for scaling,
162 * - maxWidth, maxHeight: for maximum dimensions, 38 * - maxWidth, maxHeight: for maximum dimensions,
163 * - width, height: for exact requested size. 39 * - width, height: for exact requested size.
164 * Returns the target size as hash array with width, height properties. 40 * Returns the target size as hash array with width, height properties.
165 * 41 *
166 * @param {number} width Source width. 42 * @param {number} width Source width.
167 * @param {number} height Source height. 43 * @param {number} height Source height.
168 * @param {Object} options Resizing options as a hash array. 44 * @param {Object} options Resizing options as a hash array.
169 * @return {Object} Dimensions, eg. {width: 100, height: 50}. 45 * @return {Object} Dimensions, eg. {width: 100, height: 50}.
170 */ 46 */
171 ImageLoader.resizeDimensions = function(width, height, options) { 47 ImageLoaderUtil.resizeDimensions = function(width, height, options) {
172 var scale = options.scale || 1; 48 var scale = options.scale || 1;
173 var targetDimensions = options.orientation.getSizeAfterCancelling( 49 var targetDimensions = options.orientation.getSizeAfterCancelling(
174 width * scale, height * scale); 50 width * scale, height * scale);
175 var targetWidth = targetDimensions.width; 51 var targetWidth = targetDimensions.width;
176 var targetHeight = targetDimensions.height; 52 var targetHeight = targetDimensions.height;
177 53
178 if (options.maxWidth && targetWidth > options.maxWidth) { 54 if (options.maxWidth && targetWidth > options.maxWidth) {
179 var scale = options.maxWidth / targetWidth; 55 var scale = options.maxWidth / targetWidth;
180 targetWidth *= scale; 56 targetWidth *= scale;
181 targetHeight *= scale; 57 targetHeight *= scale;
(...skipping 17 matching lines...) Expand all
199 return {width: targetWidth, height: targetHeight}; 75 return {width: targetWidth, height: targetHeight};
200 }; 76 };
201 77
202 /** 78 /**
203 * Performs resizing and cropping of the source image into the target canvas. 79 * Performs resizing and cropping of the source image into the target canvas.
204 * 80 *
205 * @param {HTMLCanvasElement|Image} source Source image or canvas. 81 * @param {HTMLCanvasElement|Image} source Source image or canvas.
206 * @param {HTMLCanvasElement} target Target canvas. 82 * @param {HTMLCanvasElement} target Target canvas.
207 * @param {Object} options Resizing options as a hash array. 83 * @param {Object} options Resizing options as a hash array.
208 */ 84 */
209 ImageLoader.resizeAndCrop = function(source, target, options) { 85 ImageLoaderUtil.resizeAndCrop = function(source, target, options) {
210 // Calculates copy parameters. 86 // Calculates copy parameters.
211 var copyParameters = ImageLoader.calculateCopyParameters(source, options); 87 var copyParameters = ImageLoaderUtil.calculateCopyParameters(
88 source, options);
212 target.width = copyParameters.canvas.width; 89 target.width = copyParameters.canvas.width;
213 target.height = copyParameters.canvas.height; 90 target.height = copyParameters.canvas.height;
214 91
215 // Apply. 92 // Apply.
216 var targetContext = 93 var targetContext =
217 /** @type {CanvasRenderingContext2D} */ (target.getContext('2d')); 94 /** @type {CanvasRenderingContext2D} */ (target.getContext('2d'));
218 targetContext.save(); 95 targetContext.save();
219 options.orientation.cancelImageOrientation( 96 options.orientation.cancelImageOrientation(
220 targetContext, copyParameters.target.width, copyParameters.target.height); 97 targetContext, copyParameters.target.width, copyParameters.target.height);
221 targetContext.drawImage( 98 targetContext.drawImage(
222 source, 99 source,
223 copyParameters.source.x, 100 copyParameters.source.x,
224 copyParameters.source.y, 101 copyParameters.source.y,
225 copyParameters.source.width, 102 copyParameters.source.width,
226 copyParameters.source.height, 103 copyParameters.source.height,
227 copyParameters.target.x, 104 copyParameters.target.x,
228 copyParameters.target.y, 105 copyParameters.target.y,
229 copyParameters.target.width, 106 copyParameters.target.width,
230 copyParameters.target.height); 107 copyParameters.target.height);
231 targetContext.restore(); 108 targetContext.restore();
232 }; 109 };
233 110
234 /** 111 /**
235 * @typedef {{ 112 * @typedef {{
236 * source: {x:number, y:number, width:number, height:number}, 113 * source: {x:number, y:number, width:number, height:number},
237 * target: {x:number, y:number, width:number, height:number}, 114 * target: {x:number, y:number, width:number, height:number},
238 * canvas: {width:number, height:number} 115 * canvas: {width:number, height:number}
239 * }} 116 * }}
240 */ 117 */
241 ImageLoader.CopyParameters; 118 ImageLoaderUtil.CopyParameters;
242 119
243 /** 120 /**
244 * Calculates copy parameters. 121 * Calculates copy parameters.
245 * 122 *
246 * @param {HTMLCanvasElement|Image} source Source image or canvas. 123 * @param {HTMLCanvasElement|Image} source Source image or canvas.
247 * @param {Object} options Resizing options as a hash array. 124 * @param {Object} options Resizing options as a hash array.
248 * @return {!ImageLoader.CopyParameters} Calculated copy parameters. 125 * @return {!ImageLoaderUtil.CopyParameters} Calculated copy parameters.
249 */ 126 */
250 ImageLoader.calculateCopyParameters = function(source, options) { 127 ImageLoaderUtil.calculateCopyParameters = function(source, options) {
251 if (options.crop) { 128 if (options.crop) {
252 // When an image is cropped, target should be a fixed size square. 129 // When an image is cropped, target should be a fixed size square.
253 assert(options.width); 130 assert(options.width);
254 assert(options.height); 131 assert(options.height);
255 assert(options.width === options.height); 132 assert(options.width === options.height);
256 133
257 // The length of shorter edge becomes dimension of cropped area in the 134 // The length of shorter edge becomes dimension of cropped area in the
258 // source. 135 // source.
259 var cropSourceDimension = Math.min(source.width, source.height); 136 var cropSourceDimension = Math.min(source.width, source.height);
260 137
(...skipping 11 matching lines...) Expand all
272 height: options.height 149 height: options.height
273 }, 150 },
274 canvas: { 151 canvas: {
275 width: options.width, 152 width: options.width,
276 height: options.height 153 height: options.height
277 } 154 }
278 }; 155 };
279 } 156 }
280 157
281 // Target dimension is calculated in the rotated(transformed) coordinate. 158 // Target dimension is calculated in the rotated(transformed) coordinate.
282 var targetCanvasDimensions = ImageLoader.resizeDimensions( 159 var targetCanvasDimensions = ImageLoaderUtil.resizeDimensions(
283 source.width, source.height, options); 160 source.width, source.height, options);
284 161
285 var targetDimensions = options.orientation.getSizeAfterCancelling( 162 var targetDimensions = options.orientation.getSizeAfterCancelling(
286 targetCanvasDimensions.width, targetCanvasDimensions.height); 163 targetCanvasDimensions.width, targetCanvasDimensions.height);
287 164
288 return { 165 return {
289 source: { 166 source: {
290 x: 0, 167 x: 0,
291 y: 0, 168 y: 0,
292 width: source.width, 169 width: source.width,
293 height: source.height 170 height: source.height
294 }, 171 },
295 target: { 172 target: {
296 x: 0, 173 x: 0,
297 y: 0, 174 y: 0,
298 width: targetDimensions.width, 175 width: targetDimensions.width,
299 height: targetDimensions.height 176 height: targetDimensions.height
300 }, 177 },
301 canvas: { 178 canvas: {
302 width: targetCanvasDimensions.width, 179 width: targetCanvasDimensions.width,
303 height: targetCanvasDimensions.height 180 height: targetCanvasDimensions.height
304 } 181 }
305 }; 182 };
306 }; 183 };
307 184
308 /** 185 /**
309 * Matrix converts AdobeRGB color space into sRGB color space. 186 * Matrix converts AdobeRGB color space into sRGB color space.
310 * @const {!Array<number>} 187 * @const {!Array<number>}
311 */ 188 */
312 ImageLoader.MATRIX_FROM_ADOBE_TO_STANDARD = [ 189 ImageLoaderUtil.MATRIX_FROM_ADOBE_TO_STANDARD = [
313 1.39836, -0.39836, 0.00000, 190 1.39836, -0.39836, 0.00000,
314 0.00000, 1.00000, 0.00000, 191 0.00000, 1.00000, 0.00000,
315 0.00000, -0.04293, 1.04293 192 0.00000, -0.04293, 1.04293
316 ]; 193 ];
317 194
318 /** 195 /**
319 * Converts the canvas of color space into sRGB. 196 * Converts the canvas of color space into sRGB.
320 * @param {HTMLCanvasElement} target Target canvas. 197 * @param {HTMLCanvasElement} target Target canvas.
321 * @param {ColorSpace} colorSpace Current color space. 198 * @param {ColorSpace} colorSpace Current color space.
322 */ 199 */
323 ImageLoader.convertColorSpace = function(target, colorSpace) { 200 ImageLoaderUtil.convertColorSpace = function(target, colorSpace) {
324 if (colorSpace === ColorSpace.SRGB) 201 if (colorSpace === ColorSpace.SRGB)
325 return; 202 return;
326 if (colorSpace === ColorSpace.ADOBE_RGB) { 203 if (colorSpace === ColorSpace.ADOBE_RGB) {
327 var matrix = ImageLoader.MATRIX_FROM_ADOBE_TO_STANDARD; 204 var matrix = ImageLoaderUtil.MATRIX_FROM_ADOBE_TO_STANDARD;
328 var context = target.getContext('2d'); 205 var context = target.getContext('2d');
329 var imageData = context.getImageData(0, 0, target.width, target.height); 206 var imageData = context.getImageData(0, 0, target.width, target.height);
330 var data = imageData.data; 207 var data = imageData.data;
331 for (var i = 0; i < data.length; i += 4) { 208 for (var i = 0; i < data.length; i += 4) {
332 // Scale to [0, 1]. 209 // Scale to [0, 1].
333 var adobeR = data[i] / 255; 210 var adobeR = data[i] / 255;
334 var adobeG = data[i + 1] / 255; 211 var adobeG = data[i + 1] / 255;
335 var adobeB = data[i + 2] / 255; 212 var adobeB = data[i + 2] / 255;
336 213
337 // Revert gannma transformation. 214 // Revert gannma transformation.
(...skipping 11 matching lines...) Expand all
349 sG = sG <= 0.0031308 ? 12.92 * sG : 1.055 * Math.pow(sG, 1 / 2.4) - 0.055; 226 sG = sG <= 0.0031308 ? 12.92 * sG : 1.055 * Math.pow(sG, 1 / 2.4) - 0.055;
350 sB = sB <= 0.0031308 ? 12.92 * sB : 1.055 * Math.pow(sB, 1 / 2.4) - 0.055; 227 sB = sB <= 0.0031308 ? 12.92 * sB : 1.055 * Math.pow(sB, 1 / 2.4) - 0.055;
351 228
352 // Scale to [0, 255]. 229 // Scale to [0, 255].
353 data[i] = Math.max(0, Math.min(255, sR * 255)); 230 data[i] = Math.max(0, Math.min(255, sR * 255));
354 data[i + 1] = Math.max(0, Math.min(255, sG * 255)); 231 data[i + 1] = Math.max(0, Math.min(255, sG * 255));
355 data[i + 2] = Math.max(0, Math.min(255, sB * 255)); 232 data[i + 2] = Math.max(0, Math.min(255, sB * 255));
356 } 233 }
357 context.putImageData(imageData, 0, 0); 234 context.putImageData(imageData, 0, 0);
358 } 235 }
359 }; 236 };
OLDNEW
« no previous file with comments | « ui/file_manager/image_loader/image_loader_unittest.js ('k') | ui/file_manager/image_loader/request.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698