1 // gcc -Wall -g bmp2dat.c -o bmp2dat `sdl-config --cflags --libs`
2 
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <stdint.h>
6 #include <limits.h>
7 #include <errno.h>
8 #include <string.h>
9 
10 #include <SDL.h>
11 
12 #define IMAGE_DAT_OR_MASK 0xff030303 // Reduce colour depth of images slightly for better compression (and remove useless top 8 bits!)
13 
14 #define ERROR_PRINTF(...) { fprintf(stderr, "%s:%s:%u Error: ", __FILE__, __PRETTY_FUNCTION__, __LINE__); fprintf(stderr,__VA_ARGS__); fflush(stderr); }
15 
Peek(SDL_Surface * i,int x,int y)16 static int Peek(SDL_Surface* i, int x, int y)
17 {
18 	if (x<0 || y<0 || x>=i->w || y>=i->h)
19 		return 0;
20 	unsigned int p=0;
21 	const int BytesPerPixel = i->format->BytesPerPixel;
22 	const int BitsPerPixel = i->format->BitsPerPixel;
23 	if (BitsPerPixel==8)
24 		p = ((unsigned char*)i->pixels)[i->pitch*y + x*BytesPerPixel];
25 	else if (BitsPerPixel==15 || BitsPerPixel==16)
26 		p = *(short*)(((char*)i->pixels) + (i->pitch*y + x*BytesPerPixel));
27 	else if (BitsPerPixel==32)
28 		p = *(unsigned int*)(((char*)i->pixels) + (i->pitch*y + x*BytesPerPixel));
29 	else if (BitsPerPixel==24)
30 		p = (int)((unsigned char*)i->pixels)[i->pitch*y + x*BytesPerPixel]
31 		  | (int)((unsigned char*)i->pixels)[i->pitch*y + x*BytesPerPixel] << 8
32 		  | (int)((unsigned char*)i->pixels)[i->pitch*y + x*BytesPerPixel] << 16;
33 
34 	return p;
35 }
36 
IsEmpty(SDL_Surface * im,int x,int y,int w,int h)37 static int IsEmpty(SDL_Surface* im, int x, int y, int w, int h)
38 {
39 	int i, j;
40 	for (i=x; i<x+w; i++)
41 		for (j=y; j<y+h; j++)
42 			if (Peek(im,i,j) != Peek(im,0,im->h-1))
43 				return 0;
44 	return 1;
45 }
46 
main(int argc,char ** argv)47 int main(int argc, char** argv)
48 {
49 	typedef unsigned int uint32;
50 	SDL_Surface * g = NULL;
51 	const char *bmp = NULL;
52 	const char *dat = NULL;
53 	int colourKey = 1;
54 
55 	if (argc < 3)
56 	{
57 		fprintf(stderr, "Usage: %s file.bmp file.dat\n", argv[0]);
58 		return -1;
59 	}
60 
61 	bmp = argv[1];
62 	dat = argv[2];
63 
64 	g = SDL_LoadBMP(bmp);
65 
66 //	SDL_PixelFormat p;
67 //	p.sf = 1;
68 //	SDL_Surface* tmp = SDL_ConvertSurface(g, &p, SDL_SWSURFACE);
69 
70 	short w=g->w, h=g->h;
71 	char* buf = (char*) g->pixels;
72 	if (colourKey)
73 	{
74 		while (IsEmpty(g, w-1, 0, 1, h) && w>1)
75 			w--;
76 		while (IsEmpty(g, 0, h-1, w, 1) && h>1)
77 			h--;
78 	}
79 
80 	FILE* f = fopen(dat, "wb");
81 	fwrite(&w, sizeof(w), 1, f);
82 	fwrite(&h, sizeof(h), 1, f);
83 
84 	uint32 mask = IMAGE_DAT_OR_MASK;
85 	int i;
86 	for (i=0; i<(int)w*h; )
87 	{
88 		uint32 c = (*(uint32*)&buf[(i%w)*3 + (i/w)*g->pitch] | mask);
89 		int i0 = i;
90 		while (i < (int)w*h && c == (*(uint32*)&buf[(i%w)*3 + (i/w)*g->pitch] | mask))
91 			i++;
92 		c &= 0xffffff;
93 		i0 = i-i0-1;
94 		if (i0 < 0xff)
95 			c |= i0 << 24;
96 		else
97 			c |= 0xff000000;
98 
99 		fwrite(&c, sizeof(c), 1, f);
100 
101 		if (i0 >= 0xff)
102 			fwrite(&i0, sizeof(i0), 1, f);
103 	}
104 	fclose(f);
105 
106 	SDL_FreeSurface(g);
107 
108 	return 0;
109 }
110