Solved

How to display Windows bitmap (.bmp)?

Posted on 1997-11-07
11
423 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
 
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
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Introduction This article is the second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
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…
This video teaches viewers about errors in exception handling.
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.

746 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

11 Experts available now in Live!

Get 1:1 Help Now