Solved

How to display Windows bitmap (.bmp)?

Posted on 1997-11-07
11
428 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
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 
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

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
javap bin 2 34
Java exception bubble up 2 17
pagenation logic how it is working in my code 1 26
How to determine if a string is a valid SHA value 7 28
Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Learn how to set up basic frames and paths in Prezi and understand the open space that Prezi allows you to create presentations in.
In addition to being a great web-based presentation tool, Prezi also makes it easy to save your presentation as a PDF to share with others as well. Learn how in this tutorial. Select the share icon from the top menu in your Prezi editor: Select "D…

815 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

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now