Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

How to display Windows bitmap (.bmp)?

Posted on 1997-11-07
11
Medium Priority
?
452 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
11 Comments
 
LVL 3

Accepted Solution

by:
gwalters earned 1000 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

The top UI technologies you need to be aware of

An important part of the job as a front-end developer is to stay up to date and in contact with new tools, trends and workflows. That’s why you cannot miss this upcoming webinar to explore the latest trends in UI technologies!

Question has a verified solution.

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

Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Not only does Prezi allow you to create non-linear presentations, it also makes it easy to apply transition animations between your frames. Learn how to apply a fade-in transition to select items and entire frames in this tutorial Select "Edit Path"…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…

715 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