001
014
015 package com.liferay.portal.image;
016
017 import com.liferay.portal.kernel.image.ImageBag;
018 import com.liferay.portal.kernel.image.ImageProcessor;
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
039 import java.io.File;
040 import java.io.IOException;
041 import java.io.OutputStream;
042
043 import java.util.Enumeration;
044
045 import javax.imageio.ImageIO;
046
047 import javax.media.jai.RenderedImageAdapter;
048
049 import net.jmge.gif.Gif89Encoder;
050
051
054 public class ImageProcessorImpl implements ImageProcessor {
055
056 public static ImageProcessorImpl getInstance() {
057 return _instance;
058 }
059
060 public BufferedImage convertImageType(BufferedImage sourceImage, int type) {
061 BufferedImage targetImage = new BufferedImage(
062 sourceImage.getWidth(), sourceImage.getHeight(), type);
063
064 Graphics2D graphics = targetImage.createGraphics();
065
066 graphics.drawRenderedImage(sourceImage, null);
067
068 graphics.dispose();
069
070 return targetImage;
071 }
072
073 public void encodeGIF(RenderedImage renderedImage, OutputStream os)
074 throws IOException {
075
076 if (JavaProps.isJDK6()) {
077 ImageIO.write(renderedImage, TYPE_GIF, os);
078 }
079 else {
080 BufferedImage bufferedImage = getBufferedImage(renderedImage);
081
082 if (!(bufferedImage.getColorModel() instanceof IndexColorModel)) {
083 bufferedImage = convertImageType(
084 bufferedImage, BufferedImage.TYPE_BYTE_INDEXED);
085 }
086
087 Gif89Encoder encoder = new Gif89Encoder(bufferedImage);
088
089 encoder.encode(os);
090 }
091 }
092
093 public void encodeWBMP(RenderedImage renderedImage, OutputStream os)
094 throws IOException {
095
096 BufferedImage bufferedImage = getBufferedImage(renderedImage);
097
098 SampleModel sampleModel = bufferedImage.getSampleModel();
099
100 int type = sampleModel.getDataType();
101
102 if ((bufferedImage.getType() != BufferedImage.TYPE_BYTE_BINARY) ||
103 (type < DataBuffer.TYPE_BYTE) || (type > DataBuffer.TYPE_INT) ||
104 (sampleModel.getNumBands() != 1) ||
105 (sampleModel.getSampleSize(0) != 1)) {
106
107 BufferedImage binaryImage = new BufferedImage(
108 bufferedImage.getWidth(), bufferedImage.getHeight(),
109 BufferedImage.TYPE_BYTE_BINARY);
110
111 Graphics graphics = binaryImage.getGraphics();
112
113 graphics.drawImage(bufferedImage, 0, 0, null);
114
115 renderedImage = binaryImage;
116 }
117
118 if (!ImageIO.write(renderedImage, "wbmp", os)) {
119
120
121
122 os.write(0);
123 os.write(0);
124 os.write(_toMultiByte(bufferedImage.getWidth()));
125 os.write(_toMultiByte(bufferedImage.getHeight()));
126
127 DataBuffer dataBuffer = bufferedImage.getData().getDataBuffer();
128
129 int size = dataBuffer.getSize();
130
131 for (int i = 0; i < size; i++) {
132 os.write((byte)dataBuffer.getElem(i));
133 }
134 }
135 }
136
137 public BufferedImage getBufferedImage(RenderedImage renderedImage) {
138 if (renderedImage instanceof BufferedImage) {
139 return (BufferedImage)renderedImage;
140 }
141 else {
142 RenderedImageAdapter adapter = new RenderedImageAdapter(
143 renderedImage);
144
145 return adapter.getAsBufferedImage();
146 }
147 }
148
149 public byte[] getBytes(RenderedImage renderedImage, String contentType)
150 throws IOException {
151
152 UnsyncByteArrayOutputStream baos = new UnsyncByteArrayOutputStream();
153
154 if (contentType.indexOf(TYPE_BMP) != -1) {
155 ImageEncoder encoder = ImageCodec.createImageEncoder(
156 TYPE_BMP, baos, null);
157
158 encoder.encode(renderedImage);
159 }
160 else if (contentType.indexOf(TYPE_GIF) != -1) {
161 encodeGIF(renderedImage, baos);
162 }
163 else if ((contentType.indexOf(TYPE_JPEG) != -1) ||
164 (contentType.indexOf("jpeg") != -1)) {
165
166 ImageIO.write(renderedImage, "jpeg", baos);
167 }
168 else if (contentType.indexOf(TYPE_PNG) != -1) {
169 ImageIO.write(renderedImage, TYPE_PNG, baos);
170 }
171 else if (contentType.indexOf("tif") != -1) {
172 ImageEncoder encoder = ImageCodec.createImageEncoder(
173 TYPE_TIFF, baos, null);
174
175 encoder.encode(renderedImage);
176 }
177
178 return baos.toByteArray();
179 }
180
181 public ImageBag read(File file) throws IOException {
182 return read(_fileUtil.getBytes(file));
183 }
184
185 public ImageBag read(byte[] bytes) {
186 RenderedImage renderedImage = null;
187 String type = TYPE_NOT_AVAILABLE;
188
189 Enumeration<ImageCodec> enu = ImageCodec.getCodecs();
190
191 while (enu.hasMoreElements()) {
192 ImageCodec codec = enu.nextElement();
193
194 if (codec.isFormatRecognized(bytes)) {
195 type = codec.getFormatName();
196
197 ImageDecoder decoder = ImageCodec.createImageDecoder(
198 type, new UnsyncByteArrayInputStream(bytes), null);
199
200 try {
201 renderedImage = decoder.decodeAsRenderedImage();
202 }
203 catch (IOException ioe) {
204 if (_log.isDebugEnabled()) {
205 _log.debug(type + ": " + ioe.getMessage());
206 }
207 }
208
209 break;
210 }
211 }
212
213 if (type.equals("jpeg")) {
214 type = TYPE_JPEG;
215 }
216
217 return new ImageBag(renderedImage, type);
218 }
219
220 public RenderedImage scale(
221 RenderedImage renderedImage, int maxHeight, int maxWidth) {
222
223 int imageHeight = renderedImage.getHeight();
224 int imageWidth = renderedImage.getWidth();
225
226 if (maxHeight == 0) {
227 maxHeight = imageHeight;
228 }
229
230 if (maxWidth == 0) {
231 maxWidth = imageWidth;
232 }
233
234 if ((imageHeight <= maxHeight) && (imageWidth <= maxWidth)) {
235 return renderedImage;
236 }
237
238 double factor = Math.min(
239 (double)maxHeight / imageHeight, (double)maxWidth / imageWidth);
240
241 int scaledHeight = Math.max(1, (int)(factor * imageHeight));
242 int scaledWidth = Math.max(1, (int)(factor * imageWidth));
243
244 BufferedImage bufferedImage = getBufferedImage(renderedImage);
245
246 Image scaledImage = bufferedImage.getScaledInstance(
247 scaledWidth, scaledHeight, Image.SCALE_SMOOTH);
248
249 BufferedImage scaledBufferedImage = new BufferedImage(
250 scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB);
251
252 scaledBufferedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
253
254 return scaledBufferedImage;
255 }
256
257 private byte[] _toMultiByte(int intValue) {
258 int numBits = 32;
259 int mask = 0x80000000;
260
261 while (mask != 0 && (intValue & mask) == 0) {
262 numBits--;
263 mask >>>= 1;
264 }
265
266 int numBitsLeft = numBits;
267 byte[] multiBytes = new byte[(numBitsLeft + 6) / 7];
268
269 int maxIndex = multiBytes.length - 1;
270
271 for (int b = 0; b <= maxIndex; b++) {
272 multiBytes[b] = (byte)((intValue >>> ((maxIndex - b) * 7)) & 0x7f);
273
274 if (b != maxIndex) {
275 multiBytes[b] |= (byte)0x80;
276 }
277 }
278
279 return multiBytes;
280 }
281
282 private static Log _log = LogFactoryUtil.getLog(ImageProcessorImpl.class);
283
284 private static ImageProcessorImpl _instance = new ImageProcessorImpl();
285
286 private static FileImpl _fileUtil = FileImpl.getInstance();
287
288 }