I have an image which needs to be sent to the server. Is there a way to convert a bitmap(jpg) to base64 string in blackberry?
Found this one, much faster conversion of Bitmap to byte[]. Exactly what I needed.
import java.io.*;
import javax.microedition.lcdui.Image;
import net.rim.device.api.compress.ZLibOutputStream;
public class MinimalPNGEncoder
{
public static Image toImage(int width, int height, byte[] alpha, byte[] red, byte[] green, byte[] blue)
{
try
{
byte[] png = toPNG(width, height, alpha, red, green, blue);
return Image.createImage(png, 0, png.length);
}
catch (IOException e)
{
return null;
}
}
public static byte[] toPNG(int width, int height, byte[] alpha, byte[] red, byte[] green, byte[] blue) throws IOException
{
byte[] signature = new byte[] {(byte) 137, (byte) 80, (byte) 78, (byte) 71, (byte) 13, (byte) 10, (byte) 26, (byte) 10};
byte[] header = createHeaderChunk(width, height);
byte[] data = createDataChunk(width, height, alpha, red, green, blue);
byte[] trailer = createTrailerChunk();
ByteArrayOutputStream png = new ByteArrayOutputStream(signature.length + header.length + data.length + trailer.length);
png.write(signature);
png.write(header);
png.write(data);
png.write(trailer);
return png.toByteArray();
}
public static byte[] createHeaderChunk(int width, int height) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream(13);
DataOutputStream chunk = new DataOutputStream(baos);
chunk.writeInt(width);
chunk.writeInt(height);
chunk.writeByte(8); // Bitdepth
chunk.writeByte(6); // Colortype ARGB
chunk.writeByte(0); // Compression
chunk.writeByte(0); // Filter
chunk.writeByte(0); // Interlace
return toChunk("IHDR", baos.toByteArray());
}
public static byte[] createDataChunk(int width, int height, byte[] alpha, byte[] red, byte[] green, byte[] blue) throws IOException
{
int source = 0;
int dest = 0;
byte[] raw = new byte[4*(width*height) + height];
for (int y = 0; y < height; y++)
{
raw[dest++] = 0; // No filter
for (int x = 0; x < width; x++)
{
raw[dest++] = red[source];
raw[dest++] = green[source];
raw[dest++] = blue[source];
raw[dest++] = alpha[source++];
}
}
return toChunk("IDAT", toZLIB(raw));
}
public static byte[] createTrailerChunk() throws IOException
{
return toChunk("IEND", new byte[] {});
}
public static byte[] toChunk(String id, byte[] raw) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream(raw.length + 12);
DataOutputStream chunk = new DataOutputStream(baos);
chunk.writeInt(raw.length);
byte[] bid = new byte[4];
for (int i = 0; i < 4; i++)
{
bid[i] = (byte) id.charAt(i);
}
chunk.write(bid);
chunk.write(raw);
int crc = 0xFFFFFFFF;
crc = updateCRC(crc, bid);
crc = updateCRC(crc, raw);
chunk.writeInt(~crc);
return baos.toByteArray();
}
static int[] crcTable = null;
public static void createCRCTable()
{
crcTable = new int[256];
for (int i = 0; i < 256; i++)
{
int c = i;
for (int k = 0; k < 8; k++)
{
c = ((c & 1) > 0) ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
}
crcTable[i] = c;
}
}
public static int updateCRC(int crc, byte[] raw)
{
if (crcTable == null)
{
createCRCTable();
}
for (int i = 0; i < raw.length; i++)
{
crc = crcTable[(crc ^ raw[i]) & 0xFF] ^ (crc >>> 8);
}
return crc;
}
/* This method is called to encode the image data as a zlib
block as required by the PNG specification. This file comes
with a minimal ZLIB encoder which uses uncompressed deflate
blocks (fast, short, easy, but no compression). If you want
compression, call another encoder (such as JZLib?) here. */
public static byte[] toZLIB(byte[] raw) throws IOException
{
//used the BB ZLib ...
ByteArrayOutputStream outBytes = new ByteArrayOutputStream(1024);
ZLibOutputStream compBytes = new ZLibOutputStream(outBytes, false, 10, 9);
compBytes.write(raw, 0, raw.length);
compBytes.close();
return outBytes.toByteArray();
//return ZLIB.toZLIB(raw);
}
}
class ZLIB
{
static final int BLOCK_SIZE = 32000;
public static byte[] toZLIB(byte[] raw) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream(raw.length + 6 + (raw.length / BLOCK_SIZE) * 5);
DataOutputStream zlib = new DataOutputStream(baos);
byte tmp = (byte) 8;
zlib.writeByte(tmp); // CM = 8, CMINFO = 0
zlib.writeByte((31 - ((tmp << 8) % 31)) % 31); // FCHECK (FDICT/FLEVEL=0)
int pos = 0;
while (raw.length - pos > BLOCK_SIZE)
{
writeUncompressedDeflateBlock(zlib, false, raw, pos, (char) BLOCK_SIZE);
pos += BLOCK_SIZE;
}
writeUncompressedDeflateBlock(zlib, true, raw, pos, (char) (raw.length - pos));
// zlib check sum of uncompressed data
zlib.writeInt(calcADLER32(raw));
return baos.toByteArray();
}
private static void writeUncompressedDeflateBlock(DataOutputStream zlib, boolean last,
byte[] raw, int off, char len) throws IOException
{
zlib.writeByte((byte)(last ? 1 : 0)); // Final flag, Compression type 0
zlib.writeByte((byte)(len & 0xFF)); // Length LSB
zlib.writeByte((byte)((len & 0xFF00) >> 8)); // Length MSB
zlib.writeByte((byte)(~len & 0xFF)); // Length 1st complement LSB
zlib.writeByte((byte)((~len & 0xFF00) >> 8)); // Length 1st complement MSB
zlib.write(raw,off,len); // Data
}
private static int calcADLER32(byte[] raw)
{
int s1 = 1;
int s2 = 0;
for (int i = 0; i < raw.length; i++)
{
int abs = raw[i] >=0 ? raw[i] : (raw[i] + 256);
s1 = (s1 + abs) % 65521;
s2 = (s2 + s1) % 65521;
}
return (s2 << 16) + s1;
}
}
And this is the method that you need to invoke.
public static byte[] toPNG(Bitmap image) throws IOException {
int imageSize = image.getWidth() * image.getHeight();
int[] rgbs = new int[imageSize];
byte[] a, r, g, b;
int colorToDecode;
image.getARGB(rgbs, 0, image.getWidth() , 0, 0, image.getWidth(), image.getHeight());
a = new byte[imageSize];
r = new byte[imageSize];
g = new byte[imageSize];
b = new byte[imageSize];
for (int i = 0; i < imageSize; i++) {
colorToDecode = rgbs[i];
a[i] = (byte) ((colorToDecode & 0xFF000000) >>> 24);
r[i] = (byte) ((colorToDecode & 0x00FF0000) >>> 16);
g[i] = (byte) ((colorToDecode & 0x0000FF00) >>> 8);
b[i] = (byte) ((colorToDecode & 0x000000FF));
}
return MinimalPNGEncoder.toPNG(image.getWidth(), image.getHeight(), a, r, g, b);
}
This is not mine. I am so grateful to Christian Fr�schlin for creating this and letting other developers to use this. This is the link for the terms.
Before i forgot, this one has a limitation. It can converts successfully a bitmap to byte[] which size is less than or equal to 63kb, but if the size exceeds the limit the converted image will be discolored.