gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Graphics > bitmap palette data

#10682 - hnager - Fri Sep 12, 2003 12:06 pm

I'm putting together a very simple image converter which reads a 16 color bitmap file and creates a header file formatted as needed to copy it to memory...I know that there are other tools out there but I'm looking at this as both a lesson in C/C++ aswell as a way to get exactly what I want out of the converted header file.

Where I'm stuck - is how to extract the bitmap palette? I have no problem opening the bitmap and extracting the height and width and bit depth, but I'm not sure how to get the palette...

thanks! Howard

#10683 - chrisrothery - Fri Sep 12, 2003 12:57 pm

Quick google search yielded this

http://www.gameprogrammer.com/archive/html/msg03091.html

seems to have a pretty low level expaination of the .bmp format, along with some example code. It goes into RLE (run length encoding for compression), which I haven't used in my bmp's before.

I've done similar, but being at work, don't have the code to hand. Piece of advice though, pay attention to padding of rows, I remember that messing me up in the past (bmp's pad each row to an even byte), so if your images come out sort of right but skewed on hardware, that's probably the problem.

#10685 - Nessie - Fri Sep 12, 2003 3:55 pm

You might also find something useful here..just a huge page dedicated to file formats for practically anything you want.

http://www.wotsit.org/

#10741 - hnager - Sat Sep 13, 2003 7:41 pm

hmmm, this is as far as I've gotten - I'm doing something wrong in the palette department...this isn't yet optimized/commented but it has the basics going. I'm only using this for 4 bit bitmaps. help!:

Code:
#include <fstream>
#include <iostream>
#include <windows.h>

using namespace std;

typedef unsigned short uShort;

class Exception {
public:
   Exception(){};
   Exception(char* e){
      details = e;
   }
   void PrintError(){ cout << details << endl; }
private:
   char* details;
};

class BMP1 {
public:
   //file header
   unsigned short   bfType; //must be set to 'BM'
   unsigned long   bfSize; //size in bytes
   unsigned short   bfReserved1;
   unsigned short   bfReserved2;
   unsigned long   bfOffBits; //number of bits before bitmap
};


class BMP2 {
public:
   //bitmap header
   unsigned long   biSize; //size of this header
   unsigned long   biWidth; //the width in pixels
   unsigned long   biHeight; //the height in pixels
   unsigned short   biPlanes; //the number of planes
   unsigned short   biBitCount; //the number of bits per pixel
   unsigned long   biCompression; //the type of compression
   unsigned long   biSizeImage; //size of image in bytes when compressed
   unsigned long   biXPelsPerMeter; //the horizontal number of pix/meter
   unsigned long   biYPelsPerMeter; //the vertical number of pix/meter
   unsigned long   biClrUsed; //the number of colors that are used
   unsigned long   biClrImportant; //the number of important colors
};



void LoadBitmap (char* lpszFilename);

int main(int argc, char* argv[]){
   char* bmpName;

   if (argc > 1){
      bmpName = argv[1];
   } else {
      std::cout << "";
   }
   
   try {
      LoadBitmap(bmpName);
   }
   catch(Exception e)
   {
      e.PrintError();
   }

   
   return 0;
}


void LoadBitmap (char* filename){

   BMP1 BMPFILEHEADER;
   BMP2 BMPINFOHEADER;

   fstream     kBitmap(filename, ios::binary | ios::in );
   
   if(!kBitmap){
      throw Exception("Unable to open bitmap...");
   }

   fstream     kHeader("test.h", ios::out );

   kBitmap.read((char *) &BMPFILEHEADER, 14);

   if (0x4D42 != BMPFILEHEADER.bfType) {
      throw Exception("Not a valid bitmap...");
   }

   kBitmap.read((char *) &BMPINFOHEADER, 40);

   if (BMPINFOHEADER.biCompression != BI_RGB){
      throw Exception("Compression not supported...");
   }
   
   

   kHeader << "//Height: " << BMPINFOHEADER.biHeight << endl;
   kHeader << "//Width: " << BMPINFOHEADER.biWidth << endl;
   kHeader << "//BitCount: " << BMPINFOHEADER.biBitCount << endl;

   kHeader << "const u8 palette[] = {" << endl << "\t";
   
   int r, g, b, counter = 0;
   for( int i=0; i<16*2; i++){
      r = kBitmap.get() >> 3 << 10;
      g = kBitmap.get() >> 3 << 5;
      b = kBitmap.get() >> 3;

      kHeader << "0x" << hex << (unsigned short)(r|g|b);
      kHeader << ", ";
      kBitmap.get(); // skip a byte (RGBx)
      if(!(++counter%8)) kHeader << endl << "\t";

   }

   kHeader << endl << "};" << endl;
   
   
   // Move to bitmap buffer
   kBitmap.seekg (10, ios::beg);
   kBitmap.read((char*)&BMPFILEHEADER.bfOffBits,4);

   kBitmap.seekg (BMPFILEHEADER.bfOffBits, ios::beg);

   
   int b1, b2;
   counter = 0;

   kHeader << "const u8 data[] = {" << endl << "\t";

   for(int i = (BMPINFOHEADER.biHeight*BMPINFOHEADER.biWidth)/2; i > 0; i--){

      b1 = kBitmap.get();
      //b2 = kBitmap.get();
      kHeader << "0x" << hex << b1;
      kHeader << ", ";
      if(!(++counter%8)) kHeader << endl << "\t";
   }

   kHeader << endl << "};" << endl;

   kBitmap.close ();
   kHeader.close ();

}

#10762 - hnager - Sun Sep 14, 2003 11:44 pm

Figured it out...now my only problem is that all black pixels are showing up as transparent...

#10769 - tepples - Mon Sep 15, 2003 3:37 am

In the GBA's indexed color modes (0, 1, 2, 4, and sprites), color 0 is always transparent. If color 0 in your palette is black, rearrange your palette so that color 0 is not used in your image.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#10770 - hnager - Mon Sep 15, 2003 3:41 am

I suppose that would have to be done within the bitmap itself, before running it through my converter?

#10784 - tepples - Mon Sep 15, 2003 3:35 pm

Yes.

To do this in GIMP, set the upper-left pixel of your bitmap to the color you want to use as transparent, then convert to indexed color, then change the upper-left pixel back.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.