1
22
23 package com.liferay.portal.image;
24
25 import com.liferay.portal.kernel.image.ImageBag;
26 import com.liferay.portal.kernel.image.ImageProcessor;
27 import com.liferay.portal.kernel.log.Log;
28 import com.liferay.portal.kernel.log.LogFactoryUtil;
29 import com.liferay.portal.kernel.util.JavaProps;
30 import com.liferay.portal.util.FileImpl;
31
32 import com.sun.media.jai.codec.ImageCodec;
33 import com.sun.media.jai.codec.ImageDecoder;
34
35 import java.awt.Graphics2D;
36 import java.awt.Image;
37 import java.awt.image.BufferedImage;
38 import java.awt.image.DataBuffer;
39 import java.awt.image.IndexColorModel;
40 import java.awt.image.RenderedImage;
41 import java.awt.image.SampleModel;
42
43 import java.io.ByteArrayInputStream;
44 import java.io.File;
45 import java.io.IOException;
46 import java.io.OutputStream;
47
48 import java.util.Enumeration;
49
50 import javax.imageio.ImageIO;
51
52 import javax.media.jai.RenderedImageAdapter;
53
54 import net.jmge.gif.Gif89Encoder;
55
56
62 public class ImageProcessorImpl implements ImageProcessor {
63
64 public static ImageProcessorImpl getInstance() {
65 return _instance;
66 }
67
68 public BufferedImage convertImageType(BufferedImage sourceImage, int type) {
69 BufferedImage targetImage = new BufferedImage(
70 sourceImage.getWidth(), sourceImage.getHeight(), type);
71
72 Graphics2D graphics = targetImage.createGraphics();
73
74 graphics.drawRenderedImage(sourceImage, null);
75 graphics.dispose();
76
77 return targetImage;
78 }
79
80 public void encodeGIF(RenderedImage renderedImage, OutputStream os)
81 throws IOException {
82
83 if (JavaProps.isJDK6()) {
84 ImageIO.write(renderedImage, "GIF", os);
85 }
86 else {
87 BufferedImage bufferedImage = getBufferedImage(renderedImage);
88
89 if (!(bufferedImage.getColorModel() instanceof IndexColorModel)) {
90 bufferedImage = convertImageType(
91 bufferedImage, BufferedImage.TYPE_BYTE_INDEXED);
92 }
93
94 Gif89Encoder encoder = new Gif89Encoder(bufferedImage);
95
96 encoder.encode(os);
97 }
98 }
99
100 public void encodeWBMP(RenderedImage renderedImage, OutputStream os)
101 throws IOException {
102
103 BufferedImage bufferedImage = getBufferedImage(renderedImage);
104
105 SampleModel sampleModel = bufferedImage.getSampleModel();
106
107 int type = sampleModel.getDataType();
108
109 if ((bufferedImage.getType() != BufferedImage.TYPE_BYTE_BINARY) ||
110 (type < DataBuffer.TYPE_BYTE) || (type > DataBuffer.TYPE_INT) ||
111 (sampleModel.getNumBands() != 1) ||
112 (sampleModel.getSampleSize(0) != 1)) {
113
114 BufferedImage binaryImage = new BufferedImage(
115 bufferedImage.getWidth(), bufferedImage.getHeight(),
116 BufferedImage.TYPE_BYTE_BINARY);
117
118 binaryImage.getGraphics().drawImage(bufferedImage, 0, 0, null);
119
120 renderedImage = binaryImage;
121 }
122
123 if (!ImageIO.write(renderedImage, "wbmp", os)) {
124
125
127 os.write(0);
128 os.write(0);
129 os.write(_toMultiByte(bufferedImage.getWidth()));
130 os.write(_toMultiByte(bufferedImage.getHeight()));
131
132 DataBuffer dataBuffer = bufferedImage.getData().getDataBuffer();
133
134 int size = dataBuffer.getSize();
135
136 for (int i = 0; i < size; i++) {
137 os.write((byte)dataBuffer.getElem(i));
138 }
139 }
140 }
141
142 public BufferedImage getBufferedImage(RenderedImage renderedImage) {
143 if (renderedImage instanceof BufferedImage) {
144 return (BufferedImage)renderedImage;
145 }
146 else {
147 RenderedImageAdapter adapter = new RenderedImageAdapter(
148 renderedImage);
149
150 return adapter.getAsBufferedImage();
151 }
152 }
153
154 public ImageBag read(File file) throws IOException {
155 return read(_fileUtil.getBytes(file));
156 }
157
158 public ImageBag read(byte[] bytes) {
159 RenderedImage renderedImage = null;
160 String type = TYPE_NOT_AVAILABLE;
161
162 Enumeration<ImageCodec> enu = ImageCodec.getCodecs();
163
164 while (enu.hasMoreElements()) {
165 ImageCodec codec = enu.nextElement();
166
167 if (codec.isFormatRecognized(bytes)) {
168 type = codec.getFormatName();
169
170 ImageDecoder decoder = ImageCodec.createImageDecoder(
171 type, new ByteArrayInputStream(bytes), null);
172
173 try {
174 renderedImage = decoder.decodeAsRenderedImage();
175 }
176 catch (IOException ioe) {
177 if (_log.isDebugEnabled()) {
178 _log.debug(type + ": " + ioe.getMessage());
179 }
180 }
181
182 break;
183 }
184 }
185
186 if (type.equals("jpeg")) {
187 type = ImageProcessor.TYPE_JPEG;
188 }
189
190 return new ImageBag(renderedImage, type);
191 }
192
193 public RenderedImage scale(
194 RenderedImage renderedImage, int maxHeight, int maxWidth) {
195
196 int imageHeight = renderedImage.getHeight();
197 int imageWidth = renderedImage.getWidth();
198
199 if (maxHeight == 0) {
200 maxHeight = imageHeight;
201 }
202
203 if (maxWidth == 0) {
204 maxWidth = imageWidth;
205 }
206
207 if ((imageHeight <= maxHeight) && (imageWidth <= maxWidth)) {
208 return renderedImage;
209 }
210
211 double factor = Math.min(
212 (double)maxHeight / imageHeight, (double)maxWidth / imageWidth);
213
214 int scaledHeight = Math.max(1, (int)(factor * imageHeight));
215 int scaledWidth = Math.max(1, (int)(factor * imageWidth));
216
217 BufferedImage bufferedImage = getBufferedImage(renderedImage);
218
219 Image scaledImage = bufferedImage.getScaledInstance(
220 scaledWidth, scaledHeight, Image.SCALE_SMOOTH);
221
222 BufferedImage scaledBufferedImage = new BufferedImage(
223 scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB);
224
225 scaledBufferedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
226
227 return scaledBufferedImage;
228 }
229
230 private byte[] _toMultiByte(int intValue) {
231 int numBits = 32;
232 int mask = 0x80000000;
233
234 while (mask != 0 && (intValue & mask) == 0) {
235 numBits--;
236 mask >>>= 1;
237 }
238
239 int numBitsLeft = numBits;
240 byte[] multiBytes = new byte[(numBitsLeft + 6) / 7];
241
242 int maxIndex = multiBytes.length - 1;
243
244 for (int b = 0; b <= maxIndex; b++) {
245 multiBytes[b] = (byte)((intValue >>> ((maxIndex - b) * 7)) & 0x7f);
246
247 if (b != maxIndex) {
248 multiBytes[b] |= (byte)0x80;
249 }
250 }
251
252 return multiBytes;
253 }
254
255 private static Log _log = LogFactoryUtil.getLog(ImageProcessorImpl.class);
256
257 private static ImageProcessorImpl _instance = new ImageProcessorImpl();
258
259 private static FileImpl _fileUtil = FileImpl.getInstance();
260
261 }