Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
936 | dev | 1 | package ak.photoalbum.images; |
2 | |||
3 | import java.util.Map; |
||
4 | import java.util.HashMap; |
||
5 | import java.util.Comparator; |
||
6 | import java.util.Arrays; |
||
7 | import java.io.File; |
||
8 | import java.io.FileFilter; |
||
9 | import java.io.IOException; |
||
10 | import java.io.FileInputStream; |
||
11 | import java.io.FileOutputStream; |
||
12 | import java.io.OutputStream; |
||
13 | import java.awt.Image; |
||
14 | import java.awt.Toolkit; |
||
15 | import java.awt.Graphics; |
||
16 | import java.awt.image.BufferedImage; |
||
17 | import java.awt.image.ImageObserver; |
||
18 | import java.awt.image.PixelGrabber; |
||
19 | import javax.imageio.ImageIO; |
||
20 | import org.apache.log4j.Logger; |
||
21 | import marcoschmidt.image.ImageInfo; |
||
22 | import ak.photoalbum.util.FileUtils; |
||
23 | import ak.photoalbum.util.FileNameComparator; |
||
24 | |||
25 | public class Thumbnailer |
||
26 | { |
||
27 | protected static final String DEFAULT_FORMAT = "jpg"; |
||
28 | protected static final String SMALL_SUFFIX = ".small"; |
||
29 | protected static final String MEDIUM_SUFFIX = ".medium"; |
||
30 | protected static final String DIR_SUFFIX = ".dir"; |
||
31 | protected static final int DEFAULT_SMALL_WIDTH = 120; |
||
32 | protected static final int DEFAULT_SMALL_HEIGHT = 120; |
||
33 | protected static final int DEFAULT_MEDIUM_WIDTH = 800; |
||
34 | protected static final int DEFAULT_MEDIUM_HEIGHT = 800; |
||
35 | |||
36 | protected Logger logger; |
||
37 | protected ImageResizer resizer; |
||
38 | protected int smallWidth = DEFAULT_SMALL_WIDTH; |
||
39 | protected int smallHeight = DEFAULT_SMALL_HEIGHT; |
||
40 | protected int mediumWidth = DEFAULT_MEDIUM_WIDTH; |
||
41 | protected int mediumHeight = DEFAULT_MEDIUM_HEIGHT; |
||
42 | protected File cacheDir; |
||
43 | protected String format = DEFAULT_FORMAT; |
||
44 | protected Map smallCache = new HashMap(); |
||
45 | protected Map mediumCache = new HashMap(); |
||
46 | protected Map dirCache = new HashMap(); |
||
47 | protected File imagesRoot; |
||
48 | protected FileFilter imagesFilter = null; |
||
49 | protected Comparator fileNameComparator = new FileNameComparator(true); |
||
50 | protected Comparator fileNameComparatorRev = new FileNameComparator(false); |
||
51 | |||
52 | protected File dirTemplate; |
||
53 | protected ThumbnailPosition[] dirThumbnailPositions; |
||
54 | protected int[] dirTemplateSize; |
||
55 | protected long dirTemplateTimestamp; |
||
56 | |||
57 | public Thumbnailer() |
||
58 | { |
||
59 | this.logger = Logger.getLogger(this.getClass()); |
||
60 | } |
||
61 | |||
62 | public String getMime() |
||
63 | { |
||
64 | return FileUtils.getMime(format); |
||
65 | } |
||
66 | |||
67 | public int[] getDirSize(File origin) |
||
68 | throws IOException |
||
69 | { |
||
70 | if(dirTemplateSize == null |
||
71 | || dirTemplateTimestamp != dirTemplate.lastModified()) |
||
72 | { |
||
73 | dirTemplateSize = getOriginSize(dirTemplate); |
||
74 | dirTemplateTimestamp = dirTemplate.lastModified(); |
||
75 | } |
||
76 | |||
77 | return dirTemplateSize; |
||
78 | } |
||
79 | |||
80 | public int[] getSmallSize(File origin) |
||
81 | throws IOException |
||
82 | { |
||
83 | CachedFile cached = getCached(smallCache, origin); |
||
84 | |||
85 | if(cached == null) { |
||
86 | int[] originSize = getOriginSize(origin); |
||
87 | |||
88 | return calcSizes(originSize[0], originSize[1], smallWidth, smallHeight); |
||
89 | } |
||
90 | else { |
||
91 | int[] originSize = new int[2]; |
||
92 | |||
93 | originSize[0] = cached.getWidth(); |
||
94 | originSize[1] = cached.getHeight(); |
||
95 | |||
96 | return originSize; |
||
97 | } |
||
98 | } |
||
99 | |||
100 | public int[] getMediumSize(File origin) |
||
101 | throws IOException |
||
102 | { |
||
103 | CachedFile cached = getCached(mediumCache, origin); |
||
104 | |||
105 | if(cached == null) { |
||
106 | int[] originSize = getOriginSize(origin); |
||
107 | |||
108 | return calcSizes(originSize[0], originSize[1], mediumWidth, mediumHeight); |
||
109 | } |
||
110 | else { |
||
111 | int[] originSize = new int[2]; |
||
112 | |||
113 | originSize[0] = cached.getWidth(); |
||
114 | originSize[1] = cached.getHeight(); |
||
115 | |||
116 | return originSize; |
||
117 | } |
||
118 | } |
||
119 | |||
120 | protected int[] getOriginSize(File origin) |
||
121 | throws IOException |
||
122 | { |
||
123 | if(logger.isDebugEnabled()) |
||
124 | logger.debug("get size of " + origin.getCanonicalPath()); |
||
125 | |||
126 | ImageInfo ii = new ImageInfo(); |
||
127 | FileInputStream in = null; |
||
128 | int[] res = new int[2]; |
||
129 | |||
130 | try { |
||
131 | in = new FileInputStream(origin); |
||
132 | ii.setInput(in); |
||
133 | |||
134 | if(!ii.check()) { |
||
135 | logger.warn("not supported format of " + origin.getCanonicalPath()); |
||
136 | res[0] = 0; |
||
137 | res[1] = 0; |
||
138 | } |
||
139 | else{ |
||
140 | res[0] = ii.getWidth(); |
||
141 | res[1] = ii.getHeight(); |
||
142 | } |
||
143 | } |
||
144 | finally { |
||
145 | if(in != null) in.close(); |
||
146 | } |
||
147 | |||
148 | return res; |
||
149 | } |
||
150 | |||
151 | public void rebuildCache() |
||
152 | throws IOException |
||
153 | { |
||
154 | logger.info("rebuild cache"); |
||
155 | |||
156 | deleteCache(); |
||
157 | buildCache(); |
||
158 | } |
||
159 | |||
160 | public void deleteCache() |
||
161 | throws IOException |
||
162 | { |
||
163 | logger.info("delete cache"); |
||
164 | |||
165 | deleteCache(cacheDir); |
||
166 | } |
||
167 | |||
168 | public void buildCache() |
||
169 | throws IOException |
||
170 | { |
||
171 | logger.info("build cache"); |
||
172 | |||
173 | buildCache(imagesRoot); |
||
174 | } |
||
175 | |||
176 | protected void deleteCache(File dir) |
||
177 | throws IOException |
||
178 | { |
||
179 | File[] children = dir.listFiles(); |
||
180 | |||
181 | if(children == null) return; // the dir does not exists |
||
182 | |||
183 | Arrays.sort(children, fileNameComparator); |
||
184 | |||
185 | for(int i = 0; i < children.length; i++) { |
||
186 | if(children[i].isDirectory()) |
||
187 | deleteCache(children[i]); |
||
188 | else |
||
189 | children[i].delete(); |
||
190 | } |
||
191 | dir.delete(); |
||
192 | } |
||
193 | |||
194 | protected void buildCache(File dir) |
||
195 | throws IOException |
||
196 | { |
||
197 | File[] children; |
||
198 | |||
199 | if(imagesFilter == null) |
||
200 | children = dir.listFiles(); |
||
201 | else |
||
202 | children = dir.listFiles(imagesFilter); |
||
203 | |||
204 | if(children == null) return; // the dir does not exists |
||
205 | |||
206 | Arrays.sort(children, fileNameComparator); |
||
207 | |||
208 | for(int i = 0; i < children.length; i++) { |
||
209 | if(children[i].isDirectory()) { |
||
210 | writeDir(children[i], null); |
||
211 | buildCache(children[i]); |
||
212 | } |
||
213 | else { |
||
214 | writeSmall(children[i], null); |
||
215 | writeMedium(children[i], null); |
||
216 | } |
||
217 | } |
||
218 | } |
||
219 | |||
220 | protected CachedFile getCached(Map cache, File imageFile) |
||
221 | throws IOException |
||
222 | { |
||
223 | CachedFile cached = (CachedFile)cache.get(imageFile.getCanonicalPath()); |
||
224 | |||
225 | if(cached == null || !cached.getFile().exists()) { |
||
226 | logger.debug("not found in cache"); |
||
227 | return null; |
||
228 | } |
||
229 | |||
230 | if(cached.getOriginTimestamp() != imageFile.lastModified()) { |
||
231 | cached.getFile().delete(); |
||
232 | cache.remove(imageFile.getCanonicalPath()); |
||
233 | logger.debug("timestamps dont match"); |
||
234 | return null; |
||
235 | } |
||
236 | |||
237 | return cached; |
||
238 | } |
||
239 | |||
240 | protected boolean writeCached(Map cache, File imageFile, OutputStream out) |
||
241 | throws IOException |
||
242 | { |
||
243 | CachedFile cached = getCached(cache, imageFile); |
||
244 | |||
245 | if(cached == null) return false; |
||
246 | |||
247 | if(logger.isDebugEnabled()) |
||
248 | logger.debug("write cached " + imageFile.getCanonicalPath()); |
||
249 | |||
250 | if(out != null) { |
||
251 | FileInputStream in = null; |
||
252 | |||
253 | try { |
||
254 | in = new FileInputStream(cached.getFile()); |
||
255 | FileUtils.copyStreams(in, out); |
||
256 | } |
||
257 | finally { |
||
258 | if(in != null) in.close(); |
||
259 | } |
||
260 | } |
||
261 | |||
262 | return true; |
||
263 | } |
||
264 | |||
265 | protected void cacheThumbnail(Map cache, File imageFile, |
||
266 | BufferedImage thumbnail, String suffix, int width, int height) |
||
267 | throws IOException |
||
268 | { |
||
269 | logger.debug("cache thumbnail " + suffix + " " |
||
270 | + imageFile.getCanonicalPath()); |
||
271 | |||
272 | File dir = getCacheFileDir(imageFile); |
||
273 | File cacheFile = new File(dir, |
||
274 | imageFile.getName() + suffix + "." + format); |
||
275 | |||
276 | dir.mkdirs(); |
||
277 | ImageIO.write(thumbnail, format, cacheFile); |
||
278 | |||
279 | cache.put(imageFile.getCanonicalPath(), |
||
280 | new CachedFile(cacheFile, imageFile, |
||
281 | cacheFile.lastModified(), imageFile.lastModified(), width, height)); |
||
282 | } |
||
283 | |||
284 | public void startup() |
||
285 | throws IOException |
||
286 | { |
||
287 | logger.info("startup"); |
||
288 | loadCaches(cacheDir); |
||
289 | logger.info("started"); |
||
290 | } |
||
291 | |||
292 | protected void loadCaches(File dir) |
||
293 | throws IOException |
||
294 | { |
||
295 | if(logger.isDebugEnabled()) |
||
296 | logger.debug("load caches in " + dir.getCanonicalPath()); |
||
297 | |||
298 | File[] children = dir.listFiles(); |
||
299 | String dirEnd = DIR_SUFFIX + "." + format; |
||
300 | String smallEnd = SMALL_SUFFIX + "." + format; |
||
301 | String mediumEnd = MEDIUM_SUFFIX + "." + format; |
||
302 | |||
303 | if(children == null) return; // the dir does not exists |
||
304 | |||
305 | Arrays.sort(children, fileNameComparator); |
||
306 | |||
307 | for(int i = 0; i < children.length; i++) { |
||
308 | if(children[i].isDirectory()) |
||
309 | loadCaches(children[i]); |
||
310 | else { |
||
311 | File origin; |
||
312 | Map cache; |
||
313 | |||
314 | if(children[i].getName().endsWith(smallEnd)) { |
||
315 | origin = getOriginFile(children[i], SMALL_SUFFIX); |
||
316 | cache = smallCache; |
||
317 | |||
318 | if(logger.isDebugEnabled()) |
||
319 | logger.debug("load cached small " + children[i].getCanonicalPath() |
||
320 | + " for " + origin.getCanonicalPath()); |
||
321 | } |
||
322 | else if(children[i].getName().endsWith(mediumEnd)) { |
||
323 | origin = getOriginFile(children[i], MEDIUM_SUFFIX); |
||
324 | cache = mediumCache; |
||
325 | |||
326 | if(logger.isDebugEnabled()) |
||
327 | logger.debug("load cached medium " + children[i].getCanonicalPath() |
||
328 | + " for " + origin.getCanonicalPath()); |
||
329 | } |
||
330 | else if(children[i].getName().endsWith(dirEnd)) { |
||
331 | origin = getOriginFile(children[i], DIR_SUFFIX); |
||
332 | cache = dirCache; |
||
333 | |||
334 | if(logger.isDebugEnabled()) |
||
335 | logger.debug("load cached dir " + children[i].getCanonicalPath() |
||
336 | + " for " + origin.getCanonicalPath()); |
||
337 | } |
||
338 | else { |
||
339 | if(logger.isInfoEnabled()) |
||
340 | logger.warn( |
||
341 | "unknown type of cached " + children[i].getCanonicalPath()); |
||
342 | |||
343 | continue; |
||
344 | } |
||
345 | |||
346 | long originTimestamp = origin.lastModified(); |
||
347 | long cachedTimestamp = children[i].lastModified(); |
||
348 | int[] sizes = getOriginSize(children[i]); |
||
349 | |||
350 | if(origin.exists() && cachedTimestamp >= originTimestamp) { |
||
351 | cache.put(origin.getCanonicalPath(), |
||
352 | new CachedFile(children[i], origin, cachedTimestamp, |
||
353 | originTimestamp, sizes[0], sizes[1])); |
||
354 | |||
355 | logger.debug("added"); |
||
356 | } |
||
357 | else { |
||
358 | children[i].delete(); |
||
359 | |||
360 | if(logger.isDebugEnabled()) |
||
361 | logger.debug("deleted: " + origin.exists() |
||
362 | + " " + cachedTimestamp + " " + originTimestamp); |
||
363 | } |
||
364 | } |
||
365 | } |
||
366 | } |
||
367 | |||
368 | protected File getOriginFile(File cached, String suffix) |
||
369 | throws IOException |
||
370 | { |
||
371 | String fileEnd = suffix + "." + format; |
||
372 | String fileName = cached.getName(); |
||
373 | String cachedPath = cached.getParentFile().getCanonicalPath(); |
||
374 | String cacheRoot = cacheDir.getCanonicalPath(); |
||
375 | |||
376 | fileName = fileName.substring(0, fileName.length() - fileEnd.length()); |
||
377 | |||
378 | if(!cacheRoot.equals(cachedPath)) |
||
379 | if(!cacheRoot.endsWith(File.separator)) cacheRoot += File.separator; |
||
380 | |||
381 | return new File(imagesRoot, cachedPath.substring(cacheRoot.length()) |
||
382 | + File.separator + fileName); |
||
383 | } |
||
384 | |||
385 | protected File getCacheFileDir(File imageFile) |
||
386 | throws IOException |
||
387 | { |
||
388 | String imagePath = imageFile.getParentFile().getCanonicalPath(); |
||
389 | String rootPath = imagesRoot.getCanonicalPath(); |
||
390 | |||
391 | if(imagePath.equals(rootPath)) return cacheDir; |
||
392 | if(!rootPath.endsWith(File.separator)) rootPath += File.separator; |
||
393 | |||
394 | if(!imagePath.startsWith(rootPath)) |
||
395 | throw new RuntimeException("Image " + imageFile.getCanonicalPath() |
||
396 | + " is not under images root " + imagesRoot.getCanonicalPath()); |
||
397 | |||
398 | return new File(cacheDir, imagePath.substring(rootPath.length())); |
||
399 | } |
||
400 | |||
401 | public void writeSmall(File imageFile, OutputStream out) |
||
402 | throws IOException |
||
403 | { |
||
404 | if(logger.isInfoEnabled()) |
||
405 | logger.info("write small " + imageFile.getCanonicalPath()); |
||
406 | |||
407 | if(writeCached(smallCache, imageFile, out)) return; |
||
408 | |||
409 | BufferedImage small = createThumbnail(imageFile, smallWidth, smallHeight); |
||
410 | |||
411 | if(small != null) { |
||
412 | int sizes[] = calcSizes( |
||
413 | small.getWidth(null), small.getHeight(null), smallWidth, smallHeight); |
||
414 | cacheThumbnail( |
||
415 | smallCache, imageFile, small, SMALL_SUFFIX, sizes[0], sizes[1]); |
||
416 | |||
417 | if(out != null) ImageIO.write(small, format, out); |
||
418 | } |
||
419 | } |
||
420 | |||
421 | public void writeMedium(File imageFile, OutputStream out) |
||
422 | throws IOException |
||
423 | { |
||
424 | if(logger.isInfoEnabled()) |
||
425 | logger.info("write medium " + imageFile.getCanonicalPath()); |
||
426 | |||
427 | if(writeCached(mediumCache, imageFile, out)) return; |
||
428 | |||
429 | BufferedImage medium |
||
430 | = createThumbnail(imageFile, mediumWidth, mediumHeight); |
||
431 | |||
432 | if(medium != null) { |
||
433 | int sizes[] = calcSizes(medium.getWidth(null), medium.getHeight(null), |
||
434 | mediumWidth, mediumHeight); |
||
435 | cacheThumbnail( |
||
436 | mediumCache, imageFile, medium, MEDIUM_SUFFIX, sizes[0], sizes[1]); |
||
437 | |||
438 | if(out != null) ImageIO.write(medium, format, out); |
||
439 | } |
||
440 | } |
||
441 | |||
442 | public void writeDir(File dir, OutputStream out) |
||
443 | throws IOException |
||
444 | { |
||
445 | if(logger.isInfoEnabled()) |
||
446 | logger.info("write dir " + dir.getCanonicalPath()); |
||
447 | |||
448 | if(writeCached(dirCache, dir, out)) return; |
||
449 | |||
450 | BufferedImage thumbnail = createDirThumbnail(dir); |
||
451 | |||
452 | if(thumbnail != null) { |
||
453 | if(dirTemplateSize == null |
||
454 | || dirTemplateTimestamp != dirTemplate.lastModified()) |
||
455 | { |
||
456 | dirTemplateSize = getOriginSize(dirTemplate); |
||
457 | dirTemplateTimestamp = dirTemplate.lastModified(); |
||
458 | } |
||
459 | |||
460 | cacheThumbnail(dirCache, dir, thumbnail, DIR_SUFFIX, |
||
461 | dirTemplateSize[0], dirTemplateSize[1]); |
||
462 | |||
463 | if(out != null) ImageIO.write(thumbnail, format, out); |
||
464 | } |
||
465 | } |
||
466 | |||
467 | synchronized protected BufferedImage createThumbnail(File imageFile, |
||
468 | int width, int height) |
||
469 | throws IOException |
||
470 | { |
||
471 | if(logger.isDebugEnabled()) |
||
472 | logger.debug("create thumbnail " + imageFile.getCanonicalPath()); |
||
473 | |||
474 | Image image = loadImage(imageFile.getCanonicalPath()); |
||
475 | // = ImageIO.read(imageFile); |
||
476 | int[] sizes; |
||
477 | |||
478 | if(image == null) { // not supported format |
||
479 | logger.warn("unsupported format for origin or operation interrupted"); |
||
480 | |||
481 | return null; |
||
482 | } |
||
483 | else { |
||
484 | sizes = calcSizes(image.getWidth(null), image.getHeight(null), |
||
485 | width, height); |
||
486 | logger.debug("resize to " + sizes[0] + "x" + sizes[1]); |
||
487 | |||
488 | return resizer.resize(image, sizes[0], sizes[1]); |
||
489 | } |
||
490 | } |
||
491 | |||
492 | synchronized protected BufferedImage createDirThumbnail(File dir) |
||
493 | throws IOException |
||
494 | { |
||
495 | if(logger.isDebugEnabled()) |
||
496 | logger.debug("create dir thumbnail " + dir.getCanonicalPath()); |
||
497 | |||
498 | Image template = loadImage(dirTemplate.getCanonicalPath()); |
||
499 | BufferedImage dirThumbnail; |
||
500 | Graphics graphics; |
||
501 | int count; |
||
502 | File[] firstFiles; |
||
503 | |||
504 | if(template == null) { // not supported format |
||
505 | logger.warn("unsupported format for template or operation interrupted"); |
||
506 | |||
507 | return null; |
||
508 | } |
||
509 | |||
510 | dirThumbnail = createBufferedImage(template); |
||
511 | |||
512 | graphics = dirThumbnail.getGraphics(); |
||
513 | count = dirThumbnailPositions.length; |
||
514 | firstFiles = new File[count]; |
||
515 | count = getFirstFiles(dir, count, firstFiles, 0); |
||
516 | |||
517 | for(int i = 0; i < count; i++) { |
||
518 | Image image = loadImage(firstFiles[i].getCanonicalPath()); |
||
519 | |||
520 | if(image == null) { // not supported format |
||
521 | logger.warn("unsupported format for origin or operation interrupted"); |
||
522 | |||
523 | return null; |
||
524 | } |
||
525 | else { |
||
526 | BufferedImage thumbnail; |
||
527 | int[] sizes; |
||
528 | |||
529 | sizes = calcSizes(image.getWidth(null), image.getHeight(null), |
||
530 | dirThumbnailPositions[i].getWidth(), |
||
531 | dirThumbnailPositions[i].getHeight()); |
||
532 | |||
533 | thumbnail = resizer.resize(image, sizes[0], sizes[1]); |
||
534 | graphics.drawImage(thumbnail, |
||
535 | getXPosition(dirThumbnailPositions[i].getX(), |
||
536 | dirThumbnailPositions[i].getWidth(), sizes[0], |
||
537 | dirThumbnailPositions[i].getHorAlign()), |
||
538 | getYPosition(dirThumbnailPositions[i].getY(), |
||
539 | dirThumbnailPositions[i].getHeight(), sizes[1], |
||
540 | dirThumbnailPositions[i].getVertAlign()), |
||
541 | null); |
||
542 | } |
||
543 | } |
||
544 | |||
545 | return dirThumbnail; |
||
546 | } |
||
547 | |||
548 | protected Image loadImage(String fileName) |
||
549 | { |
||
550 | // FIXME: probably toolbox reads an image not by every request but |
||
551 | // caches it |
||
552 | Toolkit toolkit = Toolkit.getDefaultToolkit(); |
||
553 | Image image = toolkit.getImage(fileName); |
||
554 | |||
555 | toolkit.prepareImage(image, -1, -1, null); |
||
556 | |||
557 | while(true) { |
||
558 | int status = toolkit.checkImage(image, -1, -1, null); |
||
559 | |||
560 | if((status & ImageObserver.ALLBITS) != 0) break; |
||
561 | if((status & ImageObserver.ERROR) != 0) return null; |
||
562 | |||
563 | try { |
||
564 | Thread.sleep(100); |
||
565 | } |
||
566 | catch(Exception ex) { |
||
567 | return null; |
||
568 | } |
||
569 | } |
||
570 | |||
571 | return image; |
||
572 | } |
||
573 | |||
574 | protected int[] calcSizes(int width, int height, int maxWidth, int maxHeight) |
||
575 | { |
||
576 | int[] result = new int[2]; |
||
577 | double xRate; |
||
578 | double yRate; |
||
579 | |||
580 | if(width == 0 || height == 0) { |
||
581 | result[0] = 0; |
||
582 | result[1] = 0; |
||
583 | return result; |
||
584 | } |
||
585 | |||
586 | xRate = (double)maxWidth / (double)width; |
||
587 | yRate = (double)maxHeight / (double)height; |
||
588 | if(xRate >= 1.0 || yRate >= 1.0) { |
||
589 | result[0] = width; |
||
590 | result[1] = height; |
||
591 | } |
||
592 | else if(xRate > yRate) { |
||
593 | result[0] = maxHeight * width / height; |
||
594 | result[1] = maxHeight; |
||
595 | } |
||
596 | else { |
||
597 | result[0] = maxWidth; |
||
598 | result[1] = maxWidth * height / width; |
||
599 | } |
||
600 | |||
601 | return result; |
||
602 | } |
||
603 | |||
604 | protected int getXPosition(int left, int maxWidth, int width, int align) |
||
605 | { |
||
606 | if(align == ThumbnailPosition.ALIGN_HOR_LEFT) |
||
607 | return left; |
||
608 | else if(align == ThumbnailPosition.ALIGN_HOR_RIGHT) |
||
609 | return left + (maxWidth - width); |
||
610 | else if(align == ThumbnailPosition.ALIGN_HOR_CENTER) |
||
611 | return left + (maxWidth - width) / 2; |
||
612 | else |
||
613 | throw new RuntimeException("Unknown align type: " + align); |
||
614 | } |
||
615 | |||
616 | protected int getYPosition(int top, int maxHeight, int height, int align) |
||
617 | { |
||
618 | if(align == ThumbnailPosition.ALIGN_VERT_TOP) |
||
619 | return top; |
||
620 | else if(align == ThumbnailPosition.ALIGN_VERT_BOTTOM) |
||
621 | return top + (maxHeight - height); |
||
622 | else if(align == ThumbnailPosition.ALIGN_VERT_CENTER) |
||
623 | return top + (maxHeight - height) / 2; |
||
624 | else |
||
625 | throw new RuntimeException("Unknown align type: " + align); |
||
626 | } |
||
627 | |||
628 | protected int getFirstFiles(File dir, int count, File[] files, int pos) |
||
629 | { |
||
630 | File[] children; |
||
631 | |||
632 | if(imagesFilter == null) |
||
633 | children = dir.listFiles(); |
||
634 | else |
||
635 | children = dir.listFiles(imagesFilter); |
||
636 | |||
637 | if(children == null) return 0; // the dir does not exists |
||
638 | |||
639 | Arrays.sort(children, fileNameComparatorRev); |
||
640 | |||
641 | for(int i = 0; i < children.length; i++) { |
||
642 | if(children[i].isDirectory()) |
||
643 | ; //pos = getFirstFiles(children[i], count, files, pos); |
||
644 | else { |
||
645 | files[pos++] = children[i]; |
||
646 | } |
||
647 | |||
648 | if(pos >= count) break; |
||
649 | } |
||
650 | |||
651 | return pos; |
||
652 | } |
||
653 | |||
654 | protected BufferedImage createBufferedImage(Image image) |
||
655 | { |
||
656 | if(image == null) return null; |
||
657 | |||
658 | int width = image.getWidth(null); |
||
659 | int height = image.getHeight(null); |
||
660 | |||
661 | if(width < 1 || height < 1) return null; |
||
662 | |||
663 | // get pixels |
||
664 | int[] pixels = new int[width * height]; |
||
665 | PixelGrabber pg = new PixelGrabber(image, |
||
666 | 0, 0, width, height, pixels, 0, width); |
||
667 | |||
668 | try { |
||
669 | pg.grabPixels(); |
||
670 | } |
||
671 | catch(InterruptedException e) { |
||
672 | return null; |
||
673 | } |
||
674 | |||
675 | if((pg.getStatus() & ImageObserver.ABORT) != 0) return null; |
||
676 | |||
677 | // create buffered image |
||
678 | BufferedImage buffered = new BufferedImage(width, height, |
||
679 | BufferedImage.TYPE_INT_RGB); |
||
680 | |||
681 | for(int y = 0; y < height; y++) { |
||
682 | for(int x = 0; x < width; x++) |
||
683 | buffered.setRGB(x, y, pixels[y * width + x]); |
||
684 | } |
||
685 | |||
686 | return buffered; |
||
687 | } |
||
688 | |||
689 | public ImageResizer getResizer() |
||
690 | { |
||
691 | return resizer; |
||
692 | } |
||
693 | |||
694 | public void setResizer(ImageResizer resizer) |
||
695 | { |
||
696 | this.resizer = resizer; |
||
697 | } |
||
698 | |||
699 | public String getFormat() |
||
700 | { |
||
701 | return format; |
||
702 | } |
||
703 | |||
704 | public void setFormat(String format) |
||
705 | { |
||
706 | this.format = format; |
||
707 | } |
||
708 | |||
709 | public File getCacheDir() |
||
710 | { |
||
711 | return cacheDir; |
||
712 | } |
||
713 | |||
714 | public void setCacheDir(File dir) |
||
715 | { |
||
716 | this.cacheDir = dir; |
||
717 | } |
||
718 | |||
719 | public File getImagesRoot() |
||
720 | { |
||
721 | return imagesRoot; |
||
722 | } |
||
723 | |||
724 | public void setImagesRoot(File dir) |
||
725 | { |
||
726 | this.imagesRoot = dir; |
||
727 | } |
||
728 | |||
729 | public int getSmallWidth() |
||
730 | { |
||
731 | return smallWidth; |
||
732 | } |
||
733 | |||
734 | public void setSmallWidth(int width) |
||
735 | { |
||
736 | this.smallWidth = width; |
||
737 | } |
||
738 | |||
739 | public int getSmallHeight() |
||
740 | { |
||
741 | return smallHeight; |
||
742 | } |
||
743 | |||
744 | public void setSmallHeight(int height) |
||
745 | { |
||
746 | this.smallHeight = height; |
||
747 | } |
||
748 | |||
749 | public int getMediumWidth() |
||
750 | { |
||
751 | return mediumWidth; |
||
752 | } |
||
753 | |||
754 | public void setMediumWidth(int width) |
||
755 | { |
||
756 | this.mediumWidth = width; |
||
757 | } |
||
758 | |||
759 | public int getMediumHeight() |
||
760 | { |
||
761 | return mediumHeight; |
||
762 | } |
||
763 | |||
764 | public void setMediumHeight(int height) |
||
765 | { |
||
766 | this.mediumHeight = height; |
||
767 | } |
||
768 | |||
769 | public FileFilter getImagesFilter() |
||
770 | { |
||
771 | return imagesFilter; |
||
772 | } |
||
773 | |||
774 | public void setImagesFilter(FileFilter filter) |
||
775 | { |
||
776 | this.imagesFilter = filter; |
||
777 | } |
||
778 | |||
779 | public File getDirTemplate() |
||
780 | { |
||
781 | return dirTemplate; |
||
782 | } |
||
783 | |||
784 | public void setDirTemplate(File dirTemplate) |
||
785 | { |
||
786 | this.dirTemplate = dirTemplate; |
||
787 | } |
||
788 | |||
789 | public ThumbnailPosition[] getDirThumbnailPositions() |
||
790 | { |
||
791 | return dirThumbnailPositions; |
||
792 | } |
||
793 | |||
794 | public void setDirThumbnailPositions( |
||
795 | ThumbnailPosition[] dirThumbnailPositions) |
||
796 | { |
||
797 | this.dirThumbnailPositions = dirThumbnailPositions; |
||
798 | } |
||
799 | } |