View Javadoc
1   /*
2   
3    * Copyright (C) 2003-2010 eXo Platform SAS.
4    *
5    * This program is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU Affero General Public License
7    * as published by the Free Software Foundation; either version 3
8    * of the License, or (at your option) any later version.
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with this program; if not, see<http://www.gnu.org/licenses/>.
17   */
18  package org.exoplatform.social.core.image;
19  
20  import org.exoplatform.commons.utils.MimeTypeResolver;
21  import org.exoplatform.services.log.ExoLogger;
22  import org.exoplatform.services.log.Log;
23  import org.exoplatform.social.core.model.AvatarAttachment;
24  
25  import javax.imageio.ImageIO;
26  import java.awt.*;
27  import java.awt.image.BufferedImage;
28  import java.io.File;
29  import java.io.FileInputStream;
30  import java.io.InputStream;
31  
32  /**
33   * @author tuan_nguyenxuan Oct 29, 2010
34   */
35  public class ImageUtils {
36    public static final String KEY_SEPARATOR           = "_";
37    public static final String KEY_DIMENSION_SEPARATOR = "x";
38  
39    public static final String GIF_EXTENDSION          = "gif";
40    private static final Log LOG = ExoLogger.getLogger(ImageUtils.class);
41  
42    /**
43     * @param str Make string params not null
44     */
45    private static void makeNotNull(String... str)
46    {
47      for (String string : str) {
48        if (string == null)
49          string = "";
50      }
51    }
52  
53    /**
54     * @param oldFileName
55     * @param subfix
56     * @param postfix
57     * @return name of resized image name like from "avatar.jpg" to
58     *         "RESIZED_avatar_100x100.jpg"
59     */
60    public static String buildFileName(String oldFileName, String subfix, String postfix) {
61      makeNotNull(oldFileName,subfix,postfix);
62      if(oldFileName.equals(""))
63        return subfix + postfix;
64      int dotIndex = oldFileName.lastIndexOf('.');
65      if(dotIndex < 0)
66        return subfix + oldFileName + postfix;
67      String nameOnly = oldFileName.substring(0, dotIndex);
68      String extendtionAndDot = oldFileName.substring(dotIndex);
69      return subfix + nameOnly + postfix + extendtionAndDot;
70    }
71  
72    /**
73     * @param width
74     * @param height
75     * @return postfix for image name like avatar_100x100
76     */
77  
78    public static String buildImagePostfix(int width, int height) {
79      return KEY_SEPARATOR + (width < 0 ? 0 : width) + KEY_DIMENSION_SEPARATOR
80          + (height < 0 ? 0 : height);
81    }
82  
83    /**
84     * @param imageStream
85     * @param maxWidth
86     * @param maxHeight
87     * @param avatarId
88     * @param avatarFileName
89     * @param avatarMimeType
90     * @param avatarWorkspace
91     * @return new AvatarAtachment that contain parameter values and resized
92     *         avatar
93     */
94    public static AvatarAttachment createResizedAvatarAttachment(InputStream imageStream,
95                                                                 int maxWidth,
96                                                                 int maxHeight,
97                                                                 String avatarId,
98                                                                 String avatarFileName,
99                                                                 String avatarMimeType,
100                                                                String avatarWorkspace) {
101     if (maxHeight <= 0 || maxWidth <= 0) {
102       LOG.warn("Fail to resize image to avatar attachment with dimension <= 0");
103       return null;
104     }
105 
106     try {
107       MimeTypeResolver mimeTypeResolver = new MimeTypeResolver();
108       String extension = mimeTypeResolver.getExtension(avatarMimeType);
109       // TODO: Resize gif image. Now we skip gif because we can't resize it now
110       if (extension.equalsIgnoreCase(GIF_EXTENDSION)) {
111         return null;
112       }
113 
114       BufferedImage image = ImageIO.read(imageStream);
115 
116       int targetHeight = image.getHeight();
117       int targetWidth = image.getWidth();
118 
119       double maxDimensionsRatio =  (double) maxHeight / (double) maxWidth;
120       double imageRatio =  (double) image.getHeight() / (double) image.getWidth();
121 
122       if(imageRatio > maxDimensionsRatio && image.getHeight() > maxHeight) {
123         targetHeight = maxHeight;
124         targetWidth = (maxHeight * image.getWidth()) / image.getHeight();
125       } else if(imageRatio < maxDimensionsRatio && image.getWidth() > maxWidth) {
126         targetHeight = (maxWidth * image.getHeight()) / image.getWidth();
127         targetWidth = maxWidth;
128       }
129 
130       // Create temp file to store resized image to put to avatar attachment
131       File tmp = File.createTempFile("RESIZED", null);
132       image = resizeImage(image, targetWidth, targetHeight);
133 
134       ImageIO.write(image, extension, tmp);
135       
136       // Create new avatar attachment
137       AvatarAttachment newAvatarAttachment = new AvatarAttachment(avatarId,
138                                                                   avatarFileName,
139                                                                   avatarMimeType,
140                                                                   new FileInputStream(tmp),
141                                                                   avatarWorkspace,
142                                                                   System.currentTimeMillis());
143 
144       // Delete temp file
145       tmp.delete();
146       return newAvatarAttachment;
147     } catch (Exception e) {
148       LOG.error("Fail to resize image to avatar attachment: " + e);
149       return null;
150     }
151   }
152 
153   private static BufferedImage resizeImage(BufferedImage image, int width, int height) {
154     final BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
155     final Graphics2D graphics2D = bufferedImage.createGraphics();
156     graphics2D.setComposite(AlphaComposite.Src);
157     //below three lines are for RenderingHints for better image quality
158     graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
159     graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
160     graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
161     graphics2D.drawImage(image, 0, 0, width, height, null);
162     graphics2D.dispose();
163     return bufferedImage;
164   }
165 }