bitmap to hex

freakyhair

Limp Gawd
Joined
Dec 22, 2002
Messages
475
Hi all,

just curious if anyone knows of a program that can convert a small, B&W 320x240 bitmap into hex. I have tried a few but they are usually limited by size, or convert only color bmps. in general, they don't quite do what i need.

if not, I have visual C++ (and am comfortable, but not great with C/C++), and would be willing to try to write a program, but don't really know where to start. I would also consider using visual basic C# if you think it would be worth my time. Are there easy ways to extract the data from bitmaps in visual c++?

I need this so I can display bitmaps i have created in illustrator on an LCD via an NXP ARM7 microcontroller. I have the mC side set up, I just need to figure out how to con ert the bitmaps easily!

Thanks!!!
 
it's pretty trivial with .net. i just whipped this together. obviously you probably need to tweak to your actual needs
http://tmullin.net/~tim/BWBMP2ARRAY.zip
i just have it print 1s and 0s for white/black. i made a test bmp and get
test.bmp

Code:
00000000000000000000
00000000000000000000
00000000000000000000
01111111001111110000
00001000001000000000
00001000001000000000
00001000001000000000
00001000001110000000
00001000001000000000
00001000001000000000
00001000001111110000
00000000000000000000
00000000000000000000
00111100111111111000
00100000000100000000
00100000000100000100
00100000000100000010
00111100000100010010
00000100000100000010
00000100000100010010
00000100000100000010
00001100000100000100
01111000000000000000
00000000001111110000
00010100101000000000
00010110101011000000
00010101101001000000
00010100101111000000
00000000000000000000
00000000000000000000

let me know if the link doesn't work, i've been having some issues with my site...


/edit
reread the OP and realized i just didn't read it carefully enough. what exactly is the hex format you need?
 
I need it in single byte format. So if the first 8 bits in the hex are 10100101, I would like it to output 0xA5. Is that what you mean? I have not had a chance to look at what you made, but I will when I get home. I really appreciate the help. Thanks.
Posted via [H] Mobile Device
 
i don't suppose you have a sample bitmap and sample output you're trying to get? i've never done anything with lcds so i'm having a hard time visualizing what you want. getting the pixel data is easy. from there i don't know what you need.
 
You could convert it to a 256 color indexed image then save it as a .xpm with Gimp. Then you would have a header file, xpm is just a header file, that you could include in your C++ program. Then it should be pretty straight forward to convert it to a 256 color bw image in hex. Personally I would probably just do it with perl and some fancy regexes.
 
What exactly do you mean when you say you want it in hex? Do you want the ASCII string "0xA5"? Or a single byte with the bit pattern 10100101? The former is hex; the latter you would probably call raw binary. Hex is a human-readable representation - I'd be surprised if that's what your microcontroller is asking for.

Raw binary is how they're represented in the bitmap file, so extracting this representation is dead easy, especially if it's fixed at 320x240 monochrome. Counting from zero, bytes 10-13 (taken as an integer) tell you where the image data starts. As your number of bits per row is a multiple of 32, you don't have to worry about padding - the data should be contiguous.

I'd imagine this C/C++ code should do it, though I haven't tested it (or even thought about it terribly hard :D ). Make sure that filename is null-terminated and that img is allocated 320*240/8 bytes.
Code:
#include <stdio.h>

void extract(char *filename,char *img)
{
    int byte = 0;
    int start;
    FILE *fp = fopen(filename,"r");

    do fgetc(fp); while (++byte < 10);
    fread(&start,4,1,fp);
    byte += 4;
    do fgetc(fp); while (++byte < start);
    fread(img,1,320*240/8,fp);
    fclose(fp);
}
 
TIm_m, I think you're on to what I'm looking for. only instead of 1's and 0's, I'd need it in '0x00' (8-bit hex?)

What exactly do you mean when you say you want it in hex? Do you want the ASCII string "0xA5"? Or a single byte with the bit pattern 10100101? The former is hex; the latter you would probably call raw binary. Hex is a human-readable representation - I'd be surprised if that's what your microcontroller is asking for.

Raw binary is how they're represented in the bitmap file, so extracting this representation is dead easy, especially if it's fixed at 320x240 monochrome. Counting from zero, bytes 10-13 (taken as an integer) tell you where the image data starts. As your number of bits per row is a multiple of 32, you don't have to worry about padding - the data should be contiguous.

I'd imagine this C/C++ code should do it, though I haven't tested it (or even thought about it terribly hard :D ). Make sure that filename is null-terminated and that img is allocated 320*240/8 bytes.

I guess maybe I wasn't clear enough, and I apologize. From what it sounds like, I want the binary value of the dots on the screen.
Maybe I can describe this better. Let's say I have a monochrome Bitmap that is 32 pixels wide, and 8 Pixels high. If I wanted the left half to be white, and right half to be black, the bits in the array would need to be:

Code:
00000000000000001111111111111111
00000000000000001111111111111111
00000000000000001111111111111111
00000000000000001111111111111111
00000000000000001111111111111111
00000000000000001111111111111111
00000000000000001111111111111111
00000000000000001111111111111111

I would like it in this format:
Code:
const unsigned char bitmap[] = 
{
0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0xFF, 0xFF,
0x00, 0x00, 0xFF, 0xFF
}

For a more complicated example:
Code:
10000000000000000111111111111111
01000000000000001011111111111111
00100000000000001101111111111111
00010000000000001110111111111111
00001000000000001111011111111111
00000100000000001111101111111111
00000010000000001111110111111111
00000001000000001111111011111111
How I would like the data:
Code:
const unsigned char bitmap[] = 
{
0x80, 0x00, 0x7F, 0xFF,
0x40, 0x00, 0xBF, 0xFF,
0x20, 0x00, 0xDF, 0xFF,
0x10, 0x00, 0xEF, 0xFF,
0x08, 0x00, 0xF7, 0xFF,
0x04, 0x00, 0xFB, 0xFF,
0x02, 0x00, 0xFD, 0xFF,
0x01, 0x00, 0xFE, 0xFF
}

I hope it makes more sense. Only in my case, the bitmap is 320x240. I have tried using gimp, but the output didn't get me a whole lot further.

I really appreciate the time you guys re taking to help me understand this. I know it should be easier than I'm making it out to be, I'm just not that familiar with how to extract this from the bitmap, and then how to put it into a file.

Thanks!!!
 
OK, that's exactly what my code should do. Pass it the bitmap's file name and a pointer to an empty 9600-element character array, and it should fill out the array as you've shown.

EDIT: Wait a minute...
Do you want this character array generated inside your program? Or do you want that declaration written to a text file?

OK, give this a try. Once again, not sure if it works (or even compiles... :D).

Code:
#include <stdlib.h>
#include <stdio.h>

void extract(char *filename,char *img)
{
    int byte = 0;
    int start;
    FILE *fp = fopen(filename,"r");

    do fgetc(fp); while (++byte < 10);
    fread(&start,4,1,fp);
    byte += 4;
    do fgetc(fp); while (++byte < start);
    fread(img,1,9600,fp);
    fclose(fp);
}

int main()
{
    int i;
    char hexdigit[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    FILE *fp = fopen("outfile.c","w");
    unsigned char *bitmap = (unsigned char *)malloc(9600);
    extract("infile.bmp",bitmap);

    fputs("const unsigned char bitmap[] = \n{",fp);
    for (i=0;i<9600;i++)
    {
        if (i%320==0) fputc('\n',fp);
        fputc(hexdigit[bitmap[i]>>4],fp);
        fputc(hexdigit[bitmap[i]&0x0F],fp);
        if (i!=9599) fputc(',',fp);
    }
    fputs("\n}\n",fp);
    fclose(fp);
    free(bitmap);
}
 
Last edited:
OK, so I went with Luminary's example (I'm way more familiar with C/C++ than C#). It had to adjust it slightly to get the BMP data in the order I need it, (reverse the order of the rows) and it works...sometimes...

By sometimes, I mean I can open one BMP file (call it file a), and it will work great. I will try another BMP (file B) of the exact same size, and I will get '0xCD' as over half of my data (in a big group, usually toward the end of the data.) I can even copy the exact image from 'file b' to 'file a', save the data into the file using GIMP, and I will get the same '0xCD' for a large portion. Is this maybe because the data stream in 'extract()' is bad? I can open the BMPs that don't convert correctly just fine in any program, and when I look at the data in a binary reader, the data between both types of BMPs seem very very similar (headers do anyway.)

Code:
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>

void extract(char *filename,char *img)
{
    int byte = 0;
    int start;
    FILE *fp = fopen(filename,"r"); //open file for reading
	

    do fgetc(fp); while (++byte < 10);
    fread(&start,4,1,fp);
    byte += 4;
    do fgetc(fp); while (++byte < start);
    fread(img,1,9600,fp);
    fclose(fp);
}

int main()
{
    int i;
	int j;
    char hexdigit[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    FILE *fp = fopen("outfile.c","w");

    //unsigned char *bitmap = (unsigned char *)malloc(9600);
	char *bitmap = (char *)malloc(9600); //assign 9600 bytes of memory to the pointer 'bitmap'
    extract("infile.bmp",bitmap);

    fputs("const unsigned char bitmap[] = \n{",fp);

	for (i=239; i >= 0; i--) //start at bottom, and work up in rows
	{
		fputc('\n',fp); //each line, put a return
		for (j = 0; j < 40; j++)
		{
			fputc('0',fp);
			fputc('x',fp); //put the '0x' in front of the hex value
			fputc(hexdigit[ (bitmap[(i*40)+j]>>4)&0x0F ],fp);  //put the upper value of the byte
			fputc(hexdigit[bitmap[(i*40)+j]&0x0F],fp); //put the lower value of the byte
			if (!((i==1)&&(j==39))) fputc(',',fp);
		}
	}

    fputs("\n}\n",fp);
    fclose(fp);
    free(bitmap);
}

here are some of the files I'm using and their outputs
http://sites.google.com/site/sogrodnik/Home/filea-works.bmp
http://sites.google.com/site/sogrodnik/Home/fileb-nowork.bmp
Good output: http://sites.google.com/site/sogrodnik/Home/output-filea.c
Bad output (0xcd): http://sites.google.com/site/sogrodnik/Home/outfile-fileb.c
 
SOLUTION:

We currently open the file using 'FILE *fp = fopen(filename,"r");' This is OK, but any time it reads in '0x1A', it takes it as an EOF. Simply using "rb" as the parameter opens it in binary. solves my problems.

It seems to do everything I need. I originally came in here just for some guidance on opening the files, but I got a whole lot more. THANK YOU all very much for checking this out and helping me along.

~Freakyhair
 
Back
Top