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