Sign in to follow this  
Addictman

[java] Pixel-modifying images?

Recommended Posts

Hi. i am just wondering if there is a defacto standard for modifying the colorvalues of clusters and/or individual pixels of an image? Right now, I just use BufferedImage's setRGB method. When I reach about 5000 modifications (individual pixels) pr. loop-run, things tend to get choppy at intervals. I also looked at writableraster's. Anyone got any bright ideas and solutions for me, how I can safely modify huge amounts of pixels quickly? I'll stress that I'm looking for performance here, not necessarely clean and readable code, so anything that's fast goes. Thanks.

Share this post


Link to post
Share on other sites
It's for some effects that look really nice ;) I guess it doesnt really matter exactly what the specifics of my needs are. So, any tips?

Share this post


Link to post
Share on other sites
Don't use setRGB. Instead, you can get access to the image's pixels directly:

// create image (make sure the format you set matches the type of pixel data you want)
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

// get data array
DataBufferInt db = (DataBufferInt) img.getRaster().getDataBuffer();
int[] pixels = db.getData();

// set pixel at x, y to color c (which should be a RGB value)
pixels[y*width + x] = c;


I'm not sure I have the exact method calls written there, but it should be close.

To draw the image, you don't need to do anything extra; just use drawImage.

Also, if you also want alpha in your image, use BufferedImage.TYPE_INT_ARGB.

Share this post


Link to post
Share on other sites
Modifying the raster is what I do for those intensive operations. It is a HUGE speed-up over getting and setting pixels with the BufferedImage methods. When I started doing that, my graphics operations got about eight times faster with no further optimization.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Could you post your resulting code to share your experience?
Or could you, TheBluMage post your eight times faster raster code?

Share this post


Link to post
Share on other sites
Man, I wish I had those kinds of options in J2ME :( With MIDP 2.0 you can at least extract a data array from an Image, and create an Image from a data array, but the created version is a *new, immutable* one, which implies it has to copy your array and then GC the old thing, and... ugh. You'd think they'd give you *better* low-level access when working with a more resource-constrained system yeah? :s

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Could you post your resulting code to share your experience?
Or could you, TheBluMage post your eight times faster raster code?

Sure. It's a method designed to skew a BufferedImage inward at the top and store the resulting image in another (or the same) BufferedImage. I didn't have the old method with the get and set pixel methods, but I reconstructed it as well as I could.

Using Get and Set Pixel methods:

public static void skewInTop(BufferedImage image, BufferedImage dest, float topSkinny) {

int width = image.getWidth();
float lineIncrem = (1F - topSkinny) / image.getHeight();
int pixIncrem;
int middle = width >> 1;
int curFromOffset;
int curToOffset;
int halfShouldBe;
int middleDivHalf;
int middleModHalf;
int height = image.getHeight();

for(int i = 0; i != height; ++i) {

halfShouldBe = (int) (topSkinny * middle);
topSkinny += lineIncrem;

middleDivHalf = middle / halfShouldBe;
middleModHalf = middle % halfShouldBe;

for(curFromOffset = 0, curToOffset = 0, pixIncrem = 0; ; ++curToOffset) {

curFromOffset += middleDivHalf;
pixIncrem += middleModHalf;

if(pixIncrem > halfShouldBe) {

++curFromOffset;
pixIncrem -= halfShouldBe;

}

if(!(curFromOffset < middle)) break;
dest.setRGB(middle - curToOffset, i, image.getRGB(middle - curFromOffset, i));
dest.setRGB(middle + curToOffset, i, image.getRGB(middle + curFromOffset, i));

}

}

}




Using Raster (assumes 32-bit integer sized pixels):

public static void skewInTop(BufferedImage image, BufferedImage dest, float topSkinny) {

int[] destRaster = ((DataBufferInt) dest.getRaster().getDataBuffer()).getData();
int[] raster = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
int width = image.getWidth();
float lineIncrem = (1F - topSkinny) / image.getHeight();
int pixIncrem;
int middle = width >> 1;
int curFromOffset;
int curToOffset;
int halfShouldBe;
int value;
int middleDivHalf;
int middleModHalf;

for(int i = 0; i != raster.length; i += width) {

halfShouldBe = (int) (topSkinny * middle);
topSkinny += lineIncrem;

middleDivHalf = middle / halfShouldBe;
middleModHalf = middle % halfShouldBe;

for(curFromOffset = 0, curToOffset = 0, pixIncrem = 0; curToOffset != halfShouldBe; ++curToOffset) {

curFromOffset += middleDivHalf;
pixIncrem += middleModHalf;

if(pixIncrem > halfShouldBe) {

++curFromOffset;
pixIncrem -= halfShouldBe;

}

value = i + middle;
destRaster[value - curToOffset] = raster[value - curFromOffset];
destRaster[value + curToOffset] = raster[value + curFromOffset];

}

}

}




EDIT: Note that since I deleted the old slower method, I optimized the new one more, so now the raster one is well over eight times faster than the other I reconstructed, despite the fact that these speed optimizations were applied to it as well.

[Edited by - TheBluMage on August 19, 2004 2:45:44 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this