package org.albite.book.view;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import javax.microedition.lcdui.Image;
import org.albite.albite.AlbiteMIDlet;
import org.albite.image.AlbiteImage;
import org.albite.util.archive.ArchiveEntry;
class ImageRegion {
public static final int MARGIN = 10;
public static WeakReference BROKEN_IMAGE;
private ArchiveEntry entry;
private WeakReference imageReference;
public final int altTextBufferPosition;
public final int altTextBufferLength;
public ImageRegion(
ArchiveEntry entry,
final int altTextBufferPosition,
final int altTextBufferLength) {
this.entry = entry;
this.altTextBufferPosition = altTextBufferPosition;
this.altTextBufferLength = altTextBufferLength;
}
public final Image getImage(
final int canvasWidth,
final int canvasHeight,
final int fontHeight) {
boolean rescale = false;
int width;
int height;
Image image = null;
if (entry == null) {
image = getBrokenImage();
} else {
/*
* file found
*/
final WeakReference ref = imageReference;
if (ref != null) {
image = (Image) ref.get();
}
if (image == null) {
try {
InputStream in = entry.openInputStream();
try {
image = Image.createImage(in);
int maxWidth = (canvasWidth - 4 * MARGIN - 1);
int maxHeight = (canvasHeight - 4 * MARGIN - 1);
if (altTextBufferLength > 0) {
maxHeight -= fontHeight;
}
width = image.getWidth();
height = image.getHeight();
float ratio = 1;
/*
* check width
*/
if (width > maxWidth) {
ratio = (float) maxWidth / (float) width;
width = maxWidth;
height *= ratio;
rescale = true;
}
/*
* check height
*/
if (height > maxHeight) {
ratio = (float) maxHeight / (float) height;
height = maxHeight;
width *= ratio;
rescale = true;
}
/*
* got to check width again for h may have modified it
*/
if (width > maxWidth) {
ratio = (float) maxWidth / (float) width;
width = maxWidth;
height *= ratio;
rescale = true;
}
/*
* Try to resize, if image is too big
*/
if (rescale) {
try {
Image rescaled =
AlbiteImage.rescale(image, width, height);
image = rescaled;
} catch (OutOfMemoryError e) {
/*
* The rescaled version will be used,
* ONLY if the rescaling succeeded,
* i.e. there was enough memory for it.
*/
//#debug
AlbiteMIDlet.LOGGER.log(e);
}
}
} finally {
in.close();
}
} catch (OutOfMemoryError e) {
image = getBrokenImage();
} catch (Exception e) {
image = getBrokenImage();
}
/*
* Cache the image
*/
imageReference = new WeakReference(image);
}
}
return image;
}
private static Image getBrokenImage() {
Image image = null;
if (BROKEN_IMAGE != null) {
image = (Image) BROKEN_IMAGE.get();
}
if (image == null) {
try {
image = Image.createImage("/res/broken_image.png");
} catch (IOException e) {
//broken image placeholder was not found, but one should still
//display a placeholder
image = Image.createImage(2, 2);
}
/*
* Cache the image
*/
BROKEN_IMAGE = new WeakReference(image);
}
return image;
}
}