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