Solved

How to display Windows bitmap (.bmp)?

Posted on 1997-11-07
11
435 Views
Last Modified: 2013-11-19
I need to load, display and save a Windows
bitmap (.bmp). Does anybody know how to do
this (source code)?

As far as I understand it the Java getImage()
method is only capable of loading .gif and
.jpeg.

Lewis
0
Comment
Question by:Lewis
  • 6
  • 4
11 Comments
 
LVL 3

Accepted Solution

by:
gwalters earned 250 total points
ID: 1230187
I couldn't find one, so I wrote one.  It doesn't cover every possible BMP file, but it does get the most common ones (and the unsupported modes could easily be added; I have a BMP spec I can send you if you need these other modes).

What it handles:
 1, 4, 8, 24 bit-per-pixel images

What it doesn't:
 16, 32 bit-per-pixel images (which the Windows paint program seems to know nothing about).  These could be added, but they're more complicated as they support bitmap compressions (the above supported modes are straight bitmap).

Here it is.  It's got a main() method for testing, which takes a BMP file as its argument and displays it on a Frame.  If this is unreadable/unusable I can mail it to you:

----------------------CUT_HERE-------------------------------
import java.awt.*;
import java.awt.image.*;
import java.util.*;
import java.io.*;

public class BMPDecoder
{
  private int width;
  private int height;
  private int planes;
  private int bpp;
  private byte[] data;
  private int pos;
  private int[] pixels;
  private int[] colormap;

  public BMPDecoder(String filename) throws FileNotFoundException, IOException
  {
    File f=new File(filename);
    if (!f.exists())
      throw new FileNotFoundException();
    data=new byte[(int)f.length()];
    InputStream in=new FileInputStream(filename);
    in.read(data);
    in.close();
    init();
    decode();
  }

  public BMPDecoder(byte[] data)
  {
    this.data=data;
    init();
    decode();
  }

  private void init()
  {
    String id=""+((char)nextByte())+((char)nextByte());
    if (!"BM".equals(id))
      throw new RuntimeException("Not a Windows Bitmap");
    System.out.println("File size: "+getDWord());
    System.out.println("Reserved: "+getDWord());
    System.out.println("Offset: "+getDWord());
    if (getDWord()!=0x28)
      throw new RuntimeException("Expected 0x28 for Windows Bitmap");
    System.out.println("Width: "+(width=getDWord()));
    System.out.println("Height: "+(height=getDWord()));
    System.out.println("Planes: "+(planes=getWord()));
    System.out.println("BPP: "+(bpp=getWord()));
    if (getDWord()!=0)
      throw new RuntimeException("Compression not supported yet");
    System.out.println("Bitmap size: "+getDWord());
    System.out.println("Horiz resolution: "+getDWord());
    System.out.println("Vert resolution: "+getDWord());
    int colors=getDWord();
    System.out.println("Number of Colors: "+colors);
    System.out.println("Number of Important Colors: "+getDWord());
    if (bpp<24) {
      if (colors==0)
        System.out.println("Number of Colors: "+(colors=1<<bpp));      
      colormap=new int[colors];
      for (int i=0; i<colors; i++) {
        colormap[i]=0xff000000 + (nextByte()&0xff) + (nextByte()&0xff)*0x100 + (nextByte()&0xff)*0x10000;
        nextByte(); //skip padding
      }
    }
  }

  private byte nextByte()
  {
    return data[pos++];
  }

  private void skip(int num)
  {
    pos+=num;
  }

  private void decode()
  {
    pixels=new int[width*height];
    switch (bpp) {
    case 1:
      decode1bit();
      break;

    case 4:
      decode4bit();
      break;

    case 8:
      decode8bit();
      break;

    case 24:
      decode24bit();
      break;

    default:
      throw new RuntimeException(bpp+" bit decoding not supported");
    }
  }

  private void decode1bit()
  {
    int data=nextByte();
    int pos=0x80;
    for (int y=height-1; y>=0; y--)
      for (int x=0; x<width; x++) {
        if ((data&pos)!=0)
          pixels[y*width+x]=colormap[1];
        else
          pixels[y*width+x]=colormap[0];
        if (pos==0x01 && (y!=0 || x!=width-1)) {
          data=nextByte();
          pos=0x80;
        } else {
          pos>>=1;
        }
      }            
  }

  private void decode4bit()
  {
    int w=width;
    while ((w%8)!=0)
      w++;
    int data=nextByte();
    for (int y=height-1; y>=0; y--) {
      for (int x=0; x<w; x++) {
        int idx,i=y*width+x;
        if ((x&1)==0)
          idx=data>>4;
        else {
          idx=data&0x0f;
          if (x!=w-1 || y!=0)
            data=nextByte();
        }
        if (x<width)
          pixels[i]=colormap[idx];
      }
    }

  }

  private void decode8bit()
  {
    for (int y=height-1; y>=0; y--)
      for (int x=0; x<width; x++)
        pixels[y*width+x]=colormap[nextByte()];
  }

  private void decode24bit()
  {
    for (int y=height-1; y>=0; y--)
      for (int x=0; x<width; x++)
        pixels[y*width+x]=0xff000000 + (nextByte()&0xff) + (nextByte()&0xff)*0x100 + (nextByte()&0xff)*0x10000;
  }

  private int getWord()
  {
    return (nextByte()&0xff) + (nextByte()&0xff)*0x100;
  }

  private int getDWord()
  {
    return (nextByte()&0xff) + (nextByte()&0xff)*0x100 +
           (nextByte()&0xff)*0x10000 + (nextByte()&0xff)*0x1000000;
  }

  public Image getImage()
  {
    return Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(width,height,pixels,0,width));
  }

  public static void main(String argv[]) throws FileNotFoundException, IOException
  {
    BMPDecoder bmp=new BMPDecoder(argv[0]);
    Frame f=new Frame();
    f.resize(640,400);
    f.show();
    Image img=bmp.getImage();
    while (true) {
      Graphics g=f.getGraphics();
      g.drawImage(img,0,0,f);
      try {Thread.sleep(500);} catch (Exception e) {}
    }
  }
}
----------------------CUT_HERE-------------------------------
0
 

Author Comment

by:Lewis
ID: 1230188
Hi,
I get the following message in my DOs box:

C:\Lewis\Listings>java BMPDecoder List.bmp
File size: 14406
Reserved: 0
Offset: 118
Width: 371
Height: 76
Planes: 1
BPP: 4
Bitmap size: 14288
Horiz resolution: 0
Vert resolution: 0
Number of Colors: 16
Number of Important Colors: 16
java.lang.ArrayIndexOutOfBoundsException: -1
        at BMPDecoder.decode4bit(BMPDecoder.java
        at BMPDecoder.decode(BMPDecoder.java:90)
        at BMPDecoder.<init>(BMPDecoder.java:27)
        at BMPDecoder.main(BMPDecoder.java:182)
0
 
LVL 3

Expert Comment

by:gwalters
ID: 1230189
Could you send me that image (list.bmp): walters@ct.net

It works on all my 4-bit images, but I'm sure there are bugs in it.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 3

Expert Comment

by:gwalters
ID: 1230190
Oops, disregard my previous comment.  I'm pretty sure this should fix it (stupid mistake):

Change the following line in the decode4bit() method:

BEFORE:   idx=data>>4;
AFTER:    idx=(data>>4)&0x0f;

Sorry about that (only fails if a 4-bit image uses the 16th color).


0
 
LVL 4

Expert Comment

by:rembo
ID: 1230191

Just FYI, if you look at the source for the JDK, it
has code for reading in .bmp files.  If you just
do a getImage(), it should work.

-Tony

0
 
LVL 3

Expert Comment

by:gwalters
ID: 1230192
Rembo,

Didn't work for me (beleive me, I wouldn't have written this if I could have answered "use getImage()").

Are you talking about sun.awt.image.XbmImageDecoder?  That's for X bitmaps, not the same as Windows bitmaps.


0
 

Author Comment

by:Lewis
ID: 1230193
Hi Tony,
it works pretty well so far. It displays most of
my bitmaps.

Could you send me the BMP spec you talked about
earlier? I will try to figure out why it still
does not depict certain BMPs correctly. They
are displayed distorted (at a certain angle) and
with weird colors (looks like some kind of photo
negative).

My email is

utsch@pd.et-inf.uni-siegen.de

Regards, Lewis
0
 
LVL 3

Expert Comment

by:gwalters
ID: 1230194
I sent you the spec.
0
 

Author Comment

by:Lewis
ID: 1230195
Here are your points. They are well deserved.

Lewis
0
 

Author Comment

by:Lewis
ID: 1230196
Here are your points. They are well deserved.

Lewis
0
 
LVL 3

Expert Comment

by:gwalters
ID: 1230197
For anyone who may buy this as a <PAQ>, here are the required fixes:




  private void decode8bit()
  {
    for (int y=height-1; y>=0; y--) {
      for (int x=0; x<width; x++)
        pixels[y*width+x]=colormap[nextByte()&0xff];
      //skip padding so that lines begin on DWord boundaries:
      for (int x=0; x<4-width%4; x++)
        nextByte();
    }
  }

  private void decode24bit()
  {
    for (int y=height-1; y>=0; y--) {
      for (int x=0; x<width; x++)
        pixels[y*width+x]=0xff000000 + (nextByte()&0xff) + (nextByte()&0xff)*0x100 + (nextByte()&0xff)*0x10000;
      //skip padding so that lines begin on DWord boundaries:
      for (int x=0; x<width%4; x++)
        nextByte();
    }
  }


0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Many programs have tried to outwit PowerPoint in terms of technology and skill. These programs, however, still lack several characteristics that PowerPoint has possessed from the start. Here's why PowerPoint replacements won't entirely work for desi…
The viewer will learn how to implement Singleton Design Pattern in Java.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

679 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question