OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 /** |
6 * Loads and resizes an image. | 6 * Loads and resizes an image. |
7 * @constructor | 7 * @constructor |
8 */ | 8 */ |
9 function ImageLoader() { | 9 function ImageLoader() { |
10 /** | 10 /** |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 if (options.height) | 197 if (options.height) |
198 targetHeight = options.height; | 198 targetHeight = options.height; |
199 | 199 |
200 targetWidth = Math.round(targetWidth); | 200 targetWidth = Math.round(targetWidth); |
201 targetHeight = Math.round(targetHeight); | 201 targetHeight = Math.round(targetHeight); |
202 | 202 |
203 return {width: targetWidth, height: targetHeight}; | 203 return {width: targetWidth, height: targetHeight}; |
204 }; | 204 }; |
205 | 205 |
206 /** | 206 /** |
207 * Performs resizing of the source image into the target canvas. | 207 * Performs resizing and cropping of the source image into the target canvas. |
208 * | 208 * |
209 * @param {HTMLCanvasElement|Image} source Source image or canvas. | 209 * @param {HTMLCanvasElement|Image} source Source image or canvas. |
210 * @param {HTMLCanvasElement} target Target canvas. | 210 * @param {HTMLCanvasElement} target Target canvas. |
211 * @param {Object} options Resizing options as a hash array. | 211 * @param {Object} options Resizing options as a hash array. |
212 */ | 212 */ |
213 ImageLoader.resize = function(source, target, options) { | 213 ImageLoader.resizeAndCrop = function(source, target, options) { |
214 var targetDimensions = ImageLoader.resizeDimensions( | 214 // Default orientation is 0deg. |
| 215 var orientation = |
| 216 ImageOrientation.fromDriveOrientation(options.orientation || 0); |
| 217 |
| 218 // Calculates copy parameters. |
| 219 var copyParameters = ImageLoader.calculateCopyParameters(source, options); |
| 220 target.width = copyParameters.canvas.width; |
| 221 target.height = copyParameters.canvas.height; |
| 222 |
| 223 // Apply. |
| 224 var targetContext = |
| 225 /** @type {CanvasRenderingContext2D} */ (target.getContext('2d')); |
| 226 targetContext.save(); |
| 227 orientation.cancelImageOrientation( |
| 228 targetContext, copyParameters.target.width, copyParameters.target.height); |
| 229 targetContext.drawImage( |
| 230 source, |
| 231 copyParameters.source.x, |
| 232 copyParameters.source.y, |
| 233 copyParameters.source.width, |
| 234 copyParameters.source.height, |
| 235 copyParameters.target.x, |
| 236 copyParameters.target.y, |
| 237 copyParameters.target.width, |
| 238 copyParameters.target.height); |
| 239 targetContext.restore(); |
| 240 }; |
| 241 |
| 242 /** |
| 243 * @typedef {{ |
| 244 * source: {x:number, y:number, width:number, height:number}, |
| 245 * target: {x:number, y:number, width:number, height:number}, |
| 246 * canvas: {width:number, height:number} |
| 247 * }} |
| 248 */ |
| 249 ImageLoader.CopyParameters; |
| 250 |
| 251 /** |
| 252 * Calculates copy parameters. |
| 253 * |
| 254 * @param {HTMLCanvasElement|Image} source Source image or canvas. |
| 255 * @param {Object} options Resizing options as a hash array. |
| 256 * @return {!ImageLoader.CopyParameters} Calculated copy parameters. |
| 257 */ |
| 258 ImageLoader.calculateCopyParameters = function(source, options) { |
| 259 if (options.crop) { |
| 260 // When an image is cropped, target should be a fixed size square. |
| 261 assert(options.width); |
| 262 assert(options.height); |
| 263 assert(options.width === options.height); |
| 264 |
| 265 // The length of shorter edge becomes dimension of cropped area in the |
| 266 // source. |
| 267 var cropSourceDimension = Math.min(source.width, source.height); |
| 268 |
| 269 return { |
| 270 source: { |
| 271 x: Math.floor((source.width / 2) - (cropSourceDimension / 2)), |
| 272 y: Math.floor((source.height / 2) - (cropSourceDimension / 2)), |
| 273 width: cropSourceDimension, |
| 274 height: cropSourceDimension |
| 275 }, |
| 276 target: { |
| 277 x: 0, |
| 278 y: 0, |
| 279 width: options.width, |
| 280 height: options.height |
| 281 }, |
| 282 canvas: { |
| 283 width: options.width, |
| 284 height: options.height |
| 285 } |
| 286 }; |
| 287 } |
| 288 |
| 289 // Target dimension is calculated in the rotated(transformed) coordinate. |
| 290 var targetCanvasDimensions = ImageLoader.resizeDimensions( |
215 source.width, source.height, options); | 291 source.width, source.height, options); |
216 | 292 |
217 // Default orientation is 0deg. | 293 var targetDimensions = targetCanvasDimensions; |
218 var orientation = options.orientation || new ImageOrientation(1, 0, 0, 1); | 294 if (options.orientation && options.orientation % 2) { |
219 var size = orientation.getSizeAfterCancelling( | 295 targetDimensions = { |
220 targetDimensions.width, targetDimensions.height); | 296 width: targetCanvasDimensions.height, |
221 target.width = size.width; | 297 height: targetCanvasDimensions.width |
222 target.height = size.height; | 298 }; |
| 299 } |
223 | 300 |
224 var targetContext = target.getContext('2d'); | 301 return { |
225 targetContext.save(); | 302 source: { |
226 orientation.cancelImageOrientation( | 303 x: 0, |
227 targetContext, targetDimensions.width, targetDimensions.height); | 304 y: 0, |
228 targetContext.drawImage( | 305 width: source.width, |
229 source, | 306 height: source.height |
230 0, 0, source.width, source.height, | 307 }, |
231 0, 0, targetDimensions.width, targetDimensions.height); | 308 target: { |
232 targetContext.restore(); | 309 x: 0, |
| 310 y: 0, |
| 311 width: targetDimensions.width, |
| 312 height: targetDimensions.height |
| 313 }, |
| 314 canvas: { |
| 315 width: targetCanvasDimensions.width, |
| 316 height: targetCanvasDimensions.height |
| 317 } |
| 318 }; |
233 }; | 319 }; |
234 | 320 |
235 /** | 321 /** |
236 * Matrix converts AdobeRGB color space into sRGB color space. | 322 * Matrix converts AdobeRGB color space into sRGB color space. |
237 * @const {!Array<number>} | 323 * @const {!Array<number>} |
238 */ | 324 */ |
239 ImageLoader.MATRIX_FROM_ADOBE_TO_STANDARD = [ | 325 ImageLoader.MATRIX_FROM_ADOBE_TO_STANDARD = [ |
240 1.39836, -0.39836, 0.00000, | 326 1.39836, -0.39836, 0.00000, |
241 0.00000, 1.00000, 0.00000, | 327 0.00000, 1.00000, 0.00000, |
242 0.00000, -0.04293, 1.04293 | 328 0.00000, -0.04293, 1.04293 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 sB = sB <= 0.0031308 ? 12.92 * sB : 1.055 * Math.pow(sB, 1 / 2.4) - 0.055; | 363 sB = sB <= 0.0031308 ? 12.92 * sB : 1.055 * Math.pow(sB, 1 / 2.4) - 0.055; |
278 | 364 |
279 // Scale to [0, 255]. | 365 // Scale to [0, 255]. |
280 data[i] = Math.max(0, Math.min(255, sR * 255)); | 366 data[i] = Math.max(0, Math.min(255, sR * 255)); |
281 data[i + 1] = Math.max(0, Math.min(255, sG * 255)); | 367 data[i + 1] = Math.max(0, Math.min(255, sG * 255)); |
282 data[i + 2] = Math.max(0, Math.min(255, sB * 255)); | 368 data[i + 2] = Math.max(0, Math.min(255, sB * 255)); |
283 } | 369 } |
284 context.putImageData(imageData, 0, 0); | 370 context.putImageData(imageData, 0, 0); |
285 } | 371 } |
286 }; | 372 }; |
OLD | NEW |