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