extensions/net.sf.basedb.thumbnails/trunk/src/net/sf/basedb/thumbnails/Thumbnails.java

Code
Comments
Other
Rev Date Author Line
3398 15 Jun 15 nicklas 1 package net.sf.basedb.thumbnails;
3398 15 Jun 15 nicklas 2
3417 24 Jun 15 nicklas 3 import java.awt.Color;
3417 24 Jun 15 nicklas 4 import java.awt.Transparency;
3417 24 Jun 15 nicklas 5 import java.awt.image.BufferedImage;
3417 24 Jun 15 nicklas 6 import java.io.ByteArrayOutputStream;
3417 24 Jun 15 nicklas 7 import java.io.IOException;
3417 24 Jun 15 nicklas 8
3417 24 Jun 15 nicklas 9 import javax.imageio.IIOImage;
3417 24 Jun 15 nicklas 10 import javax.imageio.ImageIO;
3417 24 Jun 15 nicklas 11 import javax.imageio.ImageWriteParam;
3417 24 Jun 15 nicklas 12 import javax.imageio.ImageWriter;
3417 24 Jun 15 nicklas 13 import javax.imageio.stream.MemoryCacheImageOutputStream;
3417 24 Jun 15 nicklas 14
3417 24 Jun 15 nicklas 15 import net.sf.basedb.core.File;
3417 24 Jun 15 nicklas 16 import net.sf.basedb.thumbnails.impl.ImageImageLoader;
6045 11 Nov 20 nicklas 17 import net.sf.basedb.thumbnails.impl.NdpiImageLoader;
3417 24 Jun 15 nicklas 18 import net.sf.basedb.thumbnails.impl.PdfImageLoader;
5351 10 Apr 19 nicklas 19 import net.sf.basedb.thumbnails.impl.SvgImageLoader;
3417 24 Jun 15 nicklas 20
3417 24 Jun 15 nicklas 21 import org.imgscalr.Scalr;
6043 11 Nov 20 nicklas 22 import org.imgscalr.Scalr.Rotation;
3417 24 Jun 15 nicklas 23
3398 15 Jun 15 nicklas 24 /**
3398 15 Jun 15 nicklas 25   Global constants for the Thumbnails package.
3398 15 Jun 15 nicklas 26   
3398 15 Jun 15 nicklas 27   @author Nicklas
3398 15 Jun 15 nicklas 28   @since 1.0
3398 15 Jun 15 nicklas 29 */
3398 15 Jun 15 nicklas 30 public final class Thumbnails 
3398 15 Jun 15 nicklas 31 {
3398 15 Jun 15 nicklas 32   /**
3398 15 Jun 15 nicklas 33     The current version of this package.
3398 15 Jun 15 nicklas 34   */
6085 26 Nov 20 nicklas 35   public static final String VERSION = "1.3-dev";
3398 15 Jun 15 nicklas 36
3401 15 Jun 15 nicklas 37   /**
3401 15 Jun 15 nicklas 38     The version number for the file format in use when storing
3401 15 Jun 15 nicklas 39     thumbnails. If the format changes in an incompatible way, this
3401 15 Jun 15 nicklas 40     number must be increased. This will make sure that the old files
3401 15 Jun 15 nicklas 41     are not used and that new files are generated instead.
3401 15 Jun 15 nicklas 42   */
5351 10 Apr 19 nicklas 43   public static final int FILE_VERSION = Integer.valueOf(2).intValue();
3398 15 Jun 15 nicklas 44
3401 15 Jun 15 nicklas 45   
3401 15 Jun 15 nicklas 46   /**
3401 15 Jun 15 nicklas 47     The static cache key under which a thumbnail is
3401 15 Jun 15 nicklas 48     saved.
3401 15 Jun 15 nicklas 49     
3401 15 Jun 15 nicklas 50     @param fileId The ID of the file
3401 15 Jun 15 nicklas 51     @param fileVersion The version number of the file
3401 15 Jun 15 nicklas 52     @param size The thumbnail size
6043 11 Nov 20 nicklas 53     @param rotation Optional rotation
3401 15 Jun 15 nicklas 54   */
6053 13 Nov 20 nicklas 55   public static String getCacheKey(int fileId, int fileVersion, String extension, ThumbnailSize size, Rotation rotation, Crop crop, int imageIndex)
3401 15 Jun 15 nicklas 56   {
3401 15 Jun 15 nicklas 57     int subdir = fileId % 1000;
6043 11 Nov 20 nicklas 58     String r = rotation == null ? "" : "-"+rotation.name();
6053 13 Nov 20 nicklas 59     String c = crop == null ? "" : "-"+crop.name();
6046 11 Nov 20 nicklas 60     String i = imageIndex >= 0 ? "-"+imageIndex : "";
6053 13 Nov 20 nicklas 61     return "/thumbnails-v" + FILE_VERSION + "/" + size.name() + "/" + subdir + "/" + fileId + "-" + fileVersion + i + r + c + "." + extension;
3401 15 Jun 15 nicklas 62   }
3401 15 Jun 15 nicklas 63
3417 24 Jun 15 nicklas 64   /**
3417 24 Jun 15 nicklas 65     Scale the given image so that it is not larger than the given
3417 24 Jun 15 nicklas 66     thumbnail size in any direction. The width/height proportions are
3417 24 Jun 15 nicklas 67     retained.
3417 24 Jun 15 nicklas 68   */
3417 24 Jun 15 nicklas 69   public static BufferedImage scaleImage(BufferedImage full, ThumbnailSize size)
3417 24 Jun 15 nicklas 70     throws IOException
3417 24 Jun 15 nicklas 71   {
3417 24 Jun 15 nicklas 72     BufferedImage thumb = null;
3417 24 Jun 15 nicklas 73       
3417 24 Jun 15 nicklas 74     // Scale so that the thumbnail never is larger than the bounding box
3417 24 Jun 15 nicklas 75     float scaleX = (float)full.getWidth() / (float)size.WIDTH;
3417 24 Jun 15 nicklas 76     float scaleY = (float)full.getHeight() / (float)size.HEIGHT;
3417 24 Jun 15 nicklas 77     if (scaleX > 1 || scaleY > 1)
3417 24 Jun 15 nicklas 78     {
3417 24 Jun 15 nicklas 79       // Only scale if the full image is larger in at least one direction
3417 24 Jun 15 nicklas 80       Scalr.Mode scaleMode = scaleX > scaleY ? Scalr.Mode.FIT_TO_WIDTH : Scalr.Mode.FIT_TO_HEIGHT;
3417 24 Jun 15 nicklas 81       thumb = Scalr.resize(full, Scalr.Method.ULTRA_QUALITY, scaleMode, size.WIDTH, size.HEIGHT);
3417 24 Jun 15 nicklas 82     }
3417 24 Jun 15 nicklas 83     else
3417 24 Jun 15 nicklas 84     {
3417 24 Jun 15 nicklas 85       // The full image is smaller than the thumbnail size
3417 24 Jun 15 nicklas 86       thumb = full;
3417 24 Jun 15 nicklas 87     }
3417 24 Jun 15 nicklas 88     
3417 24 Jun 15 nicklas 89     // Convert transparent pixels to white
3417 24 Jun 15 nicklas 90     if (thumb.getTransparency() != Transparency.OPAQUE)
3417 24 Jun 15 nicklas 91     {
3417 24 Jun 15 nicklas 92       BufferedImage opaque = new BufferedImage(thumb.getWidth(), thumb.getHeight(), BufferedImage.TYPE_INT_RGB);
3417 24 Jun 15 nicklas 93       opaque.createGraphics().drawImage(thumb, 0, 0, Color.WHITE, null);
3417 24 Jun 15 nicklas 94       thumb = opaque;
3417 24 Jun 15 nicklas 95     }
3417 24 Jun 15 nicklas 96     
3417 24 Jun 15 nicklas 97     return thumb;
3417 24 Jun 15 nicklas 98   }
3417 24 Jun 15 nicklas 99
3417 24 Jun 15 nicklas 100   /**
3417 24 Jun 15 nicklas 101     Convert the given image to JPEG.
3417 24 Jun 15 nicklas 102   */
3417 24 Jun 15 nicklas 103   public static byte[] toJpg(BufferedImage thumb, int buffer)
3417 24 Jun 15 nicklas 104     throws IOException
3417 24 Jun 15 nicklas 105   {
3417 24 Jun 15 nicklas 106     // Write to JPG with quality=0.9 (ImageIO.write() can only write using default quality=0.75)
3417 24 Jun 15 nicklas 107     ImageWriter jpgWriter = ImageIO.getImageWritersByFormatName("jpg").next();
3417 24 Jun 15 nicklas 108     ImageWriteParam jpgParam = jpgWriter.getDefaultWriteParam();
3417 24 Jun 15 nicklas 109     jpgParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
3417 24 Jun 15 nicklas 110     jpgParam.setCompressionQuality(0.9f);
3417 24 Jun 15 nicklas 111     ByteArrayOutputStream buf = new ByteArrayOutputStream(buffer);
3417 24 Jun 15 nicklas 112     jpgWriter.setOutput(new MemoryCacheImageOutputStream(buf));
3417 24 Jun 15 nicklas 113     jpgWriter.write(null, new IIOImage(thumb, null, null), jpgParam);
3417 24 Jun 15 nicklas 114     jpgWriter.dispose();
3417 24 Jun 15 nicklas 115     return buf.toByteArray();
3417 24 Jun 15 nicklas 116   }
3417 24 Jun 15 nicklas 117   
3417 24 Jun 15 nicklas 118   /**
3417 24 Jun 15 nicklas 119     Get an image loader that is likely to be able to create an image from
3417 24 Jun 15 nicklas 120     the given file.
3417 24 Jun 15 nicklas 121   */
3417 24 Jun 15 nicklas 122   public static ImageLoader getImageLoader(File f)
3417 24 Jun 15 nicklas 123   {
3417 24 Jun 15 nicklas 124     String mimeType = f.getMimeType();
3426 25 Jun 15 nicklas 125     if (mimeType == null) mimeType = "";
3417 24 Jun 15 nicklas 126     int lastDot = f.getName().lastIndexOf('.');
3417 24 Jun 15 nicklas 127     String extension = lastDot > 0 ? f.getName().substring(lastDot) : "";
3417 24 Jun 15 nicklas 128     
3417 24 Jun 15 nicklas 129     ImageLoader loader = null;
6045 11 Nov 20 nicklas 130     if ("application/pdf".equals(mimeType) || ".pdf".equals(extension))
3417 24 Jun 15 nicklas 131     {
3417 24 Jun 15 nicklas 132       loader = new PdfImageLoader();
3417 24 Jun 15 nicklas 133     }
6045 11 Nov 20 nicklas 134     else if ("image/svg+xml".equals(mimeType) || ".svg".equals(extension))
5351 10 Apr 19 nicklas 135     {
5351 10 Apr 19 nicklas 136       loader = new SvgImageLoader();
5351 10 Apr 19 nicklas 137     }
6045 11 Nov 20 nicklas 138     else if (".ndpi".equals(extension))
3417 24 Jun 15 nicklas 139     {
6045 11 Nov 20 nicklas 140       loader = new NdpiImageLoader();
6045 11 Nov 20 nicklas 141     }
6045 11 Nov 20 nicklas 142     else if (mimeType.startsWith("image/") || ".jpg".equals(extension) || ".png".equals(extension))
6045 11 Nov 20 nicklas 143     {
3417 24 Jun 15 nicklas 144       loader = new ImageImageLoader();
3417 24 Jun 15 nicklas 145     }
3417 24 Jun 15 nicklas 146     return loader;
3417 24 Jun 15 nicklas 147   }
3417 24 Jun 15 nicklas 148
3398 15 Jun 15 nicklas 149 }