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