001
014
015 package com.liferay.portal.image;
016
017 import com.liferay.portal.kernel.image.ImageBag;
018 import com.liferay.portal.kernel.image.ImageTool;
019 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
020 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.util.JavaProps;
024 import com.liferay.portal.util.FileImpl;
025
026 import com.sun.media.jai.codec.ImageCodec;
027 import com.sun.media.jai.codec.ImageDecoder;
028 import com.sun.media.jai.codec.ImageEncoder;
029
030 import java.awt.Graphics2D;
031 import java.awt.Graphics;
032 import java.awt.Image;
033 import java.awt.image.BufferedImage;
034 import java.awt.image.DataBuffer;
035 import java.awt.image.IndexColorModel;
036 import java.awt.image.RenderedImage;
037 import java.awt.image.SampleModel;
038 import java.awt.image.WritableRaster;
039
040 import java.io.File;
041 import java.io.IOException;
042 import java.io.OutputStream;
043
044 import java.util.Enumeration;
045
046 import javax.imageio.ImageIO;
047
048 import javax.media.jai.RenderedImageAdapter;
049
050 import net.jmge.gif.Gif89Encoder;
051
052
055 public class ImageToolImpl implements ImageTool {
056
057 public static ImageTool getInstance() {
058 return _instance;
059 }
060
061 public BufferedImage convertImageType(BufferedImage sourceImage, int type) {
062 BufferedImage targetImage = new BufferedImage(
063 sourceImage.getWidth(), sourceImage.getHeight(), type);
064
065 Graphics2D graphics = targetImage.createGraphics();
066
067 graphics.drawRenderedImage(sourceImage, null);
068
069 graphics.dispose();
070
071 return targetImage;
072 }
073
074 public void encodeGIF(RenderedImage renderedImage, OutputStream os)
075 throws IOException {
076
077 if (JavaProps.isJDK6()) {
078 ImageIO.write(renderedImage, TYPE_GIF, os);
079 }
080 else {
081 BufferedImage bufferedImage = getBufferedImage(renderedImage);
082
083 if (!(bufferedImage.getColorModel() instanceof IndexColorModel)) {
084 bufferedImage = convertImageType(
085 bufferedImage, BufferedImage.TYPE_BYTE_INDEXED);
086 }
087
088 Gif89Encoder encoder = new Gif89Encoder(bufferedImage);
089
090 encoder.encode(os);
091 }
092 }
093
094 public void encodeWBMP(RenderedImage renderedImage, OutputStream os)
095 throws IOException {
096
097 BufferedImage bufferedImage = getBufferedImage(renderedImage);
098
099 SampleModel sampleModel = bufferedImage.getSampleModel();
100
101 int type = sampleModel.getDataType();
102
103 if ((bufferedImage.getType() != BufferedImage.TYPE_BYTE_BINARY) ||
104 (type < DataBuffer.TYPE_BYTE) || (type > DataBuffer.TYPE_INT) ||
105 (sampleModel.getNumBands() != 1) ||
106 (sampleModel.getSampleSize(0) != 1)) {
107
108 BufferedImage binaryImage = new BufferedImage(
109 bufferedImage.getWidth(), bufferedImage.getHeight(),
110 BufferedImage.TYPE_BYTE_BINARY);
111
112 Graphics graphics = binaryImage.getGraphics();
113
114 graphics.drawImage(bufferedImage, 0, 0, null);
115
116 renderedImage = binaryImage;
117 }
118
119 if (!ImageIO.write(renderedImage, "wbmp", os)) {
120
121
122
123 os.write(0);
124 os.write(0);
125 os.write(_toMultiByte(bufferedImage.getWidth()));
126 os.write(_toMultiByte(bufferedImage.getHeight()));
127
128 DataBuffer dataBuffer = bufferedImage.getData().getDataBuffer();
129
130 int size = dataBuffer.getSize();
131
132 for (int i = 0; i < size; i++) {
133 os.write((byte)dataBuffer.getElem(i));
134 }
135 }
136 }
137
138 public BufferedImage getBufferedImage(RenderedImage renderedImage) {
139 if (renderedImage instanceof BufferedImage) {
140 return (BufferedImage)renderedImage;
141 }
142 else {
143 RenderedImageAdapter adapter = new RenderedImageAdapter(
144 renderedImage);
145
146 return adapter.getAsBufferedImage();
147 }
148 }
149
150 public byte[] getBytes(RenderedImage renderedImage, String contentType)
151 throws IOException {
152
153 UnsyncByteArrayOutputStream baos = new UnsyncByteArrayOutputStream();
154
155 write(renderedImage, contentType, baos);
156
157 return baos.toByteArray();
158 }
159
160 public ImageBag read(byte[] bytes) {
161 RenderedImage renderedImage = null;
162 String type = TYPE_NOT_AVAILABLE;
163
164 Enumeration<ImageCodec> enu = ImageCodec.getCodecs();
165
166 while (enu.hasMoreElements()) {
167 ImageCodec codec = enu.nextElement();
168
169 if (codec.isFormatRecognized(bytes)) {
170 type = codec.getFormatName();
171
172 ImageDecoder decoder = ImageCodec.createImageDecoder(
173 type, new UnsyncByteArrayInputStream(bytes), null);
174
175 try {
176 renderedImage = decoder.decodeAsRenderedImage();
177 }
178 catch (IOException ioe) {
179 if (_log.isDebugEnabled()) {
180 _log.debug(type + ": " + ioe.getMessage());
181 }
182 }
183
184 break;
185 }
186 }
187
188 if (type.equals("jpeg")) {
189 type = TYPE_JPEG;
190 }
191
192 return new ImageBag(renderedImage, type);
193 }
194
195 public ImageBag read(File file) throws IOException {
196 return read(_fileUtil.getBytes(file));
197 }
198
199 public RenderedImage scale(RenderedImage renderedImage, int width) {
200 if (width <= 0) {
201 return renderedImage;
202 }
203
204 int imageHeight = renderedImage.getHeight();
205 int imageWidth = renderedImage.getWidth();
206
207 double factor = (double) width / imageWidth;
208
209 int scaledHeight = (int)(factor * imageHeight);
210 int scaledWidth = width;
211
212 BufferedImage bufferedImage = getBufferedImage(renderedImage);
213
214 int type = bufferedImage.getType();
215
216 if (type == 0) {
217 type = BufferedImage.TYPE_INT_ARGB;
218 }
219
220 BufferedImage scaledBufferedImage = new BufferedImage(
221 scaledWidth, scaledHeight, type);
222
223 Graphics graphics = scaledBufferedImage.getGraphics();
224
225 Image scaledImage = bufferedImage.getScaledInstance(
226 scaledWidth, scaledHeight, Image.SCALE_SMOOTH);
227
228 graphics.drawImage(scaledImage, 0, 0, null);
229
230 return scaledBufferedImage;
231 }
232
233 public RenderedImage scale(
234 RenderedImage renderedImage, int maxHeight, int maxWidth) {
235
236 int imageHeight = renderedImage.getHeight();
237 int imageWidth = renderedImage.getWidth();
238
239 if (maxHeight == 0) {
240 maxHeight = imageHeight;
241 }
242
243 if (maxWidth == 0) {
244 maxWidth = imageWidth;
245 }
246
247 if ((imageHeight <= maxHeight) && (imageWidth <= maxWidth)) {
248 return renderedImage;
249 }
250
251 double factor = Math.min(
252 (double)maxHeight / imageHeight, (double)maxWidth / imageWidth);
253
254 int scaledHeight = Math.max(1, (int)(factor * imageHeight));
255 int scaledWidth = Math.max(1, (int)(factor * imageWidth));
256
257 BufferedImage bufferedImage = getBufferedImage(renderedImage);
258
259 int type = bufferedImage.getType();
260
261 if (type == 0) {
262 type = BufferedImage.TYPE_INT_ARGB;
263 }
264
265 BufferedImage scaledBufferedImage = null;
266
267 if ((type == BufferedImage.TYPE_BYTE_BINARY) ||
268 (type == BufferedImage.TYPE_BYTE_INDEXED)) {
269
270 IndexColorModel indexColorModel =
271 (IndexColorModel)bufferedImage.getColorModel();
272
273 BufferedImage tempBufferedImage = new BufferedImage(
274 1, 1, type, indexColorModel);
275
276 int bits = indexColorModel.getPixelSize();
277 int size = indexColorModel.getMapSize();
278
279 byte[] reds = new byte[size];
280
281 indexColorModel.getReds(reds);
282
283 byte[] greens = new byte[size];
284
285 indexColorModel.getGreens(greens);
286
287 byte[] blues = new byte[size];
288
289 indexColorModel.getBlues(blues);
290
291 WritableRaster writableRaster = tempBufferedImage.getRaster();
292
293 int pixel = writableRaster.getSample(0, 0, 0);
294
295 IndexColorModel scaledIndexColorModel = new IndexColorModel(
296 bits, size, reds, greens, blues, pixel);
297
298 scaledBufferedImage = new BufferedImage(
299 scaledWidth, scaledHeight, type, scaledIndexColorModel);
300 }
301 else {
302 scaledBufferedImage = new BufferedImage(
303 scaledWidth, scaledHeight, type);
304 }
305
306 Graphics graphics = scaledBufferedImage.getGraphics();
307
308 Image scaledImage = bufferedImage.getScaledInstance(
309 scaledWidth, scaledHeight, Image.SCALE_SMOOTH);
310
311 graphics.drawImage(scaledImage, 0, 0, null);
312
313 return scaledBufferedImage;
314 }
315
316 public void write(
317 RenderedImage renderedImage, String contentType, OutputStream os)
318 throws IOException {
319
320 if (contentType.contains(TYPE_BMP)) {
321 ImageEncoder imageEncoder = ImageCodec.createImageEncoder(
322 TYPE_BMP, os, null);
323
324 imageEncoder.encode(renderedImage);
325 }
326 else if (contentType.contains(TYPE_GIF)) {
327 encodeGIF(renderedImage, os);
328 }
329 else if ((contentType.contains(TYPE_JPEG)) ||
330 (contentType.contains("jpeg"))) {
331
332 ImageIO.write(renderedImage, "jpeg", os);
333 }
334 else if (contentType.contains(TYPE_PNG)) {
335 ImageIO.write(renderedImage, TYPE_PNG, os);
336 }
337 else if (contentType.contains(TYPE_TIFF) ||
338 contentType.contains("tif")) {
339
340 ImageEncoder imageEncoder = ImageCodec.createImageEncoder(
341 TYPE_TIFF, os, null);
342
343 imageEncoder.encode(renderedImage);
344 }
345 }
346
347 private byte[] _toMultiByte(int intValue) {
348 int numBits = 32;
349 int mask = 0x80000000;
350
351 while (mask != 0 && (intValue & mask) == 0) {
352 numBits--;
353 mask >>>= 1;
354 }
355
356 int numBitsLeft = numBits;
357 byte[] multiBytes = new byte[(numBitsLeft + 6) / 7];
358
359 int maxIndex = multiBytes.length - 1;
360
361 for (int b = 0; b <= maxIndex; b++) {
362 multiBytes[b] = (byte)((intValue >>> ((maxIndex - b) * 7)) & 0x7f);
363
364 if (b != maxIndex) {
365 multiBytes[b] |= (byte)0x80;
366 }
367 }
368
369 return multiBytes;
370 }
371
372 private static Log _log = LogFactoryUtil.getLog(ImageToolImpl.class);
373
374 private static ImageTool _instance = new ImageToolImpl();
375
376 private static FileImpl _fileUtil = FileImpl.getInstance();
377
378 }