/* * Copyright 2017 Laszlo Balazs-Csiki * * This file is part of Pixelitor. Pixelitor is free software: you * can redistribute it and/or modify it under the terms of the GNU * General Public License, version 3 as published by the Free * Software Foundation. * * Pixelitor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Pixelitor. If not, see <http://www.gnu.org/licenses/>. */ package pixelitor.filters; import pixelitor.filters.gui.ColorParam; import pixelitor.filters.gui.ParamSet; import pixelitor.filters.gui.RangeParam; import pixelitor.filters.gui.ShowOriginal; import pixelitor.filters.lookup.LuminanceLookup; import pixelitor.utils.ImageUtils; import java.awt.Color; import java.awt.image.BufferedImage; import static pixelitor.filters.gui.ColorParam.OpacitySetting.NO_OPACITY; /** * Colorize */ public class Colorize extends FilterWithParametrizedGUI { public static final String NAME = "Colorize"; private final RangeParam adjustBrightness = new RangeParam("Adjust Brightness", -100, 0, 100); private final ColorParam colorParam = new ColorParam("Color:", new Color(255, 207, 119), NO_OPACITY); private final RangeParam opacityParam = new RangeParam("Amount (%)", 0, 100, 100); public Colorize() { super(ShowOriginal.YES); setParamSet(new ParamSet( colorParam, adjustBrightness, opacityParam )); } @Override public BufferedImage doTransform(BufferedImage src, BufferedImage dest) { float briShift = adjustBrightness.getValueAsPercentage(); float opacity = opacityParam.getValueAsPercentage(); Color colorizeColor = colorParam.getColor(); return colorize(src, dest, colorizeColor, briShift, opacity); } public static BufferedImage colorize(BufferedImage src, BufferedImage dest, Color colorizeColor, float briShift, float opacity) { float translucence = 1 - opacity; int[] srcData = ImageUtils.getPixelsAsArray(src); int[] destData = ImageUtils.getPixelsAsArray(dest); int colorizeR = colorizeColor.getRed(); int colorizeG = colorizeColor.getGreen(); int colorizeB = colorizeColor.getBlue(); // The final R,G,B values depend on the colorize R,G,B values and on the luminosity of the source pixels. // For performance reasons the luminosity will be the index in these lookup tables int[] redLookup = new int[256]; int[] greenLookup = new int[256]; int[] blueLookup = new int[256]; for (int i = 0; i < 256; i++) { redLookup[i] = (i * colorizeR) / 255; greenLookup[i] = (i * colorizeG) / 255; blueLookup[i] = (i * colorizeB) / 255; } int length = srcData.length; for (int i = 0; i < length; i++) { int rgb = srcData[i]; int a = rgb & 0xFF000000; int lum = LuminanceLookup.getLuminosity(rgb); if (briShift > 0) { lum = (int) ((float) lum * (1.0f - briShift)); lum += 255 - (1.0f - briShift) * 255.0f; } else if (briShift < 0) { lum = (int) ((float) lum * (briShift + 1.0f)); } int destRed = redLookup[lum]; int destGreen = greenLookup[lum]; int destBlue = blueLookup[lum]; if (opacity < 1.0f) { int r = (rgb >>> 16) & 0xFF; int g = (rgb >>> 8) & 0xFF; int b = rgb & 0xFF; destRed = (int) (destRed * opacity + r * translucence); destGreen = (int) (destGreen * opacity + g * translucence); destBlue = (int) (destBlue * opacity + b * translucence); } destData[i] = a | (destRed << 16) | (destGreen << 8) | destBlue; } return dest; } @Override public boolean supportsGray() { return false; } }