Hi, I have a pixel array grabbed with PixelGrabber. I done some computation with it and now I need make a BufferedImage from it. The problem is I can't make it very fast, just slow. I made an Image type object from it then I converted it to a BufferedImages but it's so slow...... To get you mode ideas of solving this, I tell you that I need to send the image over network as PNG compressed... so that's why I need a BufferedImage. I need very fast conversion/image construction...

Thanks.

Recommended Answers

All 14 Replies

I used the following standard solution:

ims = new MemoryImageSource(width,height, pixels, 0, width);

(where the width/height vars define the image size and pixels is a simple int array of PixelGrabber-type data

then:

Image im = Toolkit.getDefaultToolkit().createImage(ims);

It seemed to me that this was fast enough to be be negligeable compared to moving the pixel aray over the network etc.

Yes but I need a BufferedImage to do that, not Image. I can't send Image object over a dataoutputstream... or I don't know how :|

This is the code I use. Working but very slow. It is there also a version using DataBufferInt but it's also slow.

finalimg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
               
                Image piximg =  Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(w, h, pixels2,0,w));
                finalimg.getGraphics().drawImage(piximg, 0, 0, null);

createImage is defined as returning Image (abstract) but actually returns a BufferedImage, so you can just cast it.
However, rather than extracting pixels, prcessing them and converting back to Image, why not work directly with the Imaage's databuffer array and save both conversions:

image = robot.createScreenCapture(new Rectangle(width, height));
Raster ras = ((BufferedImage) image).getData();
DataBufferInt db = (DataBufferInt) ras.getDataBuffer();
int[] data = db.getData();

now whatever you change in data will change the image directly.

Is this at least as fast as pixel grabber? I'll code it now...

I found it about twice as fast, plus there's zero overhead converting back to image. Good Luck!

//same with pixel and pixel2 - similay speed with pixel grabber
            Raster ras = ((BufferedImage) img).getData();
            DataBufferInt db = (DataBufferInt) ras.getDataBuffer();
            pixels2 = db.getData();

for (int x = 0; x < w; x++) {
	for (int y = 0; y < h; y++) {
		if (pixels2[x + y * w] != pixels[x + y * w])
                {
                    pixels[x + y * w] = pixels2[x + y * w];
   
                }
                else pixels2[x + y * w] = 0;//if the same make it 0


//this take as long time as a full image - and it's still abou 120K... so maybe what I chaneg in data does not change the image directly?
 sendImageToStream(img, os_img);

[...]

public void sendImageToStream(BufferedImage img, DataOutputStream dos) throws IOException{
//i send the image as byte array and not directly write the image to stream because I need the length of the image
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
     ImageIO.write(img, "png", baos);


            
            byte[] byteArray = baos.toByteArray();
            baos.close();
            int len = byteArray.length;





            try {
                 dos.writeInt(1);
                 dos.writeInt(len);//length
                 dos.write(byteArray, 0, len);

                 dos.flush();
               
            } catch(Exception e){
                 e.printStackTrace();
            }

 }

So the pixels do not modify... need to reconstruct the image? (what I needed... pixels to BufferedImage).
Thanks.

Is line 11 the right way round (don't you want to change pixels2)?

//pixel2 = current image. pixel would be the previous image data
for (int x = 0; x < pixels2.length; x++) {
		if (pixels2[x] != pixels[x])                
                        pixels[x] = pixels2[x]; //save the previous image data as the current one                         
                else pixels2[x] = 0;//set current unmodified pixels to 0	
	
}

Maybe I'm missing simething?... or the data doesn't get changed directly?

I thinks the data does not change directly the image because I used this:

finalimg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
               
                Image piximg =  Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(w, h, pixels2,0,w));
                finalimg.getGraphics().drawImage(piximg, 0, 0, null);
                sendImageToStream(finalimg, os_img);

and it transmited the data, low PNG sizes 6k, 10k, for small changes... so "pixels2" data is OK, the problem is the conversion to the BufferedImag which is very slow.

maybe need to do a setData to re-write the raster to the image?

yes, we need, if we can. Also there is a WritableRaster parameter when you construct a buffered image... but it might take some time too...

James, I found out! We shouldn't have used:

Raster ras = ((BufferedImage) img).getData();

I used:

WritableRaster wras = ((BufferedImage) img).getRaster();

and it worked... directly modified the buffered image!
I'll mark this as solved. Thanks. I still have delay because of the compression... but I will post it in the 'big' thread.
Thanks!

Brilliant! Thanks for sharing the answer.
J

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.