Subversion Repositories general

Compare Revisions

Ignore whitespace Rev 961 → Rev 962

/PhotoAlbum/trunk/src/ak/photoalbum/images/ImageResizer.java
0,0 → 1,9
package ak.photoalbum.images;
 
import java.awt.Image;
import java.awt.image.BufferedImage;
 
public interface ImageResizer
{
public BufferedImage resize(Image origin, int newWidth, int newHeight);
}
/PhotoAlbum/trunk/src/ak/photoalbum/images/CachedFile.java
0,0 → 1,99
package ak.photoalbum.images;
 
import java.io.File;
 
class CachedFile
{
private File file;
private File originFile;
private long timestamp;
private long originTimestamp;
private int width;
private int height;
 
public CachedFile()
{
}
 
public CachedFile(File file, File originFile, long timestamp,
long originTimestamp, int width, int height)
{
this.file = file;
this.originFile = originFile;
this.timestamp = timestamp;
this.originTimestamp = originTimestamp;
this.width = width;
this.height = height;
}
 
public File getFile()
{
return file;
}
 
public void setFile(File file)
{
this.file = file;
}
 
public File getOriginFile()
{
return originFile;
}
 
public void setOriginFile(File file)
{
this.originFile = file;
}
 
public long getTimestamp()
{
return timestamp;
}
 
public void setTimestamp(long timestamp)
{
this.timestamp = timestamp;
}
 
public long getOriginTimestamp()
{
return originTimestamp;
}
 
public void setOriginTimestamp(long timestamp)
{
this.originTimestamp = timestamp;
}
 
public int getWidth()
{
return width;
}
 
public void setWidth(int width)
{
this.width = width;
}
 
public int getHeight()
{
return height;
}
 
public void setHeight(int height)
{
this.height = height;
}
 
public String toString()
{
return super.toString() + ":"
+ " file=" + file
+ " originFile=" + originFile
+ " timestamp=" + timestamp
+ " originTimestamp=" + originTimestamp
+ " width=" + width
+ " height=" + height;
}
}
/PhotoAlbum/trunk/src/ak/photoalbum/images/jiu/JiuResizer.java
0,0 → 1,205
package ak.photoalbum.images.jiu;
 
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.awt.image.ImageObserver;
 
import org.apache.log4j.Logger;
 
import ak.photoalbum.images.ImageResizer;
 
import net.sourceforge.jiu.data.BilevelImage;
import net.sourceforge.jiu.data.Gray8Image;
import net.sourceforge.jiu.data.MemoryRGB24Image;
import net.sourceforge.jiu.data.Palette;
import net.sourceforge.jiu.data.Paletted8Image;
import net.sourceforge.jiu.data.PixelImage;
import net.sourceforge.jiu.data.RGB24Image;
import net.sourceforge.jiu.data.RGBIndex;
import net.sourceforge.jiu.geometry.Resample;
 
public class JiuResizer
implements ImageResizer
{
protected static final int DEFAULT_ALPHA = 0xff000000;
protected static final int FILTER_TYPE = Resample.FILTER_TYPE_LANCZOS3;
/*
Possible type small, ms medium, ms quality
-----------------------------------------------------------
FILTER_TYPE_BOX 2.4 3.5 very bad
FILTER_TYPE_TRIANGLE 2.9 5.2
FILTER_TYPE_B_SPLINE 3.6 7.2
FILTER_TYPE_BELL 3.5 6.1
FILTER_TYPE_HERMITE 2.9 5.3
FILTER_TYPE_LANCZOS3 4.7 9.7 the best
FILTER_TYPE_MITCHELL 3.6 7.1
*/
 
protected Logger logger;
 
public JiuResizer()
{
this.logger = Logger.getLogger(this.getClass());
}
 
public BufferedImage resize(Image origin, int newWidth, int newHeight)
{
try {
RGB24Image image = convertImageToRGB24Image(origin);
Resample resample;
 
if(image == null) return null;
if(image.getWidth() == newWidth && image.getHeight() == newHeight)
return convertToAwtImage(image, DEFAULT_ALPHA);
 
resample = new Resample();
resample.setInputImage(image);
resample.setSize(newWidth, newHeight);
resample.setFilter(FILTER_TYPE);
resample.process();
 
return convertToAwtImage(resample.getOutputImage(), DEFAULT_ALPHA);
}
catch(Exception ex) {
ex.printStackTrace();
 
throw new RuntimeException(ex.getMessage());
}
}
 
protected static BufferedImage convertToAwtImage(PixelImage image, int alpha)
{
if (image == null)
{
return null;
}
if (image instanceof RGB24Image)
{
return convertToAwtImage((RGB24Image)image, alpha);
}
else
if (image instanceof Gray8Image)
{
return null; //convertToAwtImage((Gray8Image)image, alpha);
}
else
if (image instanceof Paletted8Image)
{
return null; //convertToAwtImage((Paletted8Image)image, alpha);
}
else
if (image instanceof BilevelImage)
{
return null; //convertToAwtImage((BilevelImage)image, alpha);
}
else
{
return null;
}
}
 
protected static BufferedImage convertToAwtImage(RGB24Image image, int alpha)
{
if (image == null)
{
return null;
}
 
int width = image.getWidth();
int height = image.getHeight();
if (width < 1 || height < 1)
{
return null;
}
 
int[] pixels = new int[width];
byte[] red = new byte[width];
byte[] green = new byte[width];
byte[] blue = new byte[width];
 
BufferedImage newImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
 
for (int y = 0; y < height; y++)
{
image.getByteSamples(RGBIndex.INDEX_RED, 0, y, width, 1, red, 0);
image.getByteSamples(RGBIndex.INDEX_GREEN, 0, y, width, 1, green, 0);
image.getByteSamples(RGBIndex.INDEX_BLUE, 0, y, width, 1, blue, 0);
convertFromRGB24(red, 0, green, 0, blue, 0, alpha, pixels, 0, width);
 
for(int x = 0; x < width; x++)
newImage.setRGB(x, y, pixels[x]);
}
 
return newImage;
}
 
protected static void convertFromRGB24(
byte[] srcRed, int srcRedOffset,
byte[] srcGreen, int srcGreenOffset,
byte[] srcBlue, int srcBlueOffset,
int alpha,
int[] dest, int destOffset,
int num)
{
while (num-- > 0)
{
dest[destOffset++] =
alpha |
(srcBlue[srcBlueOffset++] & 0xff) |
((srcGreen[srcGreenOffset++] & 0xff) << 8) |
((srcRed[srcRedOffset++] & 0xff) << 16);
}
}
 
/**
* Creates an {@link RGB24Image} from the argument AWT image instance.
* @param image AWT image object to be converted to a {@link RGB24Image}
* @return a {@link RGB24Image} object holding the
* image data from the argument image
*/
protected static RGB24Image convertImageToRGB24Image(Image image)
{
if (image == null)
{
return null;
}
int width = image.getWidth(null);
int height = image.getHeight(null);
if (width < 1 || height < 1)
{
return null;
}
int[] pixels = new int[width * height];
PixelGrabber pg = new PixelGrabber(
image, 0, 0, width, height, pixels, 0, width);
 
try
{
pg.grabPixels();
}
catch (InterruptedException e)
{
return null;
}
if ((pg.getStatus() & ImageObserver.ABORT) != 0)
{
//System.err.println("image fetch aborted or errored");
return null;
}
RGB24Image result = new MemoryRGB24Image(width, height);
int offset = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int pixel = pixels[offset++] & 0xffffff;
result.putSample(RGBIndex.INDEX_RED, x, y, pixel >> 16);
result.putSample(RGBIndex.INDEX_GREEN, x, y, (pixel >> 8) & 0xff);
result.putSample(RGBIndex.INDEX_BLUE, x, y, pixel & 0xff);
}
}
return result;
}
}
/PhotoAlbum/trunk/src/ak/photoalbum/images/ThumbnailPosition.java
0,0 → 1,89
package ak.photoalbum.images;
 
public class ThumbnailPosition
{
public static final int ALIGN_HOR_LEFT = 1;
public static final int ALIGN_HOR_RIGHT = 2;
public static final int ALIGN_HOR_CENTER = 3;
public static final int ALIGN_VERT_TOP = 1;
public static final int ALIGN_VERT_BOTTOM = 2;
public static final int ALIGN_VERT_CENTER = 3;
 
private int x;
private int y;
private int width;
private int height;
private int horAlign;
private int vertAlign;
 
public ThumbnailPosition(int x, int y, int width, int height,
int horAlign, int vertAlign)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.horAlign = horAlign;
this.vertAlign = vertAlign;
}
 
public int getX()
{
return x;
}
 
public void setX(int x)
{
this.x = x;
}
 
public int getY()
{
return y;
}
 
public void setY(int y)
{
this.y = y;
}
 
public int getWidth()
{
return width;
}
 
public void setWidth(int width)
{
this.width = width;
}
 
public int getHeight()
{
return height;
}
 
public void setHeight(int height)
{
this.height = height;
}
 
public int getHorAlign()
{
return horAlign;
}
 
public void setHorAlign(int horAlign)
{
this.horAlign = horAlign;
}
 
public int getVertAlign()
{
return vertAlign;
}
 
public void setVertAlign(int vertAlign)
{
this.vertAlign = vertAlign;
}
}
/PhotoAlbum/trunk/src/ak/photoalbum/images/Thumbnailer.java
0,0 → 1,799
package ak.photoalbum.images;
 
import java.util.Map;
import java.util.HashMap;
import java.util.Comparator;
import java.util.Arrays;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.PixelGrabber;
import javax.imageio.ImageIO;
import org.apache.log4j.Logger;
import marcoschmidt.image.ImageInfo;
import ak.photoalbum.util.FileUtils;
import ak.photoalbum.util.FileNameComparator;
 
public class Thumbnailer
{
protected static final String DEFAULT_FORMAT = "jpg";
protected static final String SMALL_SUFFIX = ".small";
protected static final String MEDIUM_SUFFIX = ".medium";
protected static final String DIR_SUFFIX = ".dir";
protected static final int DEFAULT_SMALL_WIDTH = 120;
protected static final int DEFAULT_SMALL_HEIGHT = 120;
protected static final int DEFAULT_MEDIUM_WIDTH = 800;
protected static final int DEFAULT_MEDIUM_HEIGHT = 800;
 
protected Logger logger;
protected ImageResizer resizer;
protected int smallWidth = DEFAULT_SMALL_WIDTH;
protected int smallHeight = DEFAULT_SMALL_HEIGHT;
protected int mediumWidth = DEFAULT_MEDIUM_WIDTH;
protected int mediumHeight = DEFAULT_MEDIUM_HEIGHT;
protected File cacheDir;
protected String format = DEFAULT_FORMAT;
protected Map smallCache = new HashMap();
protected Map mediumCache = new HashMap();
protected Map dirCache = new HashMap();
protected File imagesRoot;
protected FileFilter imagesFilter = null;
protected Comparator fileNameComparator = new FileNameComparator(true);
protected Comparator fileNameComparatorRev = new FileNameComparator(false);
 
protected File dirTemplate;
protected ThumbnailPosition[] dirThumbnailPositions;
protected int[] dirTemplateSize;
protected long dirTemplateTimestamp;
 
public Thumbnailer()
{
this.logger = Logger.getLogger(this.getClass());
}
 
public String getMime()
{
return FileUtils.getMime(format);
}
 
public int[] getDirSize(File origin)
throws IOException
{
if(dirTemplateSize == null
|| dirTemplateTimestamp != dirTemplate.lastModified())
{
dirTemplateSize = getOriginSize(dirTemplate);
dirTemplateTimestamp = dirTemplate.lastModified();
}
 
return dirTemplateSize;
}
 
public int[] getSmallSize(File origin)
throws IOException
{
CachedFile cached = getCached(smallCache, origin);
 
if(cached == null) {
int[] originSize = getOriginSize(origin);
 
return calcSizes(originSize[0], originSize[1], smallWidth, smallHeight);
}
else {
int[] originSize = new int[2];
 
originSize[0] = cached.getWidth();
originSize[1] = cached.getHeight();
 
return originSize;
}
}
 
public int[] getMediumSize(File origin)
throws IOException
{
CachedFile cached = getCached(mediumCache, origin);
 
if(cached == null) {
int[] originSize = getOriginSize(origin);
 
return calcSizes(originSize[0], originSize[1], mediumWidth, mediumHeight);
}
else {
int[] originSize = new int[2];
 
originSize[0] = cached.getWidth();
originSize[1] = cached.getHeight();
 
return originSize;
}
}
 
protected int[] getOriginSize(File origin)
throws IOException
{
if(logger.isDebugEnabled())
logger.debug("get size of " + origin.getCanonicalPath());
 
ImageInfo ii = new ImageInfo();
FileInputStream in = null;
int[] res = new int[2];
 
try {
in = new FileInputStream(origin);
ii.setInput(in);
 
if(!ii.check()) {
logger.warn("not supported format of " + origin.getCanonicalPath());
res[0] = 0;
res[1] = 0;
}
else{
res[0] = ii.getWidth();
res[1] = ii.getHeight();
}
}
finally {
if(in != null) in.close();
}
 
return res;
}
 
public void rebuildCache()
throws IOException
{
logger.info("rebuild cache");
 
deleteCache();
buildCache();
}
 
public void deleteCache()
throws IOException
{
logger.info("delete cache");
 
deleteCache(cacheDir);
}
 
public void buildCache()
throws IOException
{
logger.info("build cache");
 
buildCache(imagesRoot);
}
 
protected void deleteCache(File dir)
throws IOException
{
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())
deleteCache(children[i]);
else
children[i].delete();
}
dir.delete();
}
 
protected void buildCache(File dir)
throws IOException
{
File[] children;
 
if(imagesFilter == null)
children = dir.listFiles();
else
children = dir.listFiles(imagesFilter);
 
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()) {
writeDir(children[i], null);
buildCache(children[i]);
}
else {
writeSmall(children[i], null);
writeMedium(children[i], null);
}
}
}
 
protected CachedFile getCached(Map cache, File imageFile)
throws IOException
{
CachedFile cached = (CachedFile)cache.get(imageFile.getCanonicalPath());
 
if(cached == null || !cached.getFile().exists()) {
logger.debug("not found in cache");
return null;
}
 
if(cached.getOriginTimestamp() != imageFile.lastModified()) {
cached.getFile().delete();
cache.remove(imageFile.getCanonicalPath());
logger.debug("timestamps dont match");
return null;
}
 
return cached;
}
 
protected boolean writeCached(Map cache, File imageFile, OutputStream out)
throws IOException
{
CachedFile cached = getCached(cache, imageFile);
 
if(cached == null) return false;
 
if(logger.isDebugEnabled())
logger.debug("write cached " + imageFile.getCanonicalPath());
 
if(out != null) {
FileInputStream in = null;
 
try {
in = new FileInputStream(cached.getFile());
FileUtils.copyStreams(in, out);
}
finally {
if(in != null) in.close();
}
}
 
return true;
}
 
protected void cacheThumbnail(Map cache, File imageFile,
BufferedImage thumbnail, String suffix, int width, int height)
throws IOException
{
logger.debug("cache thumbnail " + suffix + " "
+ imageFile.getCanonicalPath());
 
File dir = getCacheFileDir(imageFile);
File cacheFile = new File(dir,
imageFile.getName() + suffix + "." + format);
 
dir.mkdirs();
ImageIO.write(thumbnail, format, cacheFile);
 
cache.put(imageFile.getCanonicalPath(),
new CachedFile(cacheFile, imageFile,
cacheFile.lastModified(), imageFile.lastModified(), width, height));
}
 
public void startup()
throws IOException
{
logger.info("startup");
loadCaches(cacheDir);
logger.info("started");
}
 
protected void loadCaches(File dir)
throws IOException
{
if(logger.isDebugEnabled())
logger.debug("load caches in " + dir.getCanonicalPath());
 
File[] children = dir.listFiles();
String dirEnd = DIR_SUFFIX + "." + format;
String smallEnd = SMALL_SUFFIX + "." + format;
String mediumEnd = MEDIUM_SUFFIX + "." + format;
 
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 {
File origin;
Map cache;
 
if(children[i].getName().endsWith(smallEnd)) {
origin = getOriginFile(children[i], SMALL_SUFFIX);
cache = smallCache;
 
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 medium " + children[i].getCanonicalPath()
+ " for " + origin.getCanonicalPath());
}
else if(children[i].getName().endsWith(dirEnd)) {
origin = getOriginFile(children[i], DIR_SUFFIX);
cache = dirCache;
 
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());
 
continue;
}
 
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(children[i], origin, cachedTimestamp,
originTimestamp, sizes[0], sizes[1]));
 
logger.debug("added");
}
else {
children[i].delete();
 
if(logger.isDebugEnabled())
logger.debug("deleted: " + origin.exists()
+ " " + cachedTimestamp + " " + originTimestamp);
}
}
}
}
 
protected File getOriginFile(File cached, String suffix)
throws IOException
{
String fileEnd = suffix + "." + format;
String fileName = cached.getName();
String cachedPath = cached.getParentFile().getCanonicalPath();
String cacheRoot = cacheDir.getCanonicalPath();
 
fileName = fileName.substring(0, fileName.length() - fileEnd.length());
 
if(!cacheRoot.equals(cachedPath))
if(!cacheRoot.endsWith(File.separator)) cacheRoot += File.separator;
 
return new File(imagesRoot, cachedPath.substring(cacheRoot.length())
+ File.separator + fileName);
}
 
protected File getCacheFileDir(File imageFile)
throws IOException
{
String imagePath = imageFile.getParentFile().getCanonicalPath();
String rootPath = imagesRoot.getCanonicalPath();
 
if(imagePath.equals(rootPath)) return cacheDir;
if(!rootPath.endsWith(File.separator)) rootPath += File.separator;
 
if(!imagePath.startsWith(rootPath))
throw new RuntimeException("Image " + imageFile.getCanonicalPath()
+ " is not under images root " + imagesRoot.getCanonicalPath());
 
return new File(cacheDir, imagePath.substring(rootPath.length()));
}
 
public void writeSmall(File imageFile, OutputStream out)
throws IOException
{
if(logger.isInfoEnabled())
logger.info("write small " + imageFile.getCanonicalPath());
 
if(writeCached(smallCache, imageFile, out)) return;
 
BufferedImage small = createThumbnail(imageFile, smallWidth, smallHeight);
 
if(small != null) {
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)
throws IOException
{
if(logger.isInfoEnabled())
logger.info("write medium " + imageFile.getCanonicalPath());
 
if(writeCached(mediumCache, imageFile, out)) return;
 
BufferedImage medium
= createThumbnail(imageFile, mediumWidth, mediumHeight);
 
if(medium != null) {
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)
throws IOException
{
if(logger.isInfoEnabled())
logger.info("write dir " + dir.getCanonicalPath());
 
if(writeCached(dirCache, dir, out)) return;
 
BufferedImage thumbnail = createDirThumbnail(dir);
 
if(thumbnail != null) {
if(dirTemplateSize == null
|| dirTemplateTimestamp != dirTemplate.lastModified())
{
dirTemplateSize = getOriginSize(dirTemplate);
dirTemplateTimestamp = dirTemplate.lastModified();
}
 
cacheThumbnail(dirCache, dir, thumbnail, DIR_SUFFIX,
dirTemplateSize[0], dirTemplateSize[1]);
 
if(out != null) ImageIO.write(thumbnail, format, out);
}
}
 
synchronized protected BufferedImage createThumbnail(File imageFile,
int width, int height)
throws IOException
{
if(logger.isDebugEnabled())
logger.debug("create thumbnail " + imageFile.getCanonicalPath());
 
Image image = loadImage(imageFile.getCanonicalPath());
// = ImageIO.read(imageFile);
int[] sizes;
 
if(image == null) { // not supported format
logger.warn("unsupported format for origin or operation interrupted");
 
return null;
}
else {
sizes = calcSizes(image.getWidth(null), image.getHeight(null),
width, height);
logger.debug("resize to " + sizes[0] + "x" + sizes[1]);
 
return resizer.resize(image, sizes[0], sizes[1]);
}
}
 
synchronized protected BufferedImage createDirThumbnail(File dir)
throws IOException
{
if(logger.isDebugEnabled())
logger.debug("create dir thumbnail " + dir.getCanonicalPath());
 
Image template = loadImage(dirTemplate.getCanonicalPath());
BufferedImage dirThumbnail;
Graphics graphics;
int count;
File[] firstFiles;
 
if(template == null) { // not supported format
logger.warn("unsupported format for template or operation interrupted");
 
return null;
}
 
dirThumbnail = createBufferedImage(template);
 
graphics = dirThumbnail.getGraphics();
count = dirThumbnailPositions.length;
firstFiles = new File[count];
count = getFirstFiles(dir, count, firstFiles, 0);
 
for(int i = 0; i < count; i++) {
Image image = loadImage(firstFiles[i].getCanonicalPath());
 
if(image == null) { // not supported format
logger.warn("unsupported format for origin or operation interrupted");
 
return null;
}
else {
BufferedImage thumbnail;
int[] sizes;
 
sizes = calcSizes(image.getWidth(null), image.getHeight(null),
dirThumbnailPositions[i].getWidth(),
dirThumbnailPositions[i].getHeight());
 
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);
}
}
 
return dirThumbnail;
}
 
protected Image loadImage(String fileName)
{
// FIXME: probably toolbox reads an image not by every request but
// caches it
Toolkit toolkit = Toolkit.getDefaultToolkit();
Image image = toolkit.getImage(fileName);
 
toolkit.prepareImage(image, -1, -1, null);
 
while(true) {
int status = toolkit.checkImage(image, -1, -1, null);
 
if((status & ImageObserver.ALLBITS) != 0) break;
if((status & ImageObserver.ERROR) != 0) return null;
 
try {
Thread.sleep(100);
}
catch(Exception ex) {
return null;
}
}
 
return image;
}
 
protected int[] calcSizes(int width, int height, int maxWidth, int maxHeight)
{
int[] result = new int[2];
double xRate;
double yRate;
 
if(width == 0 || height == 0) {
result[0] = 0;
result[1] = 0;
return result;
}
 
xRate = (double)maxWidth / (double)width;
yRate = (double)maxHeight / (double)height;
if(xRate >= 1.0 || yRate >= 1.0) {
result[0] = width;
result[1] = height;
}
else if(xRate > yRate) {
result[0] = maxHeight * width / height;
result[1] = maxHeight;
}
else {
result[0] = maxWidth;
result[1] = maxWidth * height / width;
}
 
return result;
}
 
protected int getXPosition(int left, int maxWidth, int width, int align)
{
if(align == ThumbnailPosition.ALIGN_HOR_LEFT)
return left;
else if(align == ThumbnailPosition.ALIGN_HOR_RIGHT)
return left + (maxWidth - width);
else if(align == ThumbnailPosition.ALIGN_HOR_CENTER)
return left + (maxWidth - width) / 2;
else
throw new RuntimeException("Unknown align type: " + align);
}
 
protected int getYPosition(int top, int maxHeight, int height, int align)
{
if(align == ThumbnailPosition.ALIGN_VERT_TOP)
return top;
else if(align == ThumbnailPosition.ALIGN_VERT_BOTTOM)
return top + (maxHeight - height);
else if(align == ThumbnailPosition.ALIGN_VERT_CENTER)
return top + (maxHeight - height) / 2;
else
throw new RuntimeException("Unknown align type: " + align);
}
 
protected int getFirstFiles(File dir, int count, File[] files, int pos)
{
File[] children;
 
if(imagesFilter == null)
children = dir.listFiles();
else
children = dir.listFiles(imagesFilter);
 
if(children == null) return 0; // the dir does not exists
 
Arrays.sort(children, fileNameComparatorRev);
 
for(int i = 0; i < children.length; i++) {
if(children[i].isDirectory())
; //pos = getFirstFiles(children[i], count, files, pos);
else {
files[pos++] = children[i];
}
 
if(pos >= count) break;
}
 
return pos;
}
 
protected BufferedImage createBufferedImage(Image image)
{
if(image == null) return null;
 
int width = image.getWidth(null);
int height = image.getHeight(null);
 
if(width < 1 || height < 1) return null;
 
// get pixels
int[] pixels = new int[width * height];
PixelGrabber pg = new PixelGrabber(image,
0, 0, width, height, pixels, 0, width);
 
try {
pg.grabPixels();
}
catch(InterruptedException e) {
return null;
}
 
if((pg.getStatus() & ImageObserver.ABORT) != 0) return null;
 
// create buffered image
BufferedImage buffered = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
 
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++)
buffered.setRGB(x, y, pixels[y * width + x]);
}
 
return buffered;
}
 
public ImageResizer getResizer()
{
return resizer;
}
 
public void setResizer(ImageResizer resizer)
{
this.resizer = resizer;
}
 
public String getFormat()
{
return format;
}
 
public void setFormat(String format)
{
this.format = format;
}
 
public File getCacheDir()
{
return cacheDir;
}
 
public void setCacheDir(File dir)
{
this.cacheDir = dir;
}
 
public File getImagesRoot()
{
return imagesRoot;
}
 
public void setImagesRoot(File dir)
{
this.imagesRoot = dir;
}
 
public int getSmallWidth()
{
return smallWidth;
}
 
public void setSmallWidth(int width)
{
this.smallWidth = width;
}
 
public int getSmallHeight()
{
return smallHeight;
}
 
public void setSmallHeight(int height)
{
this.smallHeight = height;
}
 
public int getMediumWidth()
{
return mediumWidth;
}
 
public void setMediumWidth(int width)
{
this.mediumWidth = width;
}
 
public int getMediumHeight()
{
return mediumHeight;
}
 
public void setMediumHeight(int height)
{
this.mediumHeight = height;
}
 
public FileFilter getImagesFilter()
{
return imagesFilter;
}
 
public void setImagesFilter(FileFilter filter)
{
this.imagesFilter = filter;
}
 
public File getDirTemplate()
{
return dirTemplate;
}
 
public void setDirTemplate(File dirTemplate)
{
this.dirTemplate = dirTemplate;
}
 
public ThumbnailPosition[] getDirThumbnailPositions()
{
return dirThumbnailPositions;
}
 
public void setDirThumbnailPositions(
ThumbnailPosition[] dirThumbnailPositions)
{
this.dirThumbnailPositions = dirThumbnailPositions;
}
}