# How can I convert an image from raw data in Android without any munging?

I have raw image data (may be .png, .jpg, ...) and I want it converted in Android without changing its pixel depth (bpp). In particular, when I load a grayscale (8 bpp) image that I want to use as alpha (glTexImage() with GL_ALPHA), it converts it to 16 bpp (presumably 5_6_5).

While I do have a plan B (actually, I'm probably on plan 'E' by now, this is really becoming annoying) I would really like to discover an easy way to do this using what is readily available in the API.

So far, I'm using BitmapFactory.decodeByteArray().

While I'm at it. I'm doing this from a native environment via JNI (passing the buffer in from C, and a new buffer back to C from Java). Any portable solution in C/C++ would be preferable, but I don't want to introduce anything that might break in future versions of Android, etc.

• I'm not sure about the results but you may try to convert all image files into a single format first. then it willl be easier to customize one loading library. – Ali1S232 Jun 23 '11 at 11:07
• There is a question on StackOverflow that asks a similar question and there are a couple of solutions posted there. What have you tried so far? – CaseyB Jun 23 '11 at 18:41
• I can circumvent the problem by "knowing" what the image is and how I want to interpret it. But if Android would just give me the image as it should be, I wouldn't have to. – notlesh Jun 23 '11 at 19:11

Note that since JPEG images use a Y or YUV colourspace they do not really have a pixel depth and thus there is no "right" depth for them. That said, you are correct in expecting a 8bpp grayscale image when decoding a monochrome JPEG.

I don't know of an available API to achieve what you are trying to do in an automatic way. However, you can ask for a specific depth using the BitmapFactory preferred options:

 BitmapFactory.Options opts = new BitmapFactory.Options();
// This option is suitable for monochrome JPEGs:
opts.inPreferredConfig = Bitmap.Config.ALPHA_8;
// This option is suitable for 32-bit PNGs:
opts.inPreferredConfig = Bitmap.Config.RGB_8888;

bitmap = BitmapFactory.decodeByteArray(data, 0, len, opts);


This is still a hint for the decoder and does not guarantee that you will always get what you expect. I have additional suggestions:

• embed your own versions of libPNG and/or libJPEG. I suggest trying libjpeg-turbo which allows to fine-tune the available colourspaces even more.
• instead of using PNG or JPEG as your interchange format, use one or several texture compression formats suitable for your target devices; there are readily available tools to convert PNGs to ETC1, which is part of the OpenGL ES standard. Maybe add a layer of gzip on top of that.
• do not hesitate to experiment and try generic compression methods: store your image just as you would upload it to the video card, and compress it using libgz or libbzip2. I have images that get significantly smaller using bzip2 on an uncompressed version than when crushing with pngcrush. That may be an acceptable tradeoff.

Hope this helps!

• Thanks, these are all useful suggestions. I will consider them when I get back around to this issue; however, I am also considering adopting SDL, as it can help me keep my codebase very portable. – notlesh Jun 29 '11 at 1:15

To convert raw to image, the best Java API is ImageIO.

Documentation: ImageIO @ Java API