2

I'm trying to open .ppm images (Portable pixmaps) in Android. I've deciphered the format enough to create this:

public static Bitmap ReadBitmapFromPPM(String file) throws IOException
{
    //FileInputStream fs = new FileInputStream(file);
    BufferedReader reader = new BufferedReader(new FileReader(file));
    if (reader.read() != 'P' || reader.read() != '6')
        return null;
    reader.read(); //Eat newline
    String widths = "", heights = "";
    char temp;
    while ((temp = (char)reader.read()) != ' ')
    widths += temp;
    while ((temp = (char)reader.read()) >= '0' && temp <= '9')
    heights += temp;
    if (reader.read() != '2' || reader.read() != '5' || reader.read() != '5')
        return null;
    reader.read(); //Eat the last newline
    int width =  Integer.parseInt(widths);
    int height = Integer.parseInt(heights);
    int[] colors = new int[width*height];

   //Read in the pixels
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            char[] pixel = new char[3];
            reader.read(pixel);
            /*
            int red = reader.read();
            int green = reader.read();
            int blue = reader.read();

            byte r = (byte)red;
            byte g = (byte)green;
            byte b = (byte)blue;*/
            colors[y*width + x] =   //(255 << 24) | //A
                                    (pixel[0]&0x0ff << 16) | //R
                                    (pixel[1]&0x0ff << 8)  | //G
                                    (pixel[2]&0x0ff);       //B
        }
    }

    Bitmap bmp = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888);

I get to the point where I'm decoding the pixels, but the ascii values of the green and blue values for even the first pixel are 16 bit max value (65535 when using .read()). As you can see I've tried a lot of things to drill down to a decent value for the colors, but no luck.

When I look at the values in the ppm the characters in the second and third fields are strange. Does anyone know where I'm going astray here? The ppm opens properly in photoshop...

Anthony
  • 7,638
  • 3
  • 38
  • 71
  • You can get the full source of the [netpbm toolkit](http://netpbm.sourceforge.net/), there's no need for guess work. – mu is too short Jul 17 '11 at 21:26
  • I did come across that, but it is surprisingly complicated given the distributed core code when I was looking for a rather simple solution, but thanks for the pointer. – Anthony Jul 18 '11 at 00:23

2 Answers2

2

My code was rather foolish since I didn't research what a char in Java actually was. char in Java is not a simple byte. When the code is modified to consume byte by byte it works.

Anthony
  • 7,638
  • 3
  • 38
  • 71
  • Hi, i know its too long but can you show me the code snippet of your solution please? i too have the same issue and want to see your implementation of the problem. – KunalK Nov 26 '13 at 10:33
  • I changed that code a long time ago to deal directly with rgb bitmaps. I believe it was just a matter of swapping char with byte, but I can't remember at this point. Are you getting this image from native? – Anthony Nov 26 '13 at 13:52
1

for anyone still struggling with this, here is a functioning solution that I managed to create merging this with some other code I found online:

public static Bitmap ReadBitmapFromPPM2(String file) throws IOException {
    //FileInputStream fs = new FileInputStream(file);
    BufferedInputStream reader = new BufferedInputStream(new FileInputStream(new File(file)));
    if (reader.read() != 'P' || reader.read() != '6')
        return null;

    reader.read(); //Eat newline
    String widths = "" , heights = "";
    char temp;
    while ((temp = (char) reader.read()) != ' ') {
        widths += temp;
    }
    while ((temp = (char) reader.read()) >= '0' && temp <= '9')
        heights += temp;
    if (reader.read() != '2' || reader.read() != '5' || reader.read() != '5')
        return null;
    reader.read();

    int width = Integer.valueOf(widths);
    int height = Integer.valueOf(heights);
    int[] colors = new int[width * height];

    byte [] pixel = new byte[3];
    int len = 0;
    int cnt = 0;
    int total = 0;
    int[] rgb = new int[3];
    while ((len = reader.read(pixel)) > 0) {
        for (int i = 0; i < len; i ++) {
            rgb[cnt] = pixel[i]>=0?pixel[i]:(pixel[i] + 255);
            if ((++cnt) == 3) {
                cnt = 0;
                colors[total++] = Color.rgb(rgb[0], rgb[1], rgb[2]);
            }
        }
    }

    Bitmap bmp = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888);
    return bmp;
}
Mitch
  • 21
  • 3