Tyler Helmuth
Tyler Helmuth

Reputation: 129

Send Java BufferedImage to Bitmap Android

Hi I am trying to send a BufferedImage I have on my Java application through a tcp socket to an Android Device. I currently get the raster in a byte[] from the BufferedImage and then ship this through a plain OutputStream to the device. This works fine and I get the same byte array on the Android side. When I call Bitmap.decodeByteArray() however, I only get null.

Here is the code I have to send my picture in Java. The image type of the BufferedImage is TYPE_4BYTE_ABGR

byte[] imgBytes =    ((DataBufferByte)msg.getImage().getData().getDataBuffer()).getData();

lineBytes = (String.valueOf(imgBytes.length) + '\n').getBytes();        
out.write(lineBytes);
out.write(imgBytes);
out.write((int)'\n');
out.flush();

The first thing I write out is the size of the image so I know how big to make the byte[] on Android.

Here's the code I'm trying to use to create the Android Bitmap.

currLine = readLine(in);
int imgSize = Integer.parseInt(currLine);
byte[] imgBytes = new byte[imgSize];
in.read(imgBytes);
BitmapFactory.Options imgOptions = new BitmapFactory.Options();
imgOptions.inPreferredConfig = Bitmap.Config.ARGB_4444;

Bitmap img = BitmapFactory.decodeByteArray(imgBytes, 0, imgSize, imgOptions);

The bytes arrive fine.. They just don't work for the Bitmap.

Upvotes: 2

Views: 4232

Answers (2)

Ananth
Ananth

Reputation: 1085

imgSize should be the size of the image. Why not try imgBytes.length?

Upvotes: 0

Harald K
Harald K

Reputation: 27113

To elaborate on the suggestion I made in the comment:

From the Java/server side, send the image's width and height (if you know your image's type is always TYPE_4BYTE_ABGR you don't need anything else):

BufferedImage image = msg.getImage();
byte[] imgBytes = ((DataBufferByte) image.getData().getDataBuffer()).getData();

// Using DataOutputStream for simplicity
DataOutputStream data = new DataOutputStream(out);

data.writeInt(image.getWidth());
data.writeInt(image.getHeight());
data.write(imgBytes);

data.flush();

Now you can either convert the interleaved ABGR byte array to packed int ARGB on the server side, or on the client side, it does not really matter. I'll show the conversion on the Android/client side, for simplicity:

// Read image data
DataInputStream data = new DataInputStream(in);
int w = data.readInt();
int h = data.readInt();
byte[] imgBytes = new byte[w * h * 4]; // 4 byte ABGR
data.readFully(imgBytes);

// Convert 4 byte interleaved ABGR to int packed ARGB
int[] pixels = new int[w * h];
for (int i = 0; i < pixels.length; i++) {
    int byteIndex = i * 4;
    pixels[i] = 
            ((imgBytes[byteIndex    ] & 0xFF) << 24) 
          | ((imgBytes[byteIndex + 3] & 0xFF) << 16) 
          | ((imgBytes[byteIndex + 2] & 0xFF) <<  8) 
          |  (imgBytes[byteIndex + 1] & 0xFF);
} 

// Finally, create bitmap from packed int ARGB, using ARGB_8888
Bitmap bitmap = Bitmap.createBitmap(pixels, w, h, Bitmap.Config.ARGB_8888);

If you really want ARGB_4444, you can convert the bitmap, but note that the constant is deprecated in all recent versions of the Android API.

Upvotes: 2

Related Questions