[java] Pixel-modifying images?

Started by
8 comments, last by TheBluMage 19 years, 8 months ago
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.
Development blog, The Omega Sector -- http://www.omegasector.org
Advertisement
just a question... why do you need to modify so many pixels of an image so quickly?
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?
Development blog, The Omega Sector -- http://www.omegasector.org
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 arrayDataBufferInt 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.
Thanks, I'll give that a try ;)
Development blog, The Omega Sector -- http://www.omegasector.org
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.
It is working much better now. Thanks to both of you.
Development blog, The Omega Sector -- http://www.omegasector.org
Could you post your resulting code to share your experience?
Or could you, TheBluMage post your eight times faster raster code?
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
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]

This topic is closed to new replies.

Advertisement