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

Side by Side Diff: ui/file_manager/gallery/js/image_editor/image_util.js

Issue 1608143002: support animated GIF (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: ensure that fade attr. is false & do not animate Created 4 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 // Namespace object for the utilities. 5 // Namespace object for the utilities.
6 var ImageUtil = {}; 6 var ImageUtil = {};
7 7
8 /** 8 /**
9 * Performance trace. 9 * Performance trace.
10 */ 10 */
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 */ 433 */
434 ImageUtil.ImageLoader = function(document, metadataModel) { 434 ImageUtil.ImageLoader = function(document, metadataModel) {
435 this.document_ = document; 435 this.document_ = document;
436 436
437 /** 437 /**
438 * @private {!MetadataModel} 438 * @private {!MetadataModel}
439 * @const 439 * @const
440 */ 440 */
441 this.metadataModel_ = metadataModel; 441 this.metadataModel_ = metadataModel;
442 442
443 this.image_ = new Image();
444 this.generation_ = 0; 443 this.generation_ = 0;
445 444
446 /** 445 /**
447 * @type {number} 446 * @type {number}
448 * @private 447 * @private
449 */ 448 */
450 this.timeout_ = 0; 449 this.timeout_ = 0;
451 450
452 /** 451 /**
453 * @type {?function(!HTMLCanvasElement, string=)} 452 * @type {?function(!HTMLCanvasElement, string=)}
(...skipping 19 matching lines...) Expand all
473 * @param {number=} opt_delay Load delay in milliseconds, useful to let the 472 * @param {number=} opt_delay Load delay in milliseconds, useful to let the
474 * animations play out before the computation heavy image loading starts. 473 * animations play out before the computation heavy image loading starts.
475 */ 474 */
476 ImageUtil.ImageLoader.prototype.load = function(item, callback, opt_delay) { 475 ImageUtil.ImageLoader.prototype.load = function(item, callback, opt_delay) {
477 var entry = item.getEntry(); 476 var entry = item.getEntry();
478 477
479 this.cancel(); 478 this.cancel();
480 this.entry_ = entry; 479 this.entry_ = entry;
481 this.callback_ = callback; 480 this.callback_ = callback;
482 481
483 var targetImage = this.image_; 482 var targetImage = assertInstanceof(this.document_.createElement('img'),
483 HTMLImageElement);
484 // The transform fetcher is not cancellable so we need a generation counter. 484 // The transform fetcher is not cancellable so we need a generation counter.
485 var generation = ++this.generation_; 485 var generation = ++this.generation_;
486 486
487 /** 487 /**
488 * @param {!HTMLImageElement} image Image to be transformed. 488 * @param {!HTMLImageElement} image Image to be transformed.
489 * @param {Object=} opt_transform Transformation. 489 * @param {Object=} opt_transform Transformation.
490 */ 490 */
491 var onTransform = function(image, opt_transform) { 491 var onTransform = function(image, opt_transform) {
492 if (generation === this.generation_) { 492 if (generation === this.generation_) {
493 this.convertImage_( 493 this.convertImage_(image, opt_transform);
494 image, opt_transform || { scaleX: 1, scaleY: 1, rotate90: 0});
495 } 494 }
496 }; 495 };
497 onTransform = onTransform.bind(this); 496 onTransform = onTransform.bind(this);
498 497
499 /** 498 /**
500 * @param {string=} opt_error Error. 499 * @param {string=} opt_error Error.
501 */ 500 */
502 var onError = function(opt_error) { 501 var onError = function(opt_error) {
503 targetImage.onerror = null; 502 targetImage.onerror = null;
504 targetImage.onload = null; 503 targetImage.onload = null;
(...skipping 10 matching lines...) Expand all
515 var loadImage = function(url) { 514 var loadImage = function(url) {
516 if (generation !== this.generation_) 515 if (generation !== this.generation_)
517 return; 516 return;
518 517
519 ImageUtil.metrics.startInterval(ImageUtil.getMetricName('LoadTime')); 518 ImageUtil.metrics.startInterval(ImageUtil.getMetricName('LoadTime'));
520 this.timeout_ = 0; 519 this.timeout_ = 0;
521 520
522 targetImage.onload = function() { 521 targetImage.onload = function() {
523 targetImage.onerror = null; 522 targetImage.onerror = null;
524 targetImage.onload = null; 523 targetImage.onload = null;
524 if (generation !== this.generation_)
525 return;
525 this.metadataModel_.get([entry], ['contentImageTransform']).then( 526 this.metadataModel_.get([entry], ['contentImageTransform']).then(
526 function(metadataItems) { 527 function(metadataItems) {
528 if (generation !== this.generation_)
yawano 2016/01/21 09:11:32 nit: I don't think we need this second check since
ryoh 2016/01/22 01:15:54 That's right!
529 return;
527 onTransform(targetImage, metadataItems[0].contentImageTransform); 530 onTransform(targetImage, metadataItems[0].contentImageTransform);
528 }.bind(this)); 531 }.bind(this));
529 }.bind(this); 532 }.bind(this);
530 533
531 // The error callback has an optional error argument, which in case of a 534 // The error callback has an optional error argument, which in case of a
532 // general error should not be specified 535 // general error should not be specified
533 targetImage.onerror = onError.bind(null, 'GALLERY_IMAGE_ERROR'); 536 targetImage.onerror = onError.bind(null, 'GALLERY_IMAGE_ERROR');
534 537
535 targetImage.src = url; 538 targetImage.src = url;
536 }.bind(this); 539 }.bind(this);
537 540
538 // Loads the image. If already loaded, then forces a reload. 541 // Loads the image. If already loaded, then forces a reload.
539 var startLoad = function() { 542 var startLoad = function() {
540 if (generation !== this.generation_) 543 if (generation !== this.generation_)
541 return; 544 return;
542 545
543 // Target current image.
544 targetImage = this.image_;
545
546 // Obtain target URL. 546 // Obtain target URL.
547 if (FileType.isRaw(entry)) { 547 if (FileType.isRaw(entry)) {
548 var timestamp = 548 var timestamp =
549 item.getMetadataItem() && 549 item.getMetadataItem() &&
550 item.getMetadataItem().modificationTime && 550 item.getMetadataItem().modificationTime &&
551 item.getMetadataItem().modificationTime.getTime(); 551 item.getMetadataItem().modificationTime.getTime();
552 ImageLoaderClient.getInstance().load(entry.toURL(), function(result) { 552 ImageLoaderClient.getInstance().load(entry.toURL(), function(result) {
553 if (generation !== this.generation_) 553 if (generation !== this.generation_)
554 return; 554 return;
555 if (result.status === 'success') 555 if (result.status === 'success')
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 * Stops loading image. 603 * Stops loading image.
604 */ 604 */
605 ImageUtil.ImageLoader.prototype.cancel = function() { 605 ImageUtil.ImageLoader.prototype.cancel = function() {
606 if (!this.callback_) 606 if (!this.callback_)
607 return; 607 return;
608 this.callback_ = null; 608 this.callback_ = null;
609 if (this.timeout_) { 609 if (this.timeout_) {
610 clearTimeout(this.timeout_); 610 clearTimeout(this.timeout_);
611 this.timeout_ = 0; 611 this.timeout_ = 0;
612 } 612 }
613 if (this.image_) {
614 this.image_.onload = function() {};
615 this.image_.onerror = function() {};
616 // Force to free internal image by assigning empty image.
617 this.image_.src = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAA' +
618 'AAABAAEAAAICTAEAOw==';
619 this.image_ = document.createElement('img');
620 }
621 this.generation_++; // Silence the transform fetcher if it is in progress. 613 this.generation_++; // Silence the transform fetcher if it is in progress.
622 }; 614 };
623 615
624 /** 616 /**
625 * @param {!HTMLImageElement} image Image to be transformed. 617 * @param {!HTMLImageElement} image Image to be transformed.
626 * @param {!Object} transform transformation description to apply to the image. 618 * @param {!Object} transform transformation description to apply to the image.
627 * @private 619 * @private
628 */ 620 */
629 ImageUtil.ImageLoader.prototype.convertImage_ = function(image, transform) { 621 ImageUtil.ImageLoader.prototype.convertImage_ = function(image, transform) {
622 if (!transform ||
623 (transform.rotate90 === 0 &&
624 transform.scaleX === 1 &&
625 transform.scaleY === 1)) {
626 setTimeout(this.callback_, 0, image);
627 this.callback_ = null;
628 return;
629 }
630 var canvas = this.document_.createElement('canvas'); 630 var canvas = this.document_.createElement('canvas');
631 631
632 if (transform.rotate90 & 1) { // Rotated +/-90deg, swap the dimensions. 632 if (transform.rotate90 & 1) { // Rotated +/-90deg, swap the dimensions.
633 canvas.width = image.height; 633 canvas.width = image.height;
634 canvas.height = image.width; 634 canvas.height = image.width;
635 } else { 635 } else {
636 canvas.width = image.width; 636 canvas.width = image.width;
637 canvas.height = image.height; 637 canvas.height = image.height;
638 } 638 }
639 639
(...skipping 23 matching lines...) Expand all
663 context.drawImage( 663 context.drawImage(
664 image, 0, firstRow, image.width, lastRow - firstRow, 664 image, 0, firstRow, image.width, lastRow - firstRow,
665 -image.width / 2, firstRow - image.height / 2, 665 -image.width / 2, firstRow - image.height / 2,
666 image.width, lastRow - firstRow); 666 image.width, lastRow - firstRow);
667 667
668 if (lastRow === image.height) { 668 if (lastRow === image.height) {
669 context.restore(); 669 context.restore();
670 if (this.entry_.toURL().substr(0, 5) !== 'data:') { // Ignore data urls. 670 if (this.entry_.toURL().substr(0, 5) !== 'data:') { // Ignore data urls.
671 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('LoadTime')); 671 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('LoadTime'));
672 } 672 }
673 try { 673 setTimeout(this.callback_, 0, context.canvas);
674 setTimeout(this.callback_, 0, context.canvas);
675 } catch (e) {
676 console.error(e);
677 }
678 this.callback_ = null; 674 this.callback_ = null;
679 } else { 675 } else {
680 var self = this; 676 var self = this;
681 this.timeout_ = setTimeout( 677 this.timeout_ = setTimeout(
682 function() { 678 function() {
683 self.timeout_ = 0; 679 self.timeout_ = 0;
684 self.copyStrip_(context, image, lastRow, rowCount); 680 self.copyStrip_(context, image, lastRow, rowCount);
685 }, 0); 681 }, 0);
686 } 682 }
687 }; 683 };
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 721
726 /** 722 /**
727 * @param {string} name Local name. 723 * @param {string} name Local name.
728 * @return {string} Full name. 724 * @return {string} Full name.
729 */ 725 */
730 ImageUtil.getMetricName = function(name) { 726 ImageUtil.getMetricName = function(name) {
731 return 'PhotoEditor.' + name; 727 return 'PhotoEditor.' + name;
732 }; 728 };
733 729
734 /** 730 /**
731 * Ensures argument is canvas. If it's not, creates new canvas and copy.
732 *
733 * @param {!HTMLCanvasElement|!HTMLImageElement} imgOrCanvas image or canvas
734 * element
735 * @return {!HTMLCanvasElement} canvas.
736 */
737 ImageUtil.ensureCanvas = function(imgOrCanvas) {
738 if(imgOrCanvas.tagName === 'canvas') {
739 return assertInstanceof(imgOrCanvas, HTMLCanvasElement);
740 }
741 var canvas = assertInstanceof(document.createElement('canvas'),
742 HTMLCanvasElement);
743 canvas.width = imgOrCanvas.width;
744 canvas.height = imgOrCanvas.height;
745 var context = canvas.getContext('2d');
746 context.drawImage(imgOrCanvas, 0, 0);
747 return canvas;
748 };
749
750 /**
735 * Used for metrics reporting, keep in sync with the histogram description. 751 * Used for metrics reporting, keep in sync with the histogram description.
736 * @type {Array<string>} 752 * @type {Array<string>}
737 * @const 753 * @const
738 */ 754 */
739 ImageUtil.FILE_TYPES = ['jpg', 'png', 'gif', 'bmp', 'webp']; 755 ImageUtil.FILE_TYPES = ['jpg', 'png', 'gif', 'bmp', 'webp'];
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698