1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 * Loads and resizes an image.
11 function ImageLoader() {
13 * Persistent cache object.
17 this.cache_
= new Cache();
20 * Manages pending requests and runs them in order of priorities.
24 this.worker_
= new Worker();
26 // Grant permissions to the local file system and initialize the cache.
27 chrome
.fileBrowserPrivate
.requestFileSystem(
29 function(filesystem
) {
30 this.cache_
.initialize(function() {
35 chrome
.extension
.onMessageExternal
.addListener(function(request
,
38 if (ImageLoader
.ALLOWED_CLIENTS
.indexOf(sender
.id
) !== -1) {
39 // Sending a response may fail if the receiver already went offline.
40 // This is not an error, but a normal and quite common situation.
41 var failSafeSendResponse = function(response
) {
43 sendResponse(response
);
49 return this.onMessage_(sender
.id
, request
, failSafeSendResponse
);
55 * List of extensions allowed to perform image requests.
58 * @type {Array.<string>}
60 ImageLoader
.ALLOWED_CLIENTS
=
61 ['hhaomjibdihmijegdhdafkllkbggdgoj']; // File Manager's extension id.
64 * Handles a request. Depending on type of the request, starts or stops
67 * @param {string} senderId Sender's extension id.
68 * @param {Object} request Request message as a hash array.
69 * @param {function} callback Callback to be called to return response.
70 * @return {boolean} True if the message channel should stay alive until the
74 ImageLoader
.prototype.onMessage_ = function(senderId
, request
, callback
) {
75 var requestId
= senderId
+ ':' + request
.taskId
;
78 this.worker_
.remove(requestId
);
79 return false; // No callback calls.
81 // Create a request task and add it to the worker (queue).
82 var requestTask
= new Request(requestId
, this.cache_
, request
, callback
);
83 this.worker_
.add(requestTask
);
84 return true; // Request will call the callback.
89 * Returns the singleton instance.
90 * @return {ImageLoader} ImageLoader object.
92 ImageLoader
.getInstance = function() {
93 if (!ImageLoader
.instance_
)
94 ImageLoader
.instance_
= new ImageLoader();
95 return ImageLoader
.instance_
;
99 * Checks if the options contain any image processing.
101 * @param {number} width Source width.
102 * @param {number} height Source height.
103 * @param {Object} options Resizing options as a hash array.
104 * @return {boolean} True if yes, false if not.
106 ImageLoader
.shouldProcess = function(width
, height
, options
) {
107 var targetDimensions
= ImageLoader
.resizeDimensions(width
, height
, options
);
109 // Dimensions has to be adjusted.
110 if (targetDimensions
.width
!= width
|| targetDimensions
.height
!= height
)
113 // Orientation has to be adjusted.
114 if (options
.orientation
)
117 // No changes required.
122 * Calculates dimensions taking into account resize options, such as:
123 * - scale: for scaling,
124 * - maxWidth, maxHeight: for maximum dimensions,
125 * - width, height: for exact requested size.
126 * Returns the target size as hash array with width, height properties.
128 * @param {number} width Source width.
129 * @param {number} height Source height.
130 * @param {Object} options Resizing options as a hash array.
131 * @return {Object} Dimensions, eg. {width: 100, height: 50}.
133 ImageLoader
.resizeDimensions = function(width
, height
, options
) {
134 var sourceWidth
= width
;
135 var sourceHeight
= height
;
137 // Flip dimensions for odd orientation values: 1 (90deg) and 3 (270deg).
138 if (options
.orientation
&& options
.orientation
% 2) {
139 sourceWidth
= height
;
140 sourceHeight
= width
;
143 var targetWidth
= sourceWidth
;
144 var targetHeight
= sourceHeight
;
146 if ('scale' in options
) {
147 targetWidth
= sourceWidth
* options
.scale
;
148 targetHeight
= sourceHeight
* options
.scale
;
151 if (options
.maxWidth
&&
152 targetWidth
> options
.maxWidth
) {
153 var scale
= options
.maxWidth
/ targetWidth
;
154 targetWidth
*= scale
;
155 targetHeight
*= scale
;
158 if (options
.maxHeight
&&
159 targetHeight
> options
.maxHeight
) {
160 var scale
= options
.maxHeight
/ targetHeight
;
161 targetWidth
*= scale
;
162 targetHeight
*= scale
;
166 targetWidth
= options
.width
;
169 targetHeight
= options
.height
;
171 targetWidth
= Math
.round(targetWidth
);
172 targetHeight
= Math
.round(targetHeight
);
174 return {width
: targetWidth
, height
: targetHeight
};
178 * Performs resizing of the source image into the target canvas.
180 * @param {HTMLCanvasElement|Image} source Source image or canvas.
181 * @param {HTMLCanvasElement} target Target canvas.
182 * @param {Object} options Resizing options as a hash array.
184 ImageLoader
.resize = function(source
, target
, options
) {
185 var targetDimensions
= ImageLoader
.resizeDimensions(
186 source
.width
, source
.height
, options
);
188 target
.width
= targetDimensions
.width
;
189 target
.height
= targetDimensions
.height
;
191 // Default orientation is 0deg.
192 var orientation
= options
.orientation
|| 0;
194 // For odd orientation values: 1 (90deg) and 3 (270deg) flip dimensions.
197 if (orientation
% 2) {
198 drawImageWidth
= target
.height
;
199 drawImageHeight
= target
.width
;
201 drawImageWidth
= target
.width
;
202 drawImageHeight
= target
.height
;
205 var targetContext
= target
.getContext('2d');
206 targetContext
.save();
207 targetContext
.translate(target
.width
/ 2, target
.height
/ 2);
208 targetContext
.rotate(orientation
* Math
.PI
/ 2);
209 targetContext
.drawImage(
212 source
.width
, source
.height
,
213 -drawImageWidth
/ 2, -drawImageHeight
/ 2,
214 drawImageWidth
, drawImageHeight
);
215 targetContext
.restore();