4b52f1f958b14da91323fbfb336c31a0c7c0df68
[mir.git] / source / mircoders / media / MediaHandlerImagesExtern.java
1 /*
2  * Copyright (C) 2001, 2002 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License,
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23  * (or with modified versions of the above that use the same license as the above),
24  * and distribute linked combinations including the two.  You must obey the
25  * GNU General Public License in all respects for all of the code used other than
26  * the above mentioned libraries.  If you modify this file, you may extend this
27  * exception to your version of the file, but you are not obligated to do so.
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30 package mircoders.media;
31
32
33 import java.io.BufferedInputStream;
34 import java.io.File;
35 import java.io.FileInputStream;
36 import java.io.IOException;
37 import java.io.InputStream;
38
39 import mir.entity.Entity;
40 import mir.log.LoggerWrapper;
41 import mir.media.MediaExc;
42 import mir.media.MediaFailure;
43 import mir.media.image.ImageMagickImageProcessor;
44 import mir.media.image.ImageProcessor;
45 import mir.misc.StringUtil;
46 import mir.util.FileRoutines;
47
48 /**
49  * Image handler that stores images outside of the database.
50  * 
51  * @author Zapata
52  * @version 1.0
53  */
54
55 public class MediaHandlerImagesExtern extends MediaHandlerGeneric
56 {
57   private int maxSize;
58   private int maxIconSize;
59   private float minDescaleRatio;
60   private int minDescaleReduction;
61   private boolean scaleImages;
62   
63   public MediaHandlerImagesExtern() {
64     logger = new LoggerWrapper("Media.Images.Extern");
65     maxSize = configuration.getInt("Producer.Image.MaxSize");
66     maxIconSize = configuration.getInt("Producer.Image.MaxIconSize");
67     minDescaleRatio = configuration.getFloat("Producer.Image.MinDescalePercentage")/100;
68     minDescaleReduction = configuration.getInt("Producer.Image.MinDescaleReduction");
69     scaleImages = configuration.getBoolean("Producer.Image.ScaleImages");
70   }
71
72   public void produce(Entity anImageEntity, Entity mediaTypeEnt) throws MediaExc, MediaFailure {
73     try {
74       String date = anImageEntity.getFieldValue("date");
75       String datePath = StringUtil.webdbDate2path(date);
76       String ext = "." + mediaTypeEnt.getFieldValue("name");
77       String fileBasePath = datePath + anImageEntity.getId();
78       String filePath = fileBasePath + ext;
79
80       String imageFilePath = getBaseStoragePath() + File.separator + filePath;
81       File imageFile = new File(imageFilePath);
82       
83       if (!imageFile.exists()) {
84         throw new MediaExc("error in MediaHandlerImagesExtern.execute(): "
85             + filePath + " does not exist!");
86       } else {
87         ImageProcessor processor = new ImageMagickImageProcessor(imageFile);
88         String iconPath = getBaseIconStoragePath() + fileBasePath + ".jpg";
89         String iconStoragePath = doIconScaling(processor, iconPath);
90         anImageEntity.setFieldValue("icon_height", new Integer(processor.getScaledHeight()).toString());
91         anImageEntity.setFieldValue("icon_width", new Integer(processor.getScaledWidth()).toString());
92         anImageEntity.setFieldValue("icon_path", iconPath);
93         
94         if (scaleImages) {
95           String imageOriginalRelPath = doImageScaling(filePath, imageFile, processor);
96           anImageEntity.setFieldValue("original_file_path", imageOriginalRelPath);
97           anImageEntity.setFieldValue("img_height", Integer.toString(processor.getScaledHeight()));
98           anImageEntity.setFieldValue("img_width", Integer.toString(processor.getScaledWidth()));
99         } else {
100           anImageEntity.setFieldValue("img_height", new Integer(processor.getHeight()).toString());
101           anImageEntity.setFieldValue("img_width", new Integer(processor.getWidth()).toString());
102         }
103         processor.cleanup();
104         anImageEntity.setFieldValue("publish_path", filePath);
105         anImageEntity.update();
106         reportChange(iconStoragePath);
107         reportChange(imageFilePath);
108       }
109     }
110     catch(Throwable t) {
111       logger.error("MediaHandlerImagesExtern.execute: " + t.getMessage(), t);
112       throw new MediaFailure(t.getMessage(), t);
113     }
114   }
115
116     /**
117      * Scale an icon image and write it to the file system.
118      * @param processor
119      * @param iconPath
120      * @return
121      * @throws MediaExc
122      */
123     private String doIconScaling(ImageProcessor processor, String iconPath) throws MediaExc {
124         String iconStoragePath = configuration.getString("Producer.StorageRoot") + iconPath;
125         File iconFile = new File(iconStoragePath);
126         processor.descaleImage(maxIconSize, minDescaleRatio, minDescaleReduction);
127         File dir = new File(iconFile.getParent());
128         if (dir != null && !dir.exists()) {
129           dir.mkdirs();
130         }
131         processor.writeScaledData(iconFile, "JPEG");
132         return iconStoragePath;
133     }
134
135     /**
136      * Make the resized file.
137      * @param filePath
138      * @param imageFile
139      * @param processor
140      * @return
141      * @throws MediaExc
142      * @throws IOException
143      */
144     private String doImageScaling(String filePath, File imageFile, ImageProcessor processor) throws MediaExc, IOException {
145         // get a file path where the the original image should be saved if image resizing is turned on
146           String imagesOriginalDir = configuration.getString("Producer.ImagesOriginalDir.Path");
147           String imagesOriginalDirRelPath = configuration.getString("Producer.ImagesOriginalDir.RelPath");
148           String imageOriginalFilePath = imagesOriginalDir + filePath;
149           String imageOriginalRelPath = imagesOriginalDirRelPath +  filePath;
150           File originalFile = new File(imageOriginalFilePath);   
151           processor.descaleImage(maxSize, minDescaleRatio, minDescaleReduction);
152           File originalDir = new File(originalFile.getParent());
153           if (originalDir != null && !originalDir.exists()) {
154             originalDir.mkdirs();
155           }
156           if (!originalFile.exists()) {
157             FileRoutines.copy(imageFile, originalFile);
158             reportChange(originalFile.getAbsolutePath());
159           }
160           // yoss: don't write the scaled data again if it's the same size as
161           // the file that's there right now. Image producer runs are 4 times
162           // faster this way.
163           if (processor.getScaledFileSize() != imageFile.length()) {
164               processor.writeScaledData(imageFile, "JPEG");
165           }
166         return imageOriginalRelPath;
167     }
168
169 /** {@inheritDoc} */
170   public InputStream getThumbnail(Entity anImageEntity) throws MediaExc, MediaFailure {
171     try {
172       File file = new File(configuration.getString("Producer.StorageRoot") + anImageEntity.getFieldValue("icon_path"));
173
174       if (!file.exists()) {
175         // hackish
176         file = new File(configuration.getHome(), "../img/photo_big.gif");
177       }
178
179       return new BufferedInputStream(
180         new FileInputStream(file),8192);
181     }
182     catch (Throwable t) {
183       return null;
184     }
185   }
186
187   public String getIconMimeType(Entity anImageEntity, Entity aMediaType) {
188     return "image/jpeg";
189   }
190
191   public String getBaseStoragePath()
192   {
193     return configuration.getString("Producer.Image.Path");
194   }
195
196   public String getBaseIconStoragePath()
197   {
198     return configuration.getString("Producer.Image.IconPath");
199   }
200
201   public String getPublishHost()
202   {
203     return StringUtil.removeSlash(configuration.getString("Producer.Image.Host"));
204   }
205
206   public String getTinyIconName()
207   {
208     return configuration.getString("Producer.Icon.TinyImage");
209   }
210
211   public String getBigIconName()
212   {
213     return configuration.getString("Producer.Icon.BigImage");
214   }
215
216   public String getIconAltName()
217   {
218     return "Image";
219   }
220
221   public String getDescr(Entity mediaType)
222   {
223      return "image/jpeg";
224   }
225 }