4,6 → 4,7 |
import java.util.HashMap; |
import java.util.Comparator; |
import java.util.Arrays; |
import java.io.*; // FIXME |
import java.io.File; |
import java.io.FileFilter; |
import java.io.IOException; |
28,6 → 29,7 |
protected static final String SMALL_SUFFIX = ".small"; |
protected static final String MEDIUM_SUFFIX = ".medium"; |
protected static final String DIR_SUFFIX = ".dir"; |
protected static final String DIR_PART_SUFFIX = ".dir_part"; |
protected static final int DEFAULT_SMALL_WIDTH = 120; |
protected static final int DEFAULT_SMALL_HEIGHT = 120; |
protected static final int DEFAULT_MEDIUM_WIDTH = 800; |
48,6 → 50,7 |
protected FileFilter imagesFilter = null; |
protected Comparator fileNameComparator = new FileNameComparator(true); |
protected Comparator fileNameComparatorRev = new FileNameComparator(false); |
protected boolean nativeMode = true; // FIXME config |
|
protected File dirTemplate; |
protected ThumbnailPosition[] dirThumbnailPositions; |
262,6 → 265,11 |
return true; |
} |
|
protected File getCacheFile(File dir, File imageFile, String suffix) |
{ |
return new File(dir, imageFile.getName() + suffix + "." + format); |
} |
|
protected void cacheThumbnail(Map cache, File imageFile, |
BufferedImage thumbnail, String suffix, int width, int height) |
throws IOException |
270,8 → 278,7 |
+ imageFile.getCanonicalPath()); |
|
File dir = getCacheFileDir(imageFile); |
File cacheFile = new File(dir, |
imageFile.getName() + suffix + "." + format); |
File cacheFile = getCacheFile(dir, imageFile, suffix); |
|
dir.mkdirs(); |
ImageIO.write(thumbnail, format, cacheFile); |
289,79 → 296,93 |
logger.info("started"); |
} |
|
protected void loadCaches(File dir) |
protected void loadFileCache(File file) |
throws IOException |
{ |
if(logger.isDebugEnabled()) |
logger.debug("load caches in " + dir.getCanonicalPath()); |
|
File[] children = dir.listFiles(); |
{ |
/* FIXME use this optimization? |
String dirEnd = DIR_SUFFIX + "." + format; |
String smallEnd = SMALL_SUFFIX + "." + format; |
String mediumEnd = MEDIUM_SUFFIX + "." + format; |
*/ |
|
if(children == null) return; // the dir does not exists |
File origin; |
Map cache; |
|
Arrays.sort(children, fileNameComparator); |
if(file.getName().endsWith(SMALL_SUFFIX + "." + format)) { |
origin = getOriginFile(file, SMALL_SUFFIX); |
cache = smallCache; |
|
for(int i = 0; i < children.length; i++) { |
if(children[i].isDirectory()) |
loadCaches(children[i]); |
else { |
File origin; |
Map cache; |
if(logger.isDebugEnabled()) |
logger.debug("load cached small " + file.getCanonicalPath() |
+ " for " + origin.getCanonicalPath()); |
} |
else if(file.getName().endsWith(MEDIUM_SUFFIX + "." + format)) { |
origin = getOriginFile(file, MEDIUM_SUFFIX); |
cache = mediumCache; |
|
if(children[i].getName().endsWith(smallEnd)) { |
origin = getOriginFile(children[i], SMALL_SUFFIX); |
cache = smallCache; |
if(logger.isDebugEnabled()) |
logger.debug("load cached medium " + file.getCanonicalPath() |
+ " for " + origin.getCanonicalPath()); |
} |
else if(file.getName().endsWith(DIR_SUFFIX + "." + format)) { |
origin = getOriginFile(file, DIR_SUFFIX); |
cache = dirCache; |
|
if(logger.isDebugEnabled()) |
logger.debug("load cached small " + children[i].getCanonicalPath() |
+ " for " + origin.getCanonicalPath()); |
} |
else if(children[i].getName().endsWith(mediumEnd)) { |
origin = getOriginFile(children[i], MEDIUM_SUFFIX); |
cache = mediumCache; |
if(logger.isDebugEnabled()) |
logger.debug("load cached dir " + file.getCanonicalPath() |
+ " for " + origin.getCanonicalPath()); |
} |
else { |
if(logger.isInfoEnabled()) |
logger.warn( |
"unknown type of cached " + file.getCanonicalPath()); |
|
if(logger.isDebugEnabled()) |
logger.debug("load cached medium " + children[i].getCanonicalPath() |
+ " for " + origin.getCanonicalPath()); |
} |
else if(children[i].getName().endsWith(dirEnd)) { |
origin = getOriginFile(children[i], DIR_SUFFIX); |
cache = dirCache; |
return; |
} |
|
if(logger.isDebugEnabled()) |
logger.debug("load cached dir " + children[i].getCanonicalPath() |
+ " for " + origin.getCanonicalPath()); |
} |
else { |
if(logger.isInfoEnabled()) |
logger.warn( |
"unknown type of cached " + children[i].getCanonicalPath()); |
loadCacheInfo(file, origin, cache); |
} |
|
continue; |
} |
protected void loadCacheInfo(File file, File origin, Map cache) |
throws IOException |
{ |
long originTimestamp = origin.lastModified(); |
long cachedTimestamp = file.lastModified(); |
int[] sizes = getOriginSize(file); |
|
long originTimestamp = origin.lastModified(); |
long cachedTimestamp = children[i].lastModified(); |
int[] sizes = getOriginSize(children[i]); |
if(origin.exists() && cachedTimestamp >= originTimestamp) { |
cache.put(origin.getCanonicalPath(), |
new CachedFile(file, origin, cachedTimestamp, |
originTimestamp, sizes[0], sizes[1])); |
|
if(origin.exists() && cachedTimestamp >= originTimestamp) { |
cache.put(origin.getCanonicalPath(), |
new CachedFile(children[i], origin, cachedTimestamp, |
originTimestamp, sizes[0], sizes[1])); |
logger.debug("added"); |
} |
else { |
file.delete(); |
|
logger.debug("added"); |
} |
else { |
children[i].delete(); |
if(logger.isDebugEnabled()) |
logger.debug("deleted: " + origin.exists() |
+ " " + cachedTimestamp + " " + originTimestamp); |
} |
} |
|
if(logger.isDebugEnabled()) |
logger.debug("deleted: " + origin.exists() |
+ " " + cachedTimestamp + " " + originTimestamp); |
} |
} |
protected void loadCaches(File dir) |
throws IOException |
{ |
if(logger.isDebugEnabled()) |
logger.debug("load caches in " + dir.getCanonicalPath()); |
|
File[] children = dir.listFiles(); |
|
if(children == null) return; // the dir does not exists |
|
Arrays.sort(children, fileNameComparator); |
|
for(int i = 0; i < children.length; i++) { |
if(children[i].isDirectory()) |
loadCaches(children[i]); |
else |
loadFileCache(children[i]); |
} |
} |
|
406,16 → 427,27 |
|
if(writeCached(smallCache, imageFile, out)) return; |
|
BufferedImage small = createThumbnail(imageFile, smallWidth, smallHeight); |
if(nativeMode) { |
File dir = getCacheFileDir(imageFile); |
File cacheFile = getCacheFile(dir, imageFile, SMALL_SUFFIX); |
|
if(small != null) { |
int sizes[] = calcSizes( |
small.getWidth(null), small.getHeight(null), smallWidth, smallHeight); |
cacheThumbnail( |
smallCache, imageFile, small, SMALL_SUFFIX, sizes[0], sizes[1]); |
createThumbnailNative(dir, cacheFile, imageFile, smallWidth, smallHeight); |
loadCacheInfo(cacheFile, imageFile, smallCache); |
writeCached(smallCache, imageFile, out); |
} |
else { |
BufferedImage small = createThumbnail(imageFile, smallWidth, smallHeight); |
|
if(out != null) ImageIO.write(small, format, out); |
} |
if(small != null) { |
// a thumbnail returned - save it into the cache dir |
int sizes[] = calcSizes( |
small.getWidth(null), small.getHeight(null), smallWidth, smallHeight); |
cacheThumbnail( |
smallCache, imageFile, small, SMALL_SUFFIX, sizes[0], sizes[1]); |
|
if(out != null) ImageIO.write(small, format, out); |
} |
} |
} |
|
public void writeMedium(File imageFile, OutputStream out) |
426,17 → 458,27 |
|
if(writeCached(mediumCache, imageFile, out)) return; |
|
BufferedImage medium |
= createThumbnail(imageFile, mediumWidth, mediumHeight); |
if(nativeMode) { |
File dir = getCacheFileDir(imageFile); |
File cacheFile = getCacheFile(dir, imageFile, MEDIUM_SUFFIX); |
|
if(medium != null) { |
int sizes[] = calcSizes(medium.getWidth(null), medium.getHeight(null), |
mediumWidth, mediumHeight); |
cacheThumbnail( |
mediumCache, imageFile, medium, MEDIUM_SUFFIX, sizes[0], sizes[1]); |
createThumbnailNative(dir, cacheFile, imageFile, mediumWidth, mediumHeight); |
loadCacheInfo(cacheFile, imageFile, mediumCache); |
writeCached(mediumCache, imageFile, out); |
} |
else { |
BufferedImage medium = createThumbnail(imageFile, mediumWidth, mediumHeight); |
|
if(out != null) ImageIO.write(medium, format, out); |
} |
if(medium != null) { |
// a image returned - save it into the cache dir |
int sizes[] = calcSizes(medium.getWidth(null), medium.getHeight(null), |
mediumWidth, mediumHeight); |
cacheThumbnail( |
mediumCache, imageFile, medium, MEDIUM_SUFFIX, sizes[0], sizes[1]); |
|
if(out != null) ImageIO.write(medium, format, out); |
} |
} |
} |
|
public void writeDir(File dir, OutputStream out) |
489,9 → 531,50 |
} |
} |
|
synchronized protected BufferedImage createThumbnailNative(File dir, File cacheFile, |
File imageFile, int width, int height) |
throws IOException |
{ |
if(logger.isDebugEnabled()) |
logger.debug("create thumbnail2 " + imageFile.getCanonicalPath() + " to " |
+ cacheFile.getCanonicalPath()); |
|
dir.mkdirs(); |
|
// FIMXE: 1) make util path (and params?) configurable |
Process process = Runtime.getRuntime().exec(new String[] { |
"/usr/local/bin/convert", |
"-size", width + "x" + height, |
"-thumbnail", width + "x" + height, |
imageFile.getCanonicalPath(), |
cacheFile.getCanonicalPath() |
}); |
|
// FIXME make it finner |
BufferedReader in = new BufferedReader(new InputStreamReader(process.getErrorStream())); |
String line; |
while((line = in.readLine()) != null) { |
System.out.println("EXEC: " + line); |
} |
|
try { |
int res = process.waitFor(); |
|
if(logger.isDebugEnabled()) |
logger.debug("process exited with result " + res); |
} |
catch(InterruptedException ex) { |
logger.debug("process interrupted"); |
} |
|
return null; |
} |
|
synchronized protected BufferedImage createDirThumbnail(File dir) |
throws IOException |
{ |
long timeStart = System.currentTimeMillis(); |
|
if(logger.isDebugEnabled()) |
logger.debug("create dir thumbnail " + dir.getCanonicalPath()); |
|
515,8 → 598,22 |
count = getFirstFiles(dir, count, firstFiles, 0); |
|
for(int i = 0; i < count; i++) { |
Image image = loadImage(firstFiles[i].getCanonicalPath()); |
Image image; |
BufferedImage thumbnail = null; |
int[] sizes; |
|
if(nativeMode) { |
File cacheFileDir = getCacheFileDir(firstFiles[i]); |
File cacheFile = getCacheFile(cacheFileDir, firstFiles[i], DIR_PART_SUFFIX); |
createThumbnailNative(cacheFileDir, cacheFile, firstFiles[i], |
dirThumbnailPositions[i].getWidth(), dirThumbnailPositions[i].getHeight()); |
image = loadImage(cacheFile.getCanonicalPath()); |
thumbnail = createBufferedImage(image); |
} |
else { |
image = loadImage(firstFiles[i].getCanonicalPath()); |
} |
|
if(image == null) { // not supported format |
logger.warn("unsupported format for origin or operation interrupted"); |
|
523,30 → 620,37 |
return null; |
} |
else { |
BufferedImage thumbnail; |
int[] sizes; |
|
sizes = calcSizes(image.getWidth(null), image.getHeight(null), |
dirThumbnailPositions[i].getWidth(), |
dirThumbnailPositions[i].getHeight()); |
} |
|
if(!nativeMode) { |
thumbnail = resizer.resize(image, sizes[0], sizes[1]); |
graphics.drawImage(thumbnail, |
getXPosition(dirThumbnailPositions[i].getX(), |
dirThumbnailPositions[i].getWidth(), sizes[0], |
dirThumbnailPositions[i].getHorAlign()), |
getYPosition(dirThumbnailPositions[i].getY(), |
dirThumbnailPositions[i].getHeight(), sizes[1], |
dirThumbnailPositions[i].getVertAlign()), |
null); |
} |
|
graphics.drawImage(thumbnail, |
getXPosition(dirThumbnailPositions[i].getX(), |
dirThumbnailPositions[i].getWidth(), sizes[0], |
dirThumbnailPositions[i].getHorAlign()), |
getYPosition(dirThumbnailPositions[i].getY(), |
dirThumbnailPositions[i].getHeight(), sizes[1], |
dirThumbnailPositions[i].getVertAlign()), |
null); |
} |
|
if(logger.isDebugEnabled()) { |
logger.debug("dir thumbnail created in " |
+ (System.currentTimeMillis() - timeStart) + " ms"); |
} |
|
return dirThumbnail; |
} |
|
protected Image loadImage(String fileName) |
{ |
long timeStart = System.currentTimeMillis(); |
|
// FIXME: probably toolbox reads an image not by every request but |
// caches it |
Toolkit toolkit = Toolkit.getDefaultToolkit(); |
568,6 → 672,11 |
} |
} |
|
if(logger.isDebugEnabled()) { |
logger.debug("image " + fileName + " loaded in " |
+ (System.currentTimeMillis() - timeStart) + " ms"); |
} |
|
return image; |
} |
|