Home | History | Annotate | Download | only in image_editor
      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
      3 // found in the LICENSE file.
      4 
      5 'use strict';
      6 
      7 /**
      8  * The base class for simple filters that only modify the image content
      9  * but do not modify the image dimensions.
     10  * @constructor
     11  * @extends {ImageEditor.Mode}
     12  */
     13 ImageEditor.Mode.Adjust = function() {
     14   ImageEditor.Mode.apply(this, arguments);
     15   this.implicitCommit = true;
     16   this.doneMessage_ = null;
     17   this.viewportGeneration_ = 0;
     18 };
     19 
     20 ImageEditor.Mode.Adjust.prototype = {__proto__: ImageEditor.Mode.prototype};
     21 
     22 /** @override */
     23 ImageEditor.Mode.Adjust.prototype.getCommand = function() {
     24   if (!this.filter_) return null;
     25 
     26   return new Command.Filter(this.name, this.filter_, this.doneMessage_);
     27 };
     28 
     29 /** @override */
     30 ImageEditor.Mode.Adjust.prototype.cleanUpUI = function() {
     31   ImageEditor.Mode.prototype.cleanUpUI.apply(this, arguments);
     32   this.hidePreview();
     33 };
     34 
     35 /**
     36  * TODO(JSDOC)
     37  */
     38 ImageEditor.Mode.Adjust.prototype.hidePreview = function() {
     39   if (this.canvas_) {
     40     this.canvas_.parentNode.removeChild(this.canvas_);
     41     this.canvas_ = null;
     42   }
     43 };
     44 
     45 /**
     46  * TODO(JSDOC)
     47  */
     48 ImageEditor.Mode.Adjust.prototype.cleanUpCaches = function() {
     49   this.filter_ = null;
     50   this.previewImageData_ = null;
     51 };
     52 
     53 /**
     54  * TODO(JSDOC)
     55  */
     56 ImageEditor.Mode.Adjust.prototype.reset = function() {
     57   ImageEditor.Mode.prototype.reset.call(this);
     58   this.hidePreview();
     59   this.cleanUpCaches();
     60 };
     61 
     62 /**
     63  * TODO(JSDOC)
     64  * @param {Object} options  // TODO(JSDOC).
     65  */
     66 ImageEditor.Mode.Adjust.prototype.update = function(options) {
     67   ImageEditor.Mode.prototype.update.apply(this, arguments);
     68 
     69   // We assume filter names are used in the UI directly.
     70   // This will have to change with i18n.
     71   this.filter_ = this.createFilter(options);
     72   this.updatePreviewImage();
     73   ImageUtil.trace.resetTimer('preview');
     74   this.filter_(this.previewImageData_, this.originalImageData, 0, 0);
     75   ImageUtil.trace.reportTimer('preview');
     76   this.canvas_.getContext('2d').putImageData(
     77       this.previewImageData_, 0, 0);
     78 };
     79 
     80 /**
     81  * Copy the source image data for the preview.
     82  * Use the cached copy if the viewport has not changed.
     83  */
     84 ImageEditor.Mode.Adjust.prototype.updatePreviewImage = function() {
     85   if (!this.previewImageData_ ||
     86       this.viewportGeneration_ != this.getViewport().getCacheGeneration()) {
     87     this.viewportGeneration_ = this.getViewport().getCacheGeneration();
     88 
     89     if (!this.canvas_) {
     90       this.canvas_ = this.getImageView().createOverlayCanvas();
     91     }
     92 
     93     this.getImageView().setupDeviceBuffer(this.canvas_);
     94 
     95     this.originalImageData = this.getImageView().copyScreenImageData();
     96     this.previewImageData_ = this.getImageView().copyScreenImageData();
     97   }
     98 };
     99 
    100 /*
    101  * Own methods
    102  */
    103 
    104 /**
    105  * TODO(JSDOC)
    106  * @param {Object} options  // TODO(JSDOC).
    107  * @return {function(ImageData,ImageData,number,number)} Created function.
    108  */
    109 ImageEditor.Mode.Adjust.prototype.createFilter = function(options) {
    110   return filter.create(this.name, options);
    111 };
    112 
    113 /**
    114  * A base class for color filters that are scale independent.
    115  * @constructor
    116  */
    117 ImageEditor.Mode.ColorFilter = function() {
    118   ImageEditor.Mode.Adjust.apply(this, arguments);
    119 };
    120 
    121 ImageEditor.Mode.ColorFilter.prototype =
    122     {__proto__: ImageEditor.Mode.Adjust.prototype};
    123 
    124 /**
    125  * TODO(JSDOC)
    126  * @return {{r: Array.<number>, g: Array.<number>, b: Array.<number>}}
    127  *    histogram.
    128  */
    129 ImageEditor.Mode.ColorFilter.prototype.getHistogram = function() {
    130   return filter.getHistogram(this.getImageView().getThumbnail());
    131 };
    132 
    133 /**
    134  * Exposure/contrast filter.
    135  * @constructor
    136  */
    137 ImageEditor.Mode.Exposure = function() {
    138   ImageEditor.Mode.ColorFilter.call(this, 'exposure', 'GALLERY_EXPOSURE');
    139 };
    140 
    141 ImageEditor.Mode.Exposure.prototype =
    142     {__proto__: ImageEditor.Mode.ColorFilter.prototype};
    143 
    144 /**
    145  * TODO(JSDOC)
    146  * @param {ImageEditor.Toolbar} toolbar The toolbar to populate.
    147  */
    148 ImageEditor.Mode.Exposure.prototype.createTools = function(toolbar) {
    149   toolbar.addRange('brightness', 'GALLERY_BRIGHTNESS', -1, 0, 1, 100);
    150   toolbar.addRange('contrast', 'GALLERY_CONTRAST', -1, 0, 1, 100);
    151 };
    152 
    153 /**
    154  * Autofix.
    155  * @constructor
    156  */
    157 ImageEditor.Mode.Autofix = function() {
    158   ImageEditor.Mode.ColorFilter.call(this, 'autofix', 'GALLERY_AUTOFIX');
    159   this.doneMessage_ = 'GALLERY_FIXED';
    160 };
    161 
    162 ImageEditor.Mode.Autofix.prototype =
    163     {__proto__: ImageEditor.Mode.ColorFilter.prototype};
    164 
    165 /**
    166  * TODO(JSDOC)
    167  * @param {ImageEditor.Toolbar} toolbar The toolbar to populate.
    168  */
    169 ImageEditor.Mode.Autofix.prototype.createTools = function(toolbar) {
    170   var self = this;
    171   toolbar.addButton('Apply', this.apply.bind(this));
    172 };
    173 
    174 /**
    175  * TODO(JSDOC)
    176  * @return {boolean}  // TODO(JSDOC).
    177  */
    178 ImageEditor.Mode.Autofix.prototype.isApplicable = function() {
    179   return this.getImageView().hasValidImage() &&
    180       filter.autofix.isApplicable(this.getHistogram());
    181 };
    182 
    183 /**
    184  * TODO(JSDOC)
    185  */
    186 ImageEditor.Mode.Autofix.prototype.apply = function() {
    187   this.update({histogram: this.getHistogram()});
    188 };
    189 
    190 /**
    191  * Instant Autofix.
    192  * @constructor
    193  */
    194 ImageEditor.Mode.InstantAutofix = function() {
    195   ImageEditor.Mode.Autofix.apply(this, arguments);
    196   this.instant = true;
    197 };
    198 
    199 ImageEditor.Mode.InstantAutofix.prototype =
    200     {__proto__: ImageEditor.Mode.Autofix.prototype};
    201 
    202 /**
    203  * TODO(JSDOC)
    204  */
    205 ImageEditor.Mode.InstantAutofix.prototype.setUp = function() {
    206   ImageEditor.Mode.Autofix.prototype.setUp.apply(this, arguments);
    207   this.apply();
    208 };
    209 
    210 /**
    211  * Blur filter.
    212  * @constructor
    213  */
    214 ImageEditor.Mode.Blur = function() {
    215   ImageEditor.Mode.Adjust.call(this, 'blur');
    216 };
    217 
    218 ImageEditor.Mode.Blur.prototype =
    219     {__proto__: ImageEditor.Mode.Adjust.prototype};
    220 
    221 /**
    222  * TODO(JSDOC)
    223  * @param {ImageEditor.Toolbar} toolbar The toolbar to populate.
    224  */
    225 ImageEditor.Mode.Blur.prototype.createTools = function(toolbar) {
    226   toolbar.addRange('strength', 'GALLERY_STRENGTH', 0, 0, 1, 100);
    227   toolbar.addRange('radius', 'GALLERY_RADIUS', 1, 1, 3);
    228 };
    229 
    230 /**
    231  * Sharpen filter.
    232  * @constructor
    233  */
    234 ImageEditor.Mode.Sharpen = function() {
    235   ImageEditor.Mode.Adjust.call(this, 'sharpen');
    236 };
    237 
    238 ImageEditor.Mode.Sharpen.prototype =
    239     {__proto__: ImageEditor.Mode.Adjust.prototype};
    240 
    241 /**
    242  * TODO(JSDOC)
    243  * @param {ImageEditor.Toolbar} toolbar The toolbar to populate.
    244  */
    245 ImageEditor.Mode.Sharpen.prototype.createTools = function(toolbar) {
    246   toolbar.addRange('strength', 'GALLERY_STRENGTH', 0, 0, 1, 100);
    247   toolbar.addRange('radius', 'GALLERY_RADIUS', 1, 1, 3);
    248 };
    249