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

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

Issue 2678723002: Compile several targets in Gallery in gyp v2. (Closed)
Patch Set: Rebased. Created 3 years, 9 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 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 */ 413 */
414 ImageUtil.setClass = function(element, className, on) { 414 ImageUtil.setClass = function(element, className, on) {
415 var cl = element.classList; 415 var cl = element.classList;
416 if (on) 416 if (on)
417 cl.add(className); 417 cl.add(className);
418 else 418 else
419 cl.remove(className); 419 cl.remove(className);
420 }; 420 };
421 421
422 /** 422 /**
423 * ImageLoader loads an image from a given Entry into a canvas in two steps:
424 * 1. Loads the image into an HTMLImageElement.
425 * 2. Copies pixels from HTMLImageElement to HTMLCanvasElement. This is done
426 * stripe-by-stripe to avoid freezing up the UI. The transform is taken into
427 * account.
428 *
429 * @param {!HTMLDocument} document Owner document.
430 * @param {!MetadataModel} metadataModel
431 * @constructor
432 * @struct
433 */
434 ImageUtil.ImageLoader = function(document, metadataModel) {
435 this.document_ = document;
436
437 /**
438 * @private {!MetadataModel}
439 * @const
440 */
441 this.metadataModel_ = metadataModel;
442
443 this.generation_ = 0;
444
445 /**
446 * @type {number}
447 * @private
448 */
449 this.timeout_ = 0;
450
451 /**
452 * @type {?function(!HTMLCanvasElement, string=)}
453 * @private
454 */
455 this.callback_ = null;
456
457 /**
458 * @type {FileEntry}
459 * @private
460 */
461 this.entry_ = null;
462 };
463
464 /**
465 * Loads an image.
466 * TODO(mtomasz): Simplify, or even get rid of this class and merge with the
467 * ThumbnaiLoader class.
468 *
469 * @param {!GalleryItem} item Item representing the image to be loaded.
470 * @param {function(!HTMLCanvasElement, string=)} callback Callback to be
471 * called when loaded. The second optional argument is an error identifier.
472 * @param {number=} opt_delay Load delay in milliseconds, useful to let the
473 * animations play out before the computation heavy image loading starts.
474 */
475 ImageUtil.ImageLoader.prototype.load = function(item, callback, opt_delay) {
476 var entry = item.getEntry();
477
478 this.cancel();
479 this.entry_ = entry;
480 this.callback_ = callback;
481
482 var targetImage = assertInstanceof(this.document_.createElement('img'),
483 HTMLImageElement);
484 // The transform fetcher is not cancellable so we need a generation counter.
485 var generation = ++this.generation_;
486
487 /**
488 * @param {!HTMLImageElement} image Image to be transformed.
489 * @param {Object=} opt_transform Transformation.
490 */
491 var onTransform = function(image, opt_transform) {
492 if (generation === this.generation_) {
493 this.convertImage_(image, opt_transform);
494 }
495 };
496 onTransform = onTransform.bind(this);
497
498 /**
499 * @param {string=} opt_error Error.
500 */
501 var onError = function(opt_error) {
502 targetImage.onerror = null;
503 targetImage.onload = null;
504 var tmpCallback = this.callback_;
505 this.callback_ = null;
506 var emptyCanvas = assertInstanceof(this.document_.createElement('canvas'),
507 HTMLCanvasElement);
508 emptyCanvas.width = 0;
509 emptyCanvas.height = 0;
510 tmpCallback(emptyCanvas, opt_error);
511 };
512 onError = onError.bind(this);
513
514 var loadImage = function(url) {
515 if (generation !== this.generation_)
516 return;
517
518 ImageUtil.metrics.startInterval(ImageUtil.getMetricName('LoadTime'));
519 this.timeout_ = 0;
520
521 targetImage.onload = function() {
522 targetImage.onerror = null;
523 targetImage.onload = null;
524 if (generation !== this.generation_)
525 return;
526 this.metadataModel_.get([entry], ['contentImageTransform']).then(
527 function(metadataItems) {
528 onTransform(targetImage, metadataItems[0].contentImageTransform);
529 }.bind(this));
530 }.bind(this);
531
532 // The error callback has an optional error argument, which in case of a
533 // general error should not be specified
534 targetImage.onerror = onError.bind(null, 'GALLERY_IMAGE_ERROR');
535
536 targetImage.src = url;
537 }.bind(this);
538
539 // Loads the image. If already loaded, then forces a reload.
540 var startLoad = function() {
541 if (generation !== this.generation_)
542 return;
543
544 // Obtain target URL.
545 if (FileType.isRaw(entry)) {
546 var timestamp =
547 item.getMetadataItem() &&
548 item.getMetadataItem().modificationTime &&
549 item.getMetadataItem().modificationTime.getTime();
550 ImageLoaderClient.getInstance().load(entry.toURL(), function(result) {
551 if (generation !== this.generation_)
552 return;
553 if (result.status === 'success')
554 loadImage(result.data);
555 else
556 onError('GALLERY_IMAGE_ERROR');
557 }.bind(this), {
558 cache: true,
559 timestamp: timestamp,
560 priority: 0 // Use highest priority to show main image.
561 });
562 return;
563 }
564
565 // Load the image directly. The query parameter is workaround for
566 // crbug.com/379678, which force to update the contents of the image.
567 loadImage(entry.toURL() + '?nocache=' + Date.now());
568 }.bind(this);
569
570 if (opt_delay) {
571 this.timeout_ = setTimeout(startLoad, opt_delay);
572 } else {
573 startLoad();
574 }
575 };
576
577 /**
578 * @return {boolean} True if an image is loading.
579 */
580 ImageUtil.ImageLoader.prototype.isBusy = function() {
581 return !!this.callback_;
582 };
583
584 /**
585 * @param {Entry} entry Image entry.
586 * @return {boolean} True if loader loads this image.
587 */
588 ImageUtil.ImageLoader.prototype.isLoading = function(entry) {
589 return this.isBusy() && util.isSameEntry(this.entry_, entry);
590 };
591
592 /**
593 * @param {function(!HTMLCanvasElement, string=)} callback To be called when the
594 * image loaded.
595 */
596 ImageUtil.ImageLoader.prototype.setCallback = function(callback) {
597 this.callback_ = callback;
598 };
599
600 /**
601 * Stops loading image.
602 */
603 ImageUtil.ImageLoader.prototype.cancel = function() {
604 if (!this.callback_)
605 return;
606 this.callback_ = null;
607 if (this.timeout_) {
608 clearTimeout(this.timeout_);
609 this.timeout_ = 0;
610 }
611 this.generation_++; // Silence the transform fetcher if it is in progress.
612 };
613
614 /**
615 * @param {!HTMLImageElement} image Image to be transformed.
616 * @param {!Object} transform transformation description to apply to the image.
617 * @private
618 */
619 ImageUtil.ImageLoader.prototype.convertImage_ = function(image, transform) {
620 if (!transform ||
621 (transform.rotate90 === 0 &&
622 transform.scaleX === 1 &&
623 transform.scaleY === 1)) {
624 setTimeout(this.callback_, 0, image);
625 this.callback_ = null;
626 return;
627 }
628 var canvas = this.document_.createElement('canvas');
629
630 if (transform.rotate90 & 1) { // Rotated +/-90deg, swap the dimensions.
631 canvas.width = image.height;
632 canvas.height = image.width;
633 } else {
634 canvas.width = image.width;
635 canvas.height = image.height;
636 }
637
638 var context = canvas.getContext('2d');
639 context.save();
640 context.translate(canvas.width / 2, canvas.height / 2);
641 context.rotate(transform.rotate90 * Math.PI / 2);
642 context.scale(transform.scaleX, transform.scaleY);
643
644 var stripCount = Math.ceil(image.width * image.height / (1 << 21));
645 var step = Math.max(16, Math.ceil(image.height / stripCount)) & 0xFFFFF0;
646
647 this.copyStrip_(context, image, 0, step);
648 };
649
650 /**
651 * @param {!CanvasRenderingContext2D} context Context to draw.
652 * @param {!HTMLImageElement} image Image to draw.
653 * @param {number} firstRow Number of the first pixel row to draw.
654 * @param {number} rowCount Count of pixel rows to draw.
655 * @private
656 */
657 ImageUtil.ImageLoader.prototype.copyStrip_ = function(
658 context, image, firstRow, rowCount) {
659 var lastRow = Math.min(firstRow + rowCount, image.height);
660
661 context.drawImage(
662 image, 0, firstRow, image.width, lastRow - firstRow,
663 -image.width / 2, firstRow - image.height / 2,
664 image.width, lastRow - firstRow);
665
666 if (lastRow === image.height) {
667 context.restore();
668 if (this.entry_.toURL().substr(0, 5) !== 'data:') { // Ignore data urls.
669 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('LoadTime'));
670 }
671 setTimeout(this.callback_, 0, context.canvas);
672 this.callback_ = null;
673 } else {
674 var self = this;
675 this.timeout_ = setTimeout(
676 function() {
677 self.timeout_ = 0;
678 self.copyStrip_(context, image, lastRow, rowCount);
679 }, 0);
680 }
681 };
682
683 /**
684 * @param {!HTMLElement} element To remove children from. 423 * @param {!HTMLElement} element To remove children from.
685 */ 424 */
686 ImageUtil.removeChildren = function(element) { 425 ImageUtil.removeChildren = function(element) {
687 element.textContent = ''; 426 element.textContent = '';
688 }; 427 };
689 428
690 /** 429 /**
691 * @param {string} name File name (with extension). 430 * @param {string} name File name (with extension).
692 * @return {string} File name without extension. 431 * @return {string} File name without extension.
693 */ 432 */
(...skipping 11 matching lines...) Expand all
705 */ 444 */
706 ImageUtil.getExtensionFromFullName = function(name) { 445 ImageUtil.getExtensionFromFullName = function(name) {
707 var index = name.lastIndexOf('.'); 446 var index = name.lastIndexOf('.');
708 if (index !== -1) 447 if (index !== -1)
709 return name.substring(index); 448 return name.substring(index);
710 else 449 else
711 return ''; 450 return '';
712 }; 451 };
713 452
714 /** 453 /**
715 * Metrics (from metrics.js) itnitialized by the File Manager from owner frame.
716 * @type {Object}
717 */
718 ImageUtil.metrics = null;
719
720 /**
721 * @param {string} name Local name. 454 * @param {string} name Local name.
722 * @return {string} Full name. 455 * @return {string} Full name.
723 */ 456 */
724 ImageUtil.getMetricName = function(name) { 457 ImageUtil.getMetricName = function(name) {
725 return 'PhotoEditor.' + name; 458 return 'PhotoEditor.' + name;
726 }; 459 };
727 460
728 /** 461 /**
729 * Ensures argument is canvas. If it's not, creates new canvas and copy. 462 * Ensures argument is canvas. If it's not, creates new canvas and copy.
730 * 463 *
(...skipping 13 matching lines...) Expand all
744 context.drawImage(imgOrCanvas, 0, 0); 477 context.drawImage(imgOrCanvas, 0, 0);
745 return canvas; 478 return canvas;
746 }; 479 };
747 480
748 /** 481 /**
749 * Used for metrics reporting, keep in sync with the histogram description. 482 * Used for metrics reporting, keep in sync with the histogram description.
750 * @type {Array<string>} 483 * @type {Array<string>}
751 * @const 484 * @const
752 */ 485 */
753 ImageUtil.FILE_TYPES = ['jpg', 'png', 'gif', 'bmp', 'webp']; 486 ImageUtil.FILE_TYPES = ['jpg', 'png', 'gif', 'bmp', 'webp'];
OLDNEW
« no previous file with comments | « ui/file_manager/gallery/js/image_editor/image_loader.js ('k') | ui/file_manager/gallery/js/image_editor/image_view.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698