views:

16529

answers:

2

Hey,

I'm trying to convert an Image object to a byte array then back to an Image (so that I can store the image in a blob object in an Apache Derby Database).

I can convert an Image to a byte array (code below) but I cann't convert the bytes back to an image. As a further complication I'm using J2ME, so I can't use javax.image.*. Can you help?

Thanks

package six.util;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver; 
import java.awt.Component; 
import java.awt.MediaTracker;
import java.awt.Graphics;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.image.PixelGrabber;
import java.util.ArrayList;

public class ImageConverter extends Component
{

private MediaTracker mediaTracker;
private Image image;

private ImageConverter(Image image)
{
 super();
 this.mediaTracker = new MediaTracker(this);
 this.mediaTracker.addImage(image, 0);
 this.image = image;
}

private BufferedImage convert()
{
 /*
  * Have to wait for image to load.
  */
 try
 {
  this.mediaTracker.waitForID(0);
 }catch(InterruptedException e)
 {

 }
 System.out.println("-1");

 GraphicsConfiguration graphicsConfig = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
 BufferedImage bimage = graphicsConfig.createCompatibleImage(this.image.getWidth(null),this.image.getHeight(null));
 System.out.println("-2");
 Graphics g = bimage.getGraphics();
 g.drawImage(image, 0, 0, null);
 return bimage;
}

private static byte[] convertIntToByteArray(int integer)
{
 byte[] bytes = new byte[4];
 bytes[0] =(byte)( integer >> 24 );
 bytes[1] =(byte)( (integer << 8) >> 24 );
 bytes[2] =(byte)( (integer << 16) >> 24 );
 bytes[3] =(byte)( (integer << 24) >> 24 );
 return bytes;
}

private static int convertByteArrayToInt(byte[] bytes)
{
 return (bytes[0] << 32) | (bytes[1] << 24) | (bytes[2] << 16) | (bytes[3] << 8) | bytes[4];
}

private static byte[] convertIntArrayToByteArray(int[] integers)
{
 byte[] bytes = new byte[integers.length*4];
 for (int index = 0; index < integers.length; index++)
 {
  byte[] integerBytes = convertIntToByteArray(integers[index]);
  bytes[index*4] =   integerBytes[0];
  bytes[1 + (index*4)] = integerBytes[1];
  bytes[2 + (index*4)] = integerBytes[2];
  bytes[3 + (index*4)] = integerBytes[3];
 }
 return bytes;
}

private static int[] convertByteArrayToIntArray(byte[] bytes)
{
 ArrayList integers = new ArrayList();
 for (int index = 0; index < bytes.length; index += 4)
 {
  byte[] fourBytes = new byte[4];
  fourBytes[0] = bytes[index];
  fourBytes[1] = bytes[index+1];
  fourBytes[2] = bytes[index+2];
  fourBytes[3] = bytes[index+3];
  int integer = convertByteArrayToInt(fourBytes);
  integers.add(new Integer(integer));
 }
 int[] ints = new int[bytes.length/4];
 for (int index = 0; index < integers.size() ; index++)
 {
  ints[index] = ((Integer)integers.get(index)).intValue();
 }
 return ints;
}

public static byte[] convertToBytes(Image image)
{
 System.out.println("A");
 ImageConverter converter = new ImageConverter(image);
 System.out.println("B");
 BufferedImage bufferedImage = converter.convert();
 System.out.println("C");
 PixelGrabber pixelGrabber = new PixelGrabber(image,0,0,bufferedImage.getWidth(),bufferedImage.getHeight(),true);
 System.out.println("D");
 try
 {
  if(pixelGrabber.grabPixels())
  {
   Object pixels = pixelGrabber.getPixels();
   if (pixels instanceof byte[])
   { 
    return (byte[])pixels;
   }
   return convertIntArrayToByteArray((int[])pixels);
  }
 }catch(InterruptedException e)
 {
 }
 return null;
}


 }
+1  A: 

To recreate the image you can use the method createRGBImage in the Image class (http://java.sun.com/javame/reference/apis/jsr118/), but be aware that you're using 4 bytes for each pixel in the image. A image with 200 x 200 pixels of width will have 40000 pixels in total, which will occupy 160KB of memory in the mobile device.

I've worked with images in J2ME before, but only sending the images from the server to the client. In that case, you can change the resolution of the image on the server (where you have the code and the raw power to do that), encode it as JPEG and then send it to the client. The method Image.createImage(...) can create an image in any encoded format supported by the J2ME engine that is running the application. I believe that JPEG will always be accepted.

Even if you need those images for future use, you can save the byte[] buffer returned by the server in a Record Store and then use it.

Ravi Wallau
+2  A: 

I don't know about javame, but wouldn't this work?

javax.microedition.lcdui.Image.createImage(new ByteArrayInputStream(byte[]))
moshen
that is a much quicker way
Graham