1 package com.atlassian.core.util.thumbnail;
2
3 import com.atlassian.core.util.ReusableBufferedInputStream;
4 import com.google.common.base.Optional;
5
6 import javax.imageio.ImageIO;
7 import javax.imageio.ImageReadParam;
8 import javax.imageio.ImageReader;
9 import javax.imageio.stream.ImageInputStream;
10 import java.awt.image.BufferedImage;
11 import java.io.IOException;
12 import java.io.InputStream;
13 import java.util.Iterator;
14
15 public class StreamImageScale implements ImageScaler
16 {
17 private final DimensionsHelper dimensionsHelper;
18
19 public StreamImageScale(DimensionsHelper dimensionsHelper)
20 {
21 this.dimensionsHelper = dimensionsHelper;
22 }
23
24 @Override
25 public BufferedImage scaleImage(int maxWidth, int maxHeight, ReusableBufferedInputStream imageStream) throws IOException
26 {
27 final ImageInputStream imageInputStream = getImageInputStream(imageStream);
28 final Optional<ImageReader> imageReader = getImageReader(imageInputStream);
29
30 if (!imageReader.isPresent())
31 {
32 throw new IOException("Cannot read the image");
33 }
34
35 final ImageReader reader = imageReader.get();
36 try
37 {
38 reader.setInput(imageInputStream);
39
40 final Dimensions scaledDimensions = dimensionsHelper.determineScaledDimensions(maxWidth, maxHeight, reader.getWidth(0), reader.getHeight(0));
41 int ratio = (int) Math.floor(((double) reader.getWidth(0) / (double) scaledDimensions.getWidth()));
42
43 final ImageReadParam param = reader.getDefaultReadParam();
44 param.setSourceSubsampling(ratio, ratio, 0, 0);
45
46 final BufferedImage scaledImage = reader.read(0, param);
47
48 return scaledImage.getSubimage(0, 0,
49 Math.min(scaledDimensions.getWidth(), scaledImage.getWidth()),
50 Math.min(scaledDimensions.getHeight(), scaledImage.getHeight()));
51 }
52 finally
53 {
54 reader.dispose();
55 }
56 }
57
58 ImageInputStream getImageInputStream(InputStream inputStream) throws IOException
59 {
60 return ImageIO.createImageInputStream(inputStream);
61 }
62
63 Optional<ImageReader> getImageReader(ImageInputStream imageInputStream) throws IOException
64 {
65 final Iterator<ImageReader> readers = ImageIO.getImageReaders(imageInputStream);
66 return readers.hasNext() ? Optional.of(readers.next()) : Optional.<ImageReader>absent();
67 }
68
69 }