1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.imaging;
19
20 import java.awt.RenderingHints;
21 import java.awt.Transparency;
22 import java.awt.color.ColorSpace;
23 import java.awt.color.ICC_ColorSpace;
24 import java.awt.color.ICC_Profile;
25 import java.awt.image.BufferedImage;
26 import java.awt.image.ColorConvertOp;
27 import java.awt.image.ColorModel;
28 import java.awt.image.ComponentColorModel;
29 import java.awt.image.DirectColorModel;
30 import java.awt.image.ImagingOpException;
31 import java.io.File;
32 import java.io.IOException;
33
34
35
36
37
38
39
40
41
42
43 public class ColorTools {
44
45 public BufferedImage convertBetweenColorSpaces(BufferedImage bi, final ColorSpace from, final ColorSpace to) {
46 final RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
47 hints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
48 hints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
49
50 final ColorConvertOp op = new ColorConvertOp(from, to, hints);
51
52 bi = relabelColorSpace(bi, from);
53
54 final BufferedImage result = op.filter(bi, null);
55
56 return relabelColorSpace(result, to);
57 }
58
59 public BufferedImage convertBetweenColorSpacesX2(BufferedImage bi, final ColorSpace from, final ColorSpace to) {
60 final RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
61 hints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
62 hints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
63
64
65
66
67
68
69 bi = relabelColorSpace(bi, from);
70 final ColorConvertOp op = new ColorConvertOp(from, to, hints);
71 bi = op.filter(bi, null);
72
73 bi = relabelColorSpace(bi, from);
74
75 bi = op.filter(bi, null);
76
77 return relabelColorSpace(bi, to);
78
79 }
80
81 public BufferedImage convertBetweenIccProfiles(final BufferedImage bi, final ICC_Profile from, final ICC_Profile to) {
82 final ICC_ColorSpace csFrom = new ICC_ColorSpace(from);
83 final ICC_ColorSpace csTo = new ICC_ColorSpace(to);
84
85 return convertBetweenColorSpaces(bi, csFrom, csTo);
86 }
87
88 protected BufferedImage convertFromColorSpace(final BufferedImage bi, final ColorSpace from) {
89 final ColorModel srgbCM = ColorModel.getRGBdefault();
90 return convertBetweenColorSpaces(bi, from, srgbCM.getColorSpace());
91 }
92
93 public BufferedImage convertToColorSpace(final BufferedImage bi, final ColorSpace to) {
94 final ColorSpace from = bi.getColorModel().getColorSpace();
95
96 final RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
97 hints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
98 hints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
99
100 final ColorConvertOp op = new ColorConvertOp(from, to, hints);
101
102 final BufferedImage result = op.filter(bi, null);
103
104 return relabelColorSpace(result, to);
105 }
106
107 public BufferedImage convertToIccProfile(final BufferedImage bi, final ICC_Profile to) {
108 final ICC_ColorSpace csTo = new ICC_ColorSpace(to);
109 return convertToColorSpace(bi, csTo);
110 }
111
112 public BufferedImage convertTosRgb(final BufferedImage bi) {
113 final ColorModel srgbCM = ColorModel.getRGBdefault();
114 return convertToColorSpace(bi, srgbCM.getColorSpace());
115 }
116
117 public BufferedImage correctImage(final BufferedImage src, final File file) throws ImagingException, IOException {
118 final ICC_Profile icc = Imaging.getIccProfile(file);
119 if (icc == null) {
120 return src;
121 }
122
123 final ICC_ColorSpace cs = new ICC_ColorSpace(icc);
124
125 return convertFromColorSpace(src, cs);
126 }
127
128 private int countBitsInMask(int i) {
129 int count = 0;
130 while (i != 0) {
131 count += i & 1;
132
133
134 i >>>= 1;
135 }
136 return count;
137 }
138
139 public ColorModel deriveColorModel(final BufferedImage bi, final ColorSpace cs) throws ImagingOpException {
140
141 return deriveColorModel(bi, cs, false);
142 }
143
144 public ColorModel deriveColorModel(final BufferedImage bi, final ColorSpace cs, final boolean forceNoAlpha) throws ImagingOpException {
145 return deriveColorModel(bi.getColorModel(), cs, forceNoAlpha);
146 }
147
148 public ColorModel deriveColorModel(final ColorModel colorModel, final ColorSpace cs, final boolean forceNoAlpha) throws ImagingOpException {
149
150 if (colorModel instanceof ComponentColorModel) {
151 final ComponentColorModel ccm = (ComponentColorModel) colorModel;
152
153 if (forceNoAlpha) {
154 return new ComponentColorModel(cs, false, false, Transparency.OPAQUE, ccm.getTransferType());
155 }
156 return new ComponentColorModel(cs, ccm.hasAlpha(), ccm.isAlphaPremultiplied(), ccm.getTransparency(), ccm.getTransferType());
157 }
158 if (colorModel instanceof DirectColorModel) {
159 final DirectColorModel dcm = (DirectColorModel) colorModel;
160
161 final int oldMask = dcm.getRedMask() | dcm.getGreenMask() | dcm.getBlueMask() | dcm.getAlphaMask();
162
163 final int oldBits = countBitsInMask(oldMask);
164
165 return new DirectColorModel(cs, oldBits, dcm.getRedMask(), dcm.getGreenMask(), dcm.getBlueMask(), dcm.getAlphaMask(), dcm.isAlphaPremultiplied(),
166 dcm.getTransferType());
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189 throw new ImagingOpException("Could not clone unknown ColorModel Type.");
190 }
191
192 public BufferedImage relabelColorSpace(final BufferedImage bi, final ColorModel cm) throws ImagingOpException {
193
194
195
196
197
198
199 return new BufferedImage(cm, bi.getRaster(), false, null);
200 }
201
202 public BufferedImage relabelColorSpace(final BufferedImage bi, final ColorSpace cs) throws ImagingOpException {
203
204
205
206
207
208
209 final ColorModel cm = deriveColorModel(bi, cs);
210
211 return relabelColorSpace(bi, cm);
212
213 }
214
215 public BufferedImage relabelColorSpace(final BufferedImage bi, final ICC_Profile profile) throws ImagingOpException {
216 final ICC_ColorSpace cs = new ICC_ColorSpace(profile);
217
218 return relabelColorSpace(bi, cs);
219 }
220
221 }