KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > meshcms > core > AbstractThumbnail


1 /*
2  * MeshCMS - A simple CMS based on SiteMesh
3  * Copyright (C) 2004-2007 Luciano Vernaschi
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
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, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * You can contact the author at http://www.cromoteca.com
20  * and at info@cromoteca.com
21  */

22
23 package org.meshcms.core;
24
25 import java.awt.*;
26 import java.awt.image.*;
27 import java.io.*;
28 import org.meshcms.util.*;
29
30 public abstract class AbstractThumbnail {
31   /**
32    * Default color for thumbnail borders.
33    */

34   public static final Color DEFAULT_BORDER_COLOR = new Color(216, 206, 203);
35
36   /**
37    * @return the recommended file name for the current thumbnail.
38    */

39   public abstract String JavaDoc getSuggestedFileName();
40
41   /**
42    * Creates the thumbnail. Called only if needed.
43    * @param imageFile source image file to create thumbnail from
44    * @param thumbnailFile destination file
45    *
46    * @return true if succeded to create the thumbnail and false if an error(exception) occured
47    */

48   protected abstract boolean createThumbnail(File imageFile, File thumbnailFile);
49
50   /**
51    * Checks the current thumbnail, and creates it if not available or too old.
52    */

53   public Path checkAndCreate(WebSite webSite, Path imagePath,
54       String JavaDoc thumbnailFileName) {
55     Path thumbnailPath = webSite.getGeneratedFilesPath().add(imagePath);
56     thumbnailPath = thumbnailPath.add(getClass().getName(), thumbnailFileName);
57     File imageFile = webSite.getFile(imagePath);
58
59     if (!imageFile.exists() || imageFile.isDirectory()) {
60       return null;
61     }
62
63     File thumbnailFile = webSite.getFile(thumbnailPath);
64
65     if (!thumbnailFile.exists() ||
66         thumbnailFile.lastModified() < imageFile.lastModified()) {
67       thumbnailFile.getParentFile().mkdirs();
68
69       if (!createThumbnail(imageFile, thumbnailFile)) {
70         return null;
71       }
72     }
73
74     return thumbnailPath;
75   }
76
77   public static void drawResizedImage(Graphics g, BufferedImage image, int x, int y,
78       int width, int height, boolean highQuality) {
79     if (highQuality) {
80       BufferedImage resized = resize(image, width, height);
81       g.drawImage(resized, x, y, null);
82       resized.flush();
83     } else {
84       g.drawImage(image, x, y, width, height, null);
85     }
86   }
87
88   /**
89    * Resizes an image. The method used is chosen according to the ratio between
90    * original and new size.
91    */

92   public static BufferedImage resize(BufferedImage in, int width, int height) {
93     checkImageSize(width, height);
94     int imageWidth = in.getWidth();
95     int imageHeight = in.getHeight();
96
97     return (imageWidth * imageHeight) / (width * height) > 4 ?
98         averageResize(in, width, height) :
99         linearResize(in, width, height);
100   }
101
102   /**
103    * Resizes an image using a simple linear interpolation (suitable
104    * to resize to a size similar to the original one).
105    */

106   public static BufferedImage linearResize(BufferedImage in, int width, int height) {
107     checkImageSize(width, height);
108     int imageWidth = in.getWidth();
109     int imageHeight = in.getHeight();
110     int[] pixels = in.getRGB(0, 0, imageWidth, imageHeight, null, 0, imageWidth);
111     int[] outPixels = new int[width * height];
112     int a, r, g, b;
113     int ox, x0, x1, oy, y0, y1;
114     int d = width * height;
115     int p11, p10, p01, p00;
116     int idx;
117
118     for (int py = 0; py < height; py++) {
119       for (int px = 0; px < width; px++) {
120         idx = py * width + px;
121         ox = px * imageWidth;
122         x0 = ox % width;
123         x1 = width - x0;
124         ox /= width;
125         oy = py * imageHeight;
126         y0 = oy % height;
127         y1 = height - y0;
128         oy /= height;
129
130         if (ox >= imageWidth - 1 || oy >= imageHeight - 1) {
131           outPixels[idx] = pixels[oy * imageWidth + ox];
132         } else {
133           p11 = pixels[(oy + 1) * imageWidth + (ox + 1)];
134           p10 = pixels[oy * imageWidth + (ox + 1)];
135           p01 = pixels[(oy + 1) * imageWidth + ox];
136           p00 = pixels[oy * imageWidth + ox];
137
138           a = ((x0 * y0 * ((p11 >> 24) & 0xFF) +
139                 x0 * y1 * ((p10 >> 24) & 0xFF) +
140                 x1 * y0 * ((p01 >> 24) & 0xFF) +
141                 x1 * y1 * ((p00 >> 24) & 0xFF)) / d);
142
143           r = ((x0 * y0 * ((p11 >> 16) & 0xFF) +
144                 x0 * y1 * ((p10 >> 16) & 0xFF) +
145                 x1 * y0 * ((p01 >> 16) & 0xFF) +
146                 x1 * y1 * ((p00 >> 16) & 0xFF)) / d);
147
148           g = ((x0 * y0 * ((p11 >> 8) & 0xFF) +
149                 x0 * y1 * ((p10 >> 8) & 0xFF) +
150                 x1 * y0 * ((p01 >> 8) & 0xFF) +
151                 x1 * y1 * ((p00 >> 8) & 0xFF)) / d);
152
153           b = ((x0 * y0 * (p11 & 0xFF) +
154                 x0 * y1 * (p10 & 0xFF) +
155                 x1 * y0 * (p01 & 0xFF) +
156                 x1 * y1 * (p00 & 0xFF)) / d);
157
158           outPixels[idx] = (a << 24) | (r << 16) | (g << 8) | b;
159         }
160       }
161     }
162
163     BufferedImage out = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
164     out.setRGB(0, 0, width, height, outPixels, 0, width);
165     return out;
166   }
167
168   /**
169    * Resizes an image using a simple area average (suitable to create images that
170    * are much smaller than the original).
171    */

172   public static BufferedImage averageResize(BufferedImage in, int width, int height) {
173     checkImageSize(width, height);
174     int imageWidth = in.getWidth();
175     int imageHeight = in.getHeight();
176     int[] pixels = in.getRGB(0, 0, imageWidth, imageHeight, null, 0, imageWidth);
177     int[] outPixels = new int[width * height];
178     int nw = Math.max(imageWidth / width + 1, 2);
179     int nh = Math.max(imageHeight / height + 1, 2);
180     int idx, i2, j2, argb, cnt;
181     int[] v = new int[3];
182     float kw = (float) imageWidth / (float) width;
183     float kh = (float) imageHeight / (float) height;
184     float nw2 = nw / 2.0F;
185     float nh2 = nh / 2.0F;
186
187     for (int i = 0; i < height; i++) {
188       for (int j = 0; j < width; j++) {
189         v[0] = v[1] = v[2] = cnt = 0;
190
191         i2 = (int) ((i + 0.5F) * kh - nh2);
192         j2 = (int) ((j + 0.5F) * kw - nw2);
193
194         for (int k = 0; k < nh; k++) {
195           for (int l = 0; l < nw; l++) {
196             idx = (j2 + l) + (i2 + k) * imageWidth;
197
198             if (idx > -1 && idx < pixels.length) {
199               argb = pixels[idx];
200               v[0] += (argb >> 16) & 0xFF;
201               v[1] += (argb >> 8) & 0xFF;
202               v[2] += argb & 0xFF;
203               cnt++;
204             }
205           }
206         }
207
208         outPixels[j + i * width] = 0xFF000000 | ((v[0] / cnt) << 16) |
209             ((v[1] / cnt) << 8) | (v[2] / cnt);
210       }
211     }
212
213     BufferedImage out = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
214     out.setRGB(0, 0, width, height, outPixels, 0, width);
215     return out;
216   }
217
218   private static void checkImageSize(int width, int height) {
219     if (width < 1) {
220       throw new IllegalArgumentException JavaDoc("Invalid width: " + width + " pixels");
221     }
222
223     if (height < 1) {
224       throw new IllegalArgumentException JavaDoc("Invalid height: " + height + " pixels");
225     }
226   }
227 }
228
Popular Tags