2
* $Id: ColorTintFilter.java,v 1.10 2007/02/13 22:22:04 gfx Exp $
4
* Dual-licensed under LGPL (Sun and Romain Guy) and BSD (Romain Guy).
6
* Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle,
7
* Santa Clara, California 95054, U.S.A. All rights reserved.
9
* Copyright (c) 2006 Romain Guy <romain.guy@mac.com>
10
* All rights reserved.
12
* Redistribution and use in source and binary forms, with or without
13
* modification, are permitted provided that the following conditions
15
* 1. Redistributions of source code must retain the above copyright
16
* notice, this list of conditions and the following disclaimer.
17
* 2. Redistributions in binary form must reproduce the above copyright
18
* notice, this list of conditions and the following disclaimer in the
19
* documentation and/or other materials provided with the distribution.
20
* 3. The name of the author may not be used to endorse or promote products
21
* derived from this software without specific prior written permission.
23
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
package org.jdesktop.swingx.image;
37
import java.awt.Color;
38
import java.awt.image.BufferedImage;
40
import org.jdesktop.swingx.graphics.GraphicsUtilities;
43
* <p>A color tint filter can be used to mix a solid color to an image. The
44
* result is an image tinted by the specified color. The force of the effect
45
* can be controlled with the <code>mixValue</code>, a number between 0.0 and
46
* 1.0 that can be seen as the percentage of the mix (0.0 does not affect the
47
* source image and 1.0 replaces all the pixels by the solid color).</p>
48
* <p>The color of the pixels in the resulting image is computed as follows:</p>
50
* cR = cS * (1 - mixValue) + cM * mixValue
52
* <p>Definition of the parameters:</p>
54
* <li><code>cR</code>: color of the resulting pixel</li>
55
* <li><code>cS</code>: color of the source pixel</li>
56
* <li><code>cM</code>: the solid color to mix with the source image</li>
57
* <li><code>mixValue</code>: strength of the mix, a value between 0.0 and 1.0</li>
60
* @author Romain Guy <romain.guy@mac.com>
63
public class ColorTintFilter extends AbstractFilter {
64
private final Color mixColor;
65
private final float mixValue;
67
private int[] preMultipliedRed;
68
private int[] preMultipliedGreen;
69
private int[] preMultipliedBlue;
72
* <p>Creates a new color mixer filter. The specified color will be used
73
* to tint the source image, with a mixing strength defined by
74
* <code>mixValue</code>.</p>
76
* @param mixColor the solid color to mix with the source image
77
* @param mixValue the strength of the mix, between 0.0 and 1.0; if the
78
* specified value lies outside this range, it is clamped
79
* @throws IllegalArgumentException if <code>mixColor</code> is null
81
public ColorTintFilter(Color mixColor, float mixValue) {
82
if (mixColor == null) {
83
throw new IllegalArgumentException("mixColor cannot be null");
86
this.mixColor = mixColor;
87
if (mixValue < 0.0f) {
89
} else if (mixValue > 1.0f) {
92
this.mixValue = mixValue;
94
int mix_r = (int) (mixColor.getRed() * mixValue);
95
int mix_g = (int) (mixColor.getGreen() * mixValue);
96
int mix_b = (int) (mixColor.getBlue() * mixValue);
98
// Since we use only lookup tables to apply the filter, this filter
99
// could be implemented as a LookupOp.
100
float factor = 1.0f - mixValue;
101
preMultipliedRed = new int[256];
102
preMultipliedGreen = new int[256];
103
preMultipliedBlue = new int[256];
105
for (int i = 0; i < 256; i++) {
106
int value = (int) (i * factor);
107
preMultipliedRed[i] = value + mix_r;
108
preMultipliedGreen[i] = value + mix_g;
109
preMultipliedBlue[i] = value + mix_b;
114
* <p>Returns the mix value of this filter.</p>
116
* @return the mix value, between 0.0 and 1.0
118
public float getMixValue() {
123
* <p>Returns the solid mix color of this filter.</p>
125
* @return the solid color used for mixing
127
public Color getMixColor() {
135
public BufferedImage filter(BufferedImage src, BufferedImage dst) {
137
dst = createCompatibleDestImage(src, null);
140
int width = src.getWidth();
141
int height = src.getHeight();
143
int[] pixels = new int[width * height];
144
GraphicsUtilities.getPixels(src, 0, 0, width, height, pixels);
146
GraphicsUtilities.setPixels(dst, 0, 0, width, height, pixels);
151
private void mixColor(int[] pixels) {
152
for (int i = 0; i < pixels.length; i++) {
153
int argb = pixels[i];
154
pixels[i] = (argb & 0xFF000000) |
155
preMultipliedRed[(argb >> 16) & 0xFF] << 16 |
156
preMultipliedGreen[(argb >> 8) & 0xFF] << 8 |
157
preMultipliedBlue[argb & 0xFF];