Image thumbnail in an optimized way for J2Me platform

 Trying to show thumbnail view after taking a big snapshot ? Trying to show a list view of images ? Or in any other case you try to resize or scale an image ?

I was searching for an optimized code for thumbnail creation. The main issues here are

- You need to be careful about the memory you use. After taking a big image in memory you may have a little left for allocation.
- You do not have floating point in most of the mobiles. So your image may not keep the image ratio right after scaling.
- Your need very time efficient code , you can keep the image quality apart ..

I did some google. And found the following discussions useful.

http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=41&t=002988
http://developer.sonyericsson.com/thread/27493

I tested some of those examples. Some of them cause OutOfMemory Exception. Some take a long time to resize image. But I thought I could do better. Finally I wrote the following code.


/**
* Gets the thumbnail that fit with given screen width, height and padding ..
*
* @param image The source image
* @param padding padding to the screen
* @return scaled image
*/
private final Image getThumbnailWrapper(Image image, int expectedWidth, int expectedHeight, int padding) {
final int sourceWidth = image.getWidth();
final int sourceHeight = image.getHeight();
int thumbWidth = -1;
int thumbHeight = -1;

// big width
if(sourceWidth >= sourceHeight) {
thumbWidth = expectedWidth - padding;
thumbHeight = thumbWidth * sourceHeight / sourceWidth;
// fits to height ?
if(thumbHeight > (expectedHeight - padding)) {
thumbHeight = expectedHeight - padding;
thumbWidth = thumbHeight * sourceWidth / sourceHeight;
}
} else {
// big height
thumbHeight = expectedHeight - padding;
thumbWidth = thumbHeight * sourceWidth / sourceHeight;
// fits to width ?
if(thumbWidth > (expectedWidth - padding)) {
thumbWidth = expectedWidth - padding;
thumbHeight = thumbWidth * sourceHeight / sourceWidth;
}
}

// XXX As we do not have floating point, sometimes the thumbnail resolution gets bigger ...
// we are trying hard to avoid that ..
thumbHeight = (sourceHeight < thumbHeight) ? sourceHeight : thumbHeight;
thumbWidth = (sourceWidth < thumbWidth) ? sourceWidth : thumbWidth;

return getThumbnail(image, thumbWidth, thumbHeight);
}

/**
* Gets thumbnail with a height and width specified ..
* @param image
* @param thumbWidth
* @param thumbHeight
* @return scaled image
*/
private final Image getThumbnail(Image image, int thumbWidth, int thumbHeight) {
int x, y, pos, tmp, z = 0;
final int sourceWidth = image.getWidth();
final int sourceHeight = image.getHeight();

// integer ratio ..
final int ratio = sourceWidth / thumbWidth;

// buffer where we read in data from image source
final int[] in = new int[sourceWidth];

// buffer of output thumbnail image
final int[] out = new int[thumbWidth*thumbHeight];

final int[] cols = new int[thumbWidth];

// pre-calculate columns we need to access from source image
for (x = 0,pos = 0; x < thumbWidth; x++) {
cols[x] = pos;

// increase the value without fraction calculation
pos += ratio;
tmp = pos + (thumbWidth - x) * ratio;
if(tmp > sourceWidth) {
pos--;
} else if(tmp < sourceWidth - ratio) {
pos++;
}
}

// read through the rows ..
for (y = 0, pos = 0, z = 0; y < thumbHeight; y++) {

// read a single row ..
image.getRGB(in, 0, sourceWidth, 0, pos, sourceWidth, 1);

for (x = 0; x < thumbWidth; x++, z++) {
// write this row to thumbnail
out[z] = in[cols[x]];
}

pos += ratio;
tmp = pos + (thumbHeight - y) * ratio;
if(tmp > sourceHeight) {
pos--;
} else if(tmp < sourceHeight - ratio) {
pos++;
}
}
return Image.createRGBImage(out, thumbWidth, thumbHeight, false);
}



This code has low memory need as it only reads one row from the source image each time. And it is super fast (I mean unbelievable).

 

come from: http://miniim.blogspot.com/2008/05/image-thumbnail-in-optimized-way-for.html

你可能感兴趣的:(image,Integer,buffer,Access,j2me,output)