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

Side by Side Diff: ui/file_manager/file_manager/foreground/js/thumbnail_loader.js

Issue 2630283002: Apply image transformation for thumbnails loaded by loadDetachedImage. (Closed)
Patch Set: Add comment. 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 a thumbnail using provided url. In CANVAS mode, loaded images 6 * Loads a thumbnail using provided url. In CANVAS mode, loaded images
7 * are attached as <canvas> element, while in IMAGE mode as <img>. 7 * are attached as <canvas> element, while in IMAGE mode as <img>.
8 * <canvas> renders faster than <img>, however has bigger memory overhead. 8 * <canvas> renders faster than <img>, however has bigger memory overhead.
9 * 9 *
10 * @param {Entry} entry File entry. 10 * @param {Entry} entry File entry.
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 }.bind(this)).then(function(result) { 317 }.bind(this)).then(function(result) {
318 if (!this.transform_) 318 if (!this.transform_)
319 return result; 319 return result;
320 else 320 else
321 return this.applyTransformToDataUrl_( 321 return this.applyTransformToDataUrl_(
322 this.transform_, result.data, result.width, result.height); 322 this.transform_, result.data, result.width, result.height);
323 }.bind(this)); 323 }.bind(this));
324 }; 324 };
325 325
326 /** 326 /**
327 * Renders an Image to canvas applying an image transformation.
328 * @param {Image} image Original image. Can be an unattached one to an elment.
329 * @param {number} width width of the original image
oka 2017/01/16 12:30:54 nit: Width of the ...? (instead of width).
330 * @param {number} height height of the original image
oka 2017/01/16 12:30:54 nit: Height of the ...? (instead of height).
331 * @param {{scaleX:number, scaleY:number, rotate90: number}} transform
332 * Transform.
333 * @param {!Object} canvas
334 */
335 ThumbnailLoader.prototype.renderImageToCanvasWithTransform_ = function(
336 image, width, height, transform, canvas) {
337 var scaleX = transform.scaleX;
338 var scaleY = transform.scaleY;
339 var rotate90 = transform.rotate90;
340
341 assert(scaleX === 1 || scaleX === -1);
342 assert(scaleY === 1 || scaleY === -1);
343 assert(rotate90 === 0 || rotate90 === 1);
344
345 var context = canvas.getContext('2d');
346
347 canvas.width = rotate90 === 1 ? height : width;
348 canvas.height = rotate90 === 1 ? width : height;
349
350 // Scale transformation should be applied before rotate transformation.
351 // i.e. When matrices for scale and rotate are A and B, transformation matrix
352 // should be BA.
353
354 // Rotate 90 degree at center.
355 if (rotate90 === 1) {
356 context.translate(height, 0);
357 context.rotate(Math.PI / 2);
358 }
359
360 // Flip X and Y.
361 context.translate(scaleX === -1 ? width : 0, scaleY === -1 ? height : 0);
362 context.scale(scaleX, scaleY);
363 context.drawImage(image, 0, 0);
364 };
365
366 /**
327 * Applies transform to data url. 367 * Applies transform to data url.
328 * 368 *
329 * @param {{scaleX:number, scaleY:number, rotate90: number}} transform 369 * @param {{scaleX:number, scaleY:number, rotate90: number}} transform
330 * Transform. 370 * Transform.
331 * @param {string} dataUrl Data url. 371 * @param {string} dataUrl Data url.
332 * @param {number} width Width. 372 * @param {number} width Width.
333 * @param {number} height Height. 373 * @param {number} height Height.
334 * @return {!Promise<{data:string, width:number, height:number}>} A promise 374 * @return {!Promise<{data:string, width:number, height:number}>} A promise
335 * which is resolved with dataUrl and its width and height. 375 * which is resolved with dataUrl and its width and height.
336 * @private 376 * @private
337 */ 377 */
338 ThumbnailLoader.prototype.applyTransformToDataUrl_ = function( 378 ThumbnailLoader.prototype.applyTransformToDataUrl_ = function(
339 transform, dataUrl, width, height) { 379 transform, dataUrl, width, height) {
340 var image = new Image(); 380 var image = new Image();
341 var scaleX = this.transform_.scaleX;
342 var scaleY = this.transform_.scaleY;
343 var rotate90 = this.transform_.rotate90;
344
345 assert(scaleX === 1 || scaleX === -1);
346 assert(scaleY === 1 || scaleY === -1);
347 assert(rotate90 === 0 || rotate90 === 1);
348 381
349 return new Promise(function(resolve, reject) { 382 return new Promise(function(resolve, reject) {
350 // Decode image for transformation. 383 // Decode image for transformation.
351 image.onload = resolve; 384 image.onload = resolve;
352 image.onerror = reject; 385 image.onerror = reject;
353 image.src = dataUrl; 386 image.src = dataUrl;
354 }).then(function() { 387 }).then(function() {
355 // Apply transform. Scale transformation should be applied before rotate
356 // transformation. i.e. When matrices for scale and rotate are A and B,
357 // transformation matrix should be BA.
358 var canvas = document.createElement('canvas'); 388 var canvas = document.createElement('canvas');
359 var context = canvas.getContext('2d'); 389 this.renderImageToCanvasWithTransform_(
360 390 image, width, height, this.transform_, canvas);
361 canvas.width = rotate90 === 1 ? height : width;
362 canvas.height = rotate90 === 1 ? width : height;
363
364 // Rotate 90 degree at center.
365 if (rotate90 === 1) {
366 context.translate(height, 0);
367 context.rotate(Math.PI / 2);
368 }
369
370 // Flip X and Y.
371 context.translate(scaleX === -1 ? width : 0, scaleY === -1 ? height : 0);
372 context.scale(scaleX, scaleY);
373
374 context.drawImage(image, 0, 0);
375
376 return { 391 return {
377 data: canvas.toDataURL('image/png'), 392 data: canvas.toDataURL('image/png'),
378 width: canvas.width, 393 width: canvas.width,
379 height: canvas.height 394 height: canvas.height
380 }; 395 };
381 }.bind(this)); 396 }.bind(this));
382 } 397 }
383 398
384 /** 399 /**
385 * Cancels loading the current image. 400 * Cancels loading the current image.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 * @private 481 * @private
467 */ 482 */
468 ThumbnailLoader.prototype.renderMedia_ = function() { 483 ThumbnailLoader.prototype.renderMedia_ = function() {
469 if (this.loaderType_ !== ThumbnailLoader.LoaderType.CANVAS) 484 if (this.loaderType_ !== ThumbnailLoader.LoaderType.CANVAS)
470 return; 485 return;
471 486
472 if (!this.canvas_) 487 if (!this.canvas_)
473 this.canvas_ = document.createElement('canvas'); 488 this.canvas_ = document.createElement('canvas');
474 489
475 // Copy the image to a canvas if the canvas is outdated. 490 // Copy the image to a canvas if the canvas is outdated.
491 // At this point, image transformation is not applied because we attach style
492 // attribute to an img element in attachImage() instead.
476 if (!this.canvasUpToDate_) { 493 if (!this.canvasUpToDate_) {
477 this.canvas_.width = this.image_.width; 494 this.canvas_.width = this.image_.width;
478 this.canvas_.height = this.image_.height; 495 this.canvas_.height = this.image_.height;
479 var context = this.canvas_.getContext('2d'); 496 var context = this.canvas_.getContext('2d');
480 context.drawImage(this.image_, 0, 0); 497 context.drawImage(this.image_, 0, 0);
481 this.canvasUpToDate_ = true; 498 this.canvasUpToDate_ = true;
482 } 499 }
483 }; 500 };
484 501
485 /** 502 /**
(...skipping 28 matching lines...) Expand all
514 box.textContent = ''; 531 box.textContent = '';
515 box.appendChild(attachableMedia); 532 box.appendChild(attachableMedia);
516 } 533 }
517 534
518 if (!this.taskId_) 535 if (!this.taskId_)
519 attachableMedia.classList.add('cached'); 536 attachableMedia.classList.add('cached');
520 }; 537 };
521 538
522 /** 539 /**
523 * Gets the loaded image. 540 * Gets the loaded image.
524 * TODO(mtomasz): Apply transformations.
525 * 541 *
526 * @return {Image|HTMLCanvasElement} Either image or a canvas object. 542 * @return {Image|HTMLCanvasElement} Either image or a canvas object.
527 */ 543 */
528 ThumbnailLoader.prototype.getImage = function() { 544 ThumbnailLoader.prototype.getImage = function() {
529 this.renderMedia_(); 545 this.renderMedia_();
530 return this.loaderType_ === ThumbnailLoader.LoaderType.CANVAS ? this.canvas_ : 546 if (this.loaderType_ === ThumbnailLoader.LoaderType.IMAGE)
531 this.image_; 547 // TODO(yamaguchi): Fix image orientation in case of detached image loaded
548 // in IMAGE mode. Either apply transformation here or return
549 // this.transform_ as well.
550 return this.image_;
551 if (this.transform_) {
552 this.renderImageToCanvasWithTransform_(
553 this.image_, this.image_.width, this.image_.height,
554 this.transform_, this.canvas_);
555 }
556 return this.canvas_;
532 }; 557 };
533 558
534 /** 559 /**
535 * Update the image style to fit/fill the container. 560 * Update the image style to fit/fill the container.
536 * 561 *
537 * Using webkit center packing does not align the image properly, so we need 562 * Using webkit center packing does not align the image properly, so we need
538 * to wait until the image loads and its dimensions are known, then manually 563 * to wait until the image loads and its dimensions are known, then manually
539 * position it at the center. 564 * position it at the center.
540 * 565 *
541 * @param {Element} box Containing element. 566 * @param {Element} box Containing element.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 637
613 function percent(fraction) { 638 function percent(fraction) {
614 return (fraction * 100).toFixed(2) + '%'; 639 return (fraction * 100).toFixed(2) + '%';
615 } 640 }
616 641
617 img.style.width = percent(fractionX); 642 img.style.width = percent(fractionX);
618 img.style.height = percent(fractionY); 643 img.style.height = percent(fractionY);
619 img.style.left = percent((1 - fractionX) / 2); 644 img.style.left = percent((1 - fractionX) / 2);
620 img.style.top = percent((1 - fractionY) / 2); 645 img.style.top = percent((1 - fractionY) / 2);
621 }; 646 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698