| Index: chrome/browser/resources/file_manager/js/image_editor/filter.js
|
| diff --git a/chrome/browser/resources/file_manager/js/image_editor/filter.js b/chrome/browser/resources/file_manager/js/image_editor/filter.js
|
| deleted file mode 100644
|
| index e06d4ef2dd86b9ecc81fa3a9d1392c95114415a1..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/resources/file_manager/js/image_editor/filter.js
|
| +++ /dev/null
|
| @@ -1,612 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -'use strict';
|
| -
|
| -/**
|
| - * A namespace for image filter utilities.
|
| - */
|
| -var filter = {};
|
| -
|
| -/**
|
| - * Create a filter from name and options.
|
| - *
|
| - * @param {string} name Maps to a filter method name.
|
| - * @param {Object} options A map of filter-specific options.
|
| - * @return {function(ImageData,ImageData,number,number)} created function.
|
| - */
|
| -filter.create = function(name, options) {
|
| - var filterFunc = filter[name](options);
|
| - return function() {
|
| - var time = Date.now();
|
| - filterFunc.apply(null, arguments);
|
| - var dst = arguments[0];
|
| - var mPixPerSec = dst.width * dst.height / 1000 / (Date.now() - time);
|
| - ImageUtil.trace.report(name, Math.round(mPixPerSec * 10) / 10 + 'Mps');
|
| - }
|
| -};
|
| -
|
| -/**
|
| - * Apply a filter to a image by splitting it into strips.
|
| - *
|
| - * To be used with large images to avoid freezing up the UI.
|
| - *
|
| - * @param {HTMLCanvasElement} dstCanvas Destination canvas.
|
| - * @param {HTMLCanvasElement} srcCanvas Source canvas.
|
| - * @param {function(ImageData,ImageData,number,number)} filterFunc Filter.
|
| - * @param {function(number, number)} progressCallback Progress callback.
|
| - * @param {number} maxPixelsPerStrip Pixel number to process at once.
|
| - */
|
| -filter.applyByStrips = function(
|
| - dstCanvas, srcCanvas, filterFunc, progressCallback, maxPixelsPerStrip) {
|
| - var dstContext = dstCanvas.getContext('2d');
|
| - var srcContext = srcCanvas.getContext('2d');
|
| - var source = srcContext.getImageData(0, 0, srcCanvas.width, srcCanvas.height);
|
| -
|
| - var stripCount = Math.ceil(srcCanvas.width * srcCanvas.height /
|
| - (maxPixelsPerStrip || 1000000)); // 1 Mpix is a reasonable default.
|
| -
|
| - var strip = srcContext.getImageData(0, 0,
|
| - srcCanvas.width, Math.ceil(srcCanvas.height / stripCount));
|
| -
|
| - var offset = 0;
|
| -
|
| - function filterStrip() {
|
| - // If the strip overlaps the bottom of the source image we cannot shrink it
|
| - // and we cannot fill it partially (since canvas.putImageData always draws
|
| - // the entire buffer).
|
| - // Instead we move the strip up several lines (converting those lines
|
| - // twice is a small price to pay).
|
| - if (offset > source.height - strip.height) {
|
| - offset = source.height - strip.height;
|
| - }
|
| -
|
| - filterFunc(strip, source, 0, offset);
|
| - dstContext.putImageData(strip, 0, offset);
|
| -
|
| - offset += strip.height;
|
| -
|
| - if (offset < source.height) {
|
| - setTimeout(filterStrip, 0);
|
| - } else {
|
| - ImageUtil.trace.reportTimer('filter-commit');
|
| - }
|
| -
|
| - progressCallback(offset, source.height);
|
| - }
|
| -
|
| - ImageUtil.trace.resetTimer('filter-commit');
|
| - filterStrip();
|
| -};
|
| -
|
| -/**
|
| - * Return a color histogram for an image.
|
| - *
|
| - * @param {HTMLCanvasElement|ImageData} source Image data to analyze.
|
| - * @return {{r: Array.<number>, g: Array.<number>, b: Array.<number>}}
|
| - * histogram.
|
| - */
|
| -filter.getHistogram = function(source) {
|
| - var imageData;
|
| - if (source.constructor.name == 'HTMLCanvasElement') {
|
| - imageData = source.getContext('2d').
|
| - getImageData(0, 0, source.width, source.height);
|
| - } else {
|
| - imageData = source;
|
| - }
|
| -
|
| - var r = [];
|
| - var g = [];
|
| - var b = [];
|
| -
|
| - for (var i = 0; i != 256; i++) {
|
| - r.push(0);
|
| - g.push(0);
|
| - b.push(0);
|
| - }
|
| -
|
| - var data = imageData.data;
|
| - var maxIndex = 4 * imageData.width * imageData.height;
|
| - for (var index = 0; index != maxIndex;) {
|
| - r[data[index++]]++;
|
| - g[data[index++]]++;
|
| - b[data[index++]]++;
|
| - index++;
|
| - }
|
| -
|
| - return { r: r, g: g, b: b };
|
| -};
|
| -
|
| -/**
|
| - * Compute the function for every integer value from 0 up to maxArg.
|
| - *
|
| - * Rounds and clips the results to fit the [0..255] range.
|
| - * Useful to speed up pixel manipulations.
|
| - *
|
| - * @param {number} maxArg Maximum argument value (inclusive).
|
| - * @param {function(number): number} func Function to precompute.
|
| - * @return {Uint8Array} Computed results.
|
| - */
|
| -filter.precompute = function(maxArg, func) {
|
| - var results = new Uint8Array(maxArg + 1);
|
| - for (var arg = 0; arg <= maxArg; arg++) {
|
| - results[arg] = Math.max(0, Math.min(0xFF, Math.round(func(arg))));
|
| - }
|
| - return results;
|
| -};
|
| -
|
| -/**
|
| - * Convert pixels by applying conversion tables to each channel individually.
|
| - *
|
| - * @param {Array.<number>} rMap Red channel conversion table.
|
| - * @param {Array.<number>} gMap Green channel conversion table.
|
| - * @param {Array.<number>} bMap Blue channel conversion table.
|
| - * @param {ImageData} dst Destination image data. Can be smaller than the
|
| - * source, must completely fit inside the source.
|
| - * @param {ImageData} src Source image data.
|
| - * @param {number} offsetX Horizontal offset of dst relative to src.
|
| - * @param {number} offsetY Vertical offset of dst relative to src.
|
| - */
|
| -filter.mapPixels = function(rMap, gMap, bMap, dst, src, offsetX, offsetY) {
|
| - var dstData = dst.data;
|
| - var dstWidth = dst.width;
|
| - var dstHeight = dst.height;
|
| -
|
| - var srcData = src.data;
|
| - var srcWidth = src.width;
|
| - var srcHeight = src.height;
|
| -
|
| - if (offsetX < 0 || offsetX + dstWidth > srcWidth ||
|
| - offsetY < 0 || offsetY + dstHeight > srcHeight)
|
| - throw new Error('Invalid offset');
|
| -
|
| - var dstIndex = 0;
|
| - for (var y = 0; y != dstHeight; y++) {
|
| - var srcIndex = (offsetX + (offsetY + y) * srcWidth) * 4;
|
| - for (var x = 0; x != dstWidth; x++) {
|
| - dstData[dstIndex++] = rMap[srcData[srcIndex++]];
|
| - dstData[dstIndex++] = gMap[srcData[srcIndex++]];
|
| - dstData[dstIndex++] = bMap[srcData[srcIndex++]];
|
| - dstIndex++;
|
| - srcIndex++;
|
| - }
|
| - }
|
| -};
|
| -
|
| -/**
|
| - * Number of digits after period(in binary form) to preserve.
|
| - * @type {number}
|
| - */
|
| -filter.FIXED_POINT_SHIFT = 16;
|
| -
|
| -/**
|
| - * Maximum value that can be represented in fixed point without overflow.
|
| - * @type {number}
|
| - */
|
| -filter.MAX_FLOAT_VALUE = 0x7FFFFFFF >> filter.FIXED_POINT_SHIFT;
|
| -
|
| -/**
|
| - * Converts floating point to fixed.
|
| - * @param {number} x Number to convert.
|
| - * @return {number} Converted number.
|
| - */
|
| -filter.floatToFixedPoint = function(x) {
|
| - // Math.round on negative arguments causes V8 to deoptimize the calling
|
| - // function, so we are using >> 0 instead.
|
| - return (x * (1 << filter.FIXED_POINT_SHIFT)) >> 0;
|
| -};
|
| -
|
| -/**
|
| - * Perform an image convolution with a symmetrical 5x5 matrix:
|
| - *
|
| - * 0 0 w3 0 0
|
| - * 0 w2 w1 w2 0
|
| - * w3 w1 w0 w1 w3
|
| - * 0 w2 w1 w2 0
|
| - * 0 0 w3 0 0
|
| - *
|
| - * @param {Array.<number>} weights See the picture above.
|
| - * @param {ImageData} dst Destination image data. Can be smaller than the
|
| - * source, must completely fit inside the source.
|
| - * @param {ImageData} src Source image data.
|
| - * @param {number} offsetX Horizontal offset of dst relative to src.
|
| - * @param {number} offsetY Vertical offset of dst relative to src.
|
| - */
|
| -filter.convolve5x5 = function(weights, dst, src, offsetX, offsetY) {
|
| - var w0 = filter.floatToFixedPoint(weights[0]);
|
| - var w1 = filter.floatToFixedPoint(weights[1]);
|
| - var w2 = filter.floatToFixedPoint(weights[2]);
|
| - var w3 = filter.floatToFixedPoint(weights[3]);
|
| -
|
| - var dstData = dst.data;
|
| - var dstWidth = dst.width;
|
| - var dstHeight = dst.height;
|
| - var dstStride = dstWidth * 4;
|
| -
|
| - var srcData = src.data;
|
| - var srcWidth = src.width;
|
| - var srcHeight = src.height;
|
| - var srcStride = srcWidth * 4;
|
| - var srcStride2 = srcStride * 2;
|
| -
|
| - if (offsetX < 0 || offsetX + dstWidth > srcWidth ||
|
| - offsetY < 0 || offsetY + dstHeight > srcHeight)
|
| - throw new Error('Invalid offset');
|
| -
|
| - // Javascript is not very good at inlining constants.
|
| - // We inline manually and assert that the constant is equal to the variable.
|
| - if (filter.FIXED_POINT_SHIFT != 16)
|
| - throw new Error('Wrong fixed point shift');
|
| -
|
| - var margin = 2;
|
| -
|
| - var startX = Math.max(0, margin - offsetX);
|
| - var endX = Math.min(dstWidth, srcWidth - margin - offsetX);
|
| -
|
| - var startY = Math.max(0, margin - offsetY);
|
| - var endY = Math.min(dstHeight, srcHeight - margin - offsetY);
|
| -
|
| - for (var y = startY; y != endY; y++) {
|
| - var dstIndex = y * dstStride + startX * 4;
|
| - var srcIndex = (y + offsetY) * srcStride + (startX + offsetX) * 4;
|
| -
|
| - for (var x = startX; x != endX; x++) {
|
| - for (var c = 0; c != 3; c++) {
|
| - var sum = w0 * srcData[srcIndex] +
|
| - w1 * (srcData[srcIndex - 4] +
|
| - srcData[srcIndex + 4] +
|
| - srcData[srcIndex - srcStride] +
|
| - srcData[srcIndex + srcStride]) +
|
| - w2 * (srcData[srcIndex - srcStride - 4] +
|
| - srcData[srcIndex + srcStride - 4] +
|
| - srcData[srcIndex - srcStride + 4] +
|
| - srcData[srcIndex + srcStride + 4]) +
|
| - w3 * (srcData[srcIndex - 8] +
|
| - srcData[srcIndex + 8] +
|
| - srcData[srcIndex - srcStride2] +
|
| - srcData[srcIndex + srcStride2]);
|
| - if (sum < 0)
|
| - dstData[dstIndex++] = 0;
|
| - else if (sum > 0xFF0000)
|
| - dstData[dstIndex++] = 0xFF;
|
| - else
|
| - dstData[dstIndex++] = sum >> 16;
|
| - srcIndex++;
|
| - }
|
| - srcIndex++;
|
| - dstIndex++;
|
| - }
|
| - }
|
| -};
|
| -
|
| -/**
|
| - * Compute the average color for the image.
|
| - *
|
| - * @param {ImageData} imageData Image data to analyze.
|
| - * @return {{r: number, g: number, b: number}} average color.
|
| - */
|
| -filter.getAverageColor = function(imageData) {
|
| - var data = imageData.data;
|
| - var width = imageData.width;
|
| - var height = imageData.height;
|
| -
|
| - var total = 0;
|
| - var r = 0;
|
| - var g = 0;
|
| - var b = 0;
|
| -
|
| - var maxIndex = 4 * width * height;
|
| - for (var i = 0; i != maxIndex;) {
|
| - total++;
|
| - r += data[i++];
|
| - g += data[i++];
|
| - b += data[i++];
|
| - i++;
|
| - }
|
| - if (total == 0) return { r: 0, g: 0, b: 0 };
|
| - return { r: r / total, g: g / total, b: b / total };
|
| -};
|
| -
|
| -/**
|
| - * Compute the average color with more weight given to pixes at the center.
|
| - *
|
| - * @param {ImageData} imageData Image data to analyze.
|
| - * @return {{r: number, g: number, b: number}} weighted average color.
|
| - */
|
| -filter.getWeightedAverageColor = function(imageData) {
|
| - var data = imageData.data;
|
| - var width = imageData.width;
|
| - var height = imageData.height;
|
| -
|
| - var total = 0;
|
| - var r = 0;
|
| - var g = 0;
|
| - var b = 0;
|
| -
|
| - var center = Math.floor(width / 2);
|
| - var maxDist = center * Math.sqrt(2);
|
| - maxDist *= 2; // Weaken the effect of distance
|
| -
|
| - var i = 0;
|
| - for (var x = 0; x != width; x++) {
|
| - for (var y = 0; y != height; y++) {
|
| - var dist = Math.sqrt(
|
| - (x - center) * (x - center) + (y - center) * (y - center));
|
| - var weight = (maxDist - dist) / maxDist;
|
| -
|
| - total += weight;
|
| - r += data[i++] * weight;
|
| - g += data[i++] * weight;
|
| - b += data[i++] * weight;
|
| - i++;
|
| - }
|
| - }
|
| - if (total == 0) return { r: 0, g: 0, b: 0 };
|
| - return { r: r / total, g: g / total, b: b / total };
|
| -};
|
| -
|
| -/**
|
| - * Copy part of src image to dst, applying matrix color filter on-the-fly.
|
| - *
|
| - * The copied part of src should completely fit into dst (there is no clipping
|
| - * on either side).
|
| - *
|
| - * @param {Array.<number>} matrix 3x3 color matrix.
|
| - * @param {ImageData} dst Destination image data.
|
| - * @param {ImageData} src Source image data.
|
| - * @param {number} offsetX X offset in source to start processing.
|
| - * @param {number} offsetY Y offset in source to start processing.
|
| - */
|
| -filter.colorMatrix3x3 = function(matrix, dst, src, offsetX, offsetY) {
|
| - var c11 = filter.floatToFixedPoint(matrix[0]);
|
| - var c12 = filter.floatToFixedPoint(matrix[1]);
|
| - var c13 = filter.floatToFixedPoint(matrix[2]);
|
| - var c21 = filter.floatToFixedPoint(matrix[3]);
|
| - var c22 = filter.floatToFixedPoint(matrix[4]);
|
| - var c23 = filter.floatToFixedPoint(matrix[5]);
|
| - var c31 = filter.floatToFixedPoint(matrix[6]);
|
| - var c32 = filter.floatToFixedPoint(matrix[7]);
|
| - var c33 = filter.floatToFixedPoint(matrix[8]);
|
| -
|
| - var dstData = dst.data;
|
| - var dstWidth = dst.width;
|
| - var dstHeight = dst.height;
|
| -
|
| - var srcData = src.data;
|
| - var srcWidth = src.width;
|
| - var srcHeight = src.height;
|
| -
|
| - if (offsetX < 0 || offsetX + dstWidth > srcWidth ||
|
| - offsetY < 0 || offsetY + dstHeight > srcHeight)
|
| - throw new Error('Invalid offset');
|
| -
|
| - // Javascript is not very good at inlining constants.
|
| - // We inline manually and assert that the constant is equal to the variable.
|
| - if (filter.FIXED_POINT_SHIFT != 16)
|
| - throw new Error('Wrong fixed point shift');
|
| -
|
| - var dstIndex = 0;
|
| - for (var y = 0; y != dstHeight; y++) {
|
| - var srcIndex = (offsetX + (offsetY + y) * srcWidth) * 4;
|
| - for (var x = 0; x != dstWidth; x++) {
|
| - var r = srcData[srcIndex++];
|
| - var g = srcData[srcIndex++];
|
| - var b = srcData[srcIndex++];
|
| - srcIndex++;
|
| -
|
| - var rNew = r * c11 + g * c12 + b * c13;
|
| - var gNew = r * c21 + g * c22 + b * c23;
|
| - var bNew = r * c31 + g * c32 + b * c33;
|
| -
|
| - if (rNew < 0) {
|
| - dstData[dstIndex++] = 0;
|
| - } else if (rNew > 0xFF0000) {
|
| - dstData[dstIndex++] = 0xFF;
|
| - } else {
|
| - dstData[dstIndex++] = rNew >> 16;
|
| - }
|
| -
|
| - if (gNew < 0) {
|
| - dstData[dstIndex++] = 0;
|
| - } else if (gNew > 0xFF0000) {
|
| - dstData[dstIndex++] = 0xFF;
|
| - } else {
|
| - dstData[dstIndex++] = gNew >> 16;
|
| - }
|
| -
|
| - if (bNew < 0) {
|
| - dstData[dstIndex++] = 0;
|
| - } else if (bNew > 0xFF0000) {
|
| - dstData[dstIndex++] = 0xFF;
|
| - } else {
|
| - dstData[dstIndex++] = bNew >> 16;
|
| - }
|
| -
|
| - dstIndex++;
|
| - }
|
| - }
|
| -};
|
| -
|
| -/**
|
| - * Return a convolution filter function bound to specific weights.
|
| - *
|
| - * @param {Array.<number>} weights Weights for the convolution matrix
|
| - * (not normalized).
|
| - * @return {function(ImageData,ImageData,number,number)} Convolution filter.
|
| - */
|
| -filter.createConvolutionFilter = function(weights) {
|
| - // Normalize the weights to sum to 1.
|
| - var total = 0;
|
| - for (var i = 0; i != weights.length; i++) {
|
| - total += weights[i] * (i ? 4 : 1);
|
| - }
|
| -
|
| - var normalized = [];
|
| - for (i = 0; i != weights.length; i++) {
|
| - normalized.push(weights[i] / total);
|
| - }
|
| - for (; i < 4; i++) {
|
| - normalized.push(0);
|
| - }
|
| -
|
| - var maxWeightedSum = 0xFF *
|
| - Math.abs(normalized[0]) +
|
| - Math.abs(normalized[1]) * 4 +
|
| - Math.abs(normalized[2]) * 4 +
|
| - Math.abs(normalized[3]) * 4;
|
| - if (maxWeightedSum > filter.MAX_FLOAT_VALUE)
|
| - throw new Error('convolve5x5 cannot convert the weights to fixed point');
|
| -
|
| - return filter.convolve5x5.bind(null, normalized);
|
| -};
|
| -
|
| -/**
|
| - * Creates matrix filter.
|
| - * @param {Array.<number>} matrix Color transformation matrix.
|
| - * @return {function(ImageData,ImageData,number,number)} Matrix filter.
|
| - */
|
| -filter.createColorMatrixFilter = function(matrix) {
|
| - for (var r = 0; r != 3; r++) {
|
| - var maxRowSum = 0;
|
| - for (var c = 0; c != 3; c++) {
|
| - maxRowSum += 0xFF * Math.abs(matrix[r * 3 + c]);
|
| - }
|
| - if (maxRowSum > filter.MAX_FLOAT_VALUE)
|
| - throw new Error(
|
| - 'colorMatrix3x3 cannot convert the matrix to fixed point');
|
| - }
|
| - return filter.colorMatrix3x3.bind(null, matrix);
|
| -};
|
| -
|
| -/**
|
| - * Return a blur filter.
|
| - * @param {Object} options Blur options.
|
| - * @return {function(ImageData,ImageData,number,number)} Blur filter.
|
| - */
|
| -filter.blur = function(options) {
|
| - if (options.radius == 1)
|
| - return filter.createConvolutionFilter(
|
| - [1, options.strength]);
|
| - else if (options.radius == 2)
|
| - return filter.createConvolutionFilter(
|
| - [1, options.strength, options.strength]);
|
| - else
|
| - return filter.createConvolutionFilter(
|
| - [1, options.strength, options.strength, options.strength]);
|
| -};
|
| -
|
| -/**
|
| - * Return a sharpen filter.
|
| - * @param {Object} options Sharpen options.
|
| - * @return {function(ImageData,ImageData,number,number)} Sharpen filter.
|
| - */
|
| -filter.sharpen = function(options) {
|
| - if (options.radius == 1)
|
| - return filter.createConvolutionFilter(
|
| - [5, -options.strength]);
|
| - else if (options.radius == 2)
|
| - return filter.createConvolutionFilter(
|
| - [10, -options.strength, -options.strength]);
|
| - else
|
| - return filter.createConvolutionFilter(
|
| - [15, -options.strength, -options.strength, -options.strength]);
|
| -};
|
| -
|
| -/**
|
| - * Return an exposure filter.
|
| - * @param {Object} options exposure options.
|
| - * @return {function(ImageData,ImageData,number,number)} Exposure filter.
|
| - */
|
| -filter.exposure = function(options) {
|
| - var pixelMap = filter.precompute(
|
| - 255,
|
| - function(value) {
|
| - if (options.brightness > 0) {
|
| - value *= (1 + options.brightness);
|
| - } else {
|
| - value += (0xFF - value) * options.brightness;
|
| - }
|
| - return 0x80 +
|
| - (value - 0x80) * Math.tan((options.contrast + 1) * Math.PI / 4);
|
| - });
|
| -
|
| - return filter.mapPixels.bind(null, pixelMap, pixelMap, pixelMap);
|
| -};
|
| -
|
| -/**
|
| - * Return a color autofix filter.
|
| - * @param {Object} options Histogram for autofix.
|
| - * @return {function(ImageData,ImageData,number,number)} Autofix filter.
|
| - */
|
| -filter.autofix = function(options) {
|
| - return filter.mapPixels.bind(null,
|
| - filter.autofix.stretchColors(options.histogram.r),
|
| - filter.autofix.stretchColors(options.histogram.g),
|
| - filter.autofix.stretchColors(options.histogram.b));
|
| -};
|
| -
|
| -/**
|
| - * Return a conversion table that stretches the range of colors used
|
| - * in the image to 0..255.
|
| - * @param {Array.<number>} channelHistogram Histogram to calculate range.
|
| - * @return {Uint8Array} Color mapping array.
|
| - */
|
| -filter.autofix.stretchColors = function(channelHistogram) {
|
| - var range = filter.autofix.getRange(channelHistogram);
|
| - return filter.precompute(
|
| - 255,
|
| - function(x) {
|
| - return (x - range.first) / (range.last - range.first) * 255;
|
| - }
|
| - );
|
| -};
|
| -
|
| -/**
|
| - * Return a range that encloses non-zero elements values in a histogram array.
|
| - * @param {Array.<number>} channelHistogram Histogram to analyze.
|
| - * @return {{first: number, last: number}} Channel range in histogram.
|
| - */
|
| -filter.autofix.getRange = function(channelHistogram) {
|
| - var first = 0;
|
| - while (first < channelHistogram.length && channelHistogram[first] == 0)
|
| - first++;
|
| -
|
| - var last = channelHistogram.length - 1;
|
| - while (last >= 0 && channelHistogram[last] == 0)
|
| - last--;
|
| -
|
| - if (first >= last) // Stretching does not make sense
|
| - return {first: 0, last: channelHistogram.length - 1};
|
| - else
|
| - return {first: first, last: last};
|
| -};
|
| -
|
| -/**
|
| - * Minimum channel offset that makes visual difference. If autofix calculated
|
| - * offset is less than SENSITIVITY, probably autofix is not needed.
|
| - * Reasonable empirical value.
|
| - * @type {number}
|
| - */
|
| -filter.autofix.SENSITIVITY = 8;
|
| -
|
| -/**
|
| - * @param {Array.<number>} channelHistogram Histogram to analyze.
|
| - * @return {boolean} True if stretching this range to 0..255 would make
|
| - * a visible difference.
|
| - */
|
| -filter.autofix.needsStretching = function(channelHistogram) {
|
| - var range = filter.autofix.getRange(channelHistogram);
|
| - return (range.first >= filter.autofix.SENSITIVITY ||
|
| - range.last <= 255 - filter.autofix.SENSITIVITY);
|
| -};
|
| -
|
| -/**
|
| - * @param {{r: Array.<number>, g: Array.<number>, b: Array.<number>}} histogram
|
| - * @return {boolean} True if the autofix would make a visible difference.
|
| - */
|
| -filter.autofix.isApplicable = function(histogram) {
|
| - return filter.autofix.needsStretching(histogram.r) ||
|
| - filter.autofix.needsStretching(histogram.g) ||
|
| - filter.autofix.needsStretching(histogram.b);
|
| -};
|
|
|