-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbitmap.c
More file actions
133 lines (109 loc) · 4.32 KB
/
bitmap.c
File metadata and controls
133 lines (109 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h> // C99
#include "util.h"
#pragma pack(push,1)
/* Windows 3.x bitmap file header */
typedef struct {
char filetype[2]; /* magic - always 'B' 'M' */
unsigned int filesize;
short reserved1;
short reserved2;
unsigned int dataoffset; /* offset in bytes to actual bitmap data */
} file_header_t;
/* Windows 3.x bitmap full header, including file header */
typedef struct {
file_header_t fileheader;
unsigned int headersize;
int width;
int height;
short planes;
short bitsperpixel; /* we only support the value 24 here */
unsigned int compression; /* we do not support compression */
unsigned int bitmapsize;
int horizontalres;
int verticalres;
unsigned int numcolors;
unsigned int importantcolors;
} bitmap_header_t;
#pragma pack(pop)
typedef struct bitmap{
int width;
int height;
bool* bits;
} bitmap_t;
// and all the file ops return sensible amounts
bitmap_t* load_resource(char* filepath){
// Open the file
FILE * fp = fopen(filepath, "rb");
if(!fp) fail("Cannot open file %s\n", filepath);
// Alloc and then read into the header format
bitmap_header_t* head = malloc(sizeof(bitmap_header_t));
if(!head) fail("Cannot allocate memory for bitmap (%s)\n", filepath);
if(!fread(head, sizeof(bitmap_header_t), 1, fp)) fail("Cannot load bitmap header %s\n", filepath);
if(head->fileheader.filetype[0] != 'B' || head->fileheader.filetype[1] != 'M') fail("File is not a bitmap: %s\n", filepath);
// Read image data
fseek(fp, sizeof(char) * head->fileheader.dataoffset, SEEK_SET);
unsigned char* data = calloc(head->bitmapsize, sizeof(unsigned char));
if(!head) fail("Cannot allocate memory for bitmap (%s)\n", filepath);
if(!fread(data, sizeof(char), head->bitmapsize, fp)) fail("Cannot read bitmap %s\n", filepath);
// Check bitmap properties
// if(!(head->bitsperpixel == 24 &&
// head->compression == 0 &&
// head->width == head->height )){ ... STUFF ... }
/* printf("dim: %dx%d, bpp: %d compression: %d\n", head->width, head->height, head->bitsperpixel, head->compression); */
/* printf("Offset: %d", head->fileheader.dataoffset); */
/* printf("len: %d vs. %d\n", head->bitmapsize, (head->width * head->height * head->bitsperpixel) / sizeof(char)); */
if(head->width != head->height) fail("Bitmap must be square (%s)\n", filepath);
if(head->compression != 0) fail("Bitmap must be uncompressed (%s)\n", filepath);
if(head->bitsperpixel != 24) fail("Bitmap must 24 bits-per-pixel (%s)\n", filepath);
// Create some space...
bitmap_t* new = malloc(sizeof(bitmap_t));
if(!new) fail("Cannot construct new bitmap (%s)\n", filepath);
new->bits = calloc(head->bitmapsize / 3, sizeof(bool)); // probably not an issue, but
// on most systems this is wasteful of memory.
// Load data by seeing what is over or under 128 in one channel.
// This presumes there's 24BPP, and ignores many channels.
bool* bit_ptr = new->bits;
for(int i=0; i<head->bitmapsize; i+=3){
(*bit_ptr) = ((data[i] > 128) ? true : false);
bit_ptr++;
}
new->width = head->width;
new->height = head->height;
return new;
}
// Free the memory used by a bitmap
void free_bmp(bitmap_t* bmp){
free(bmp->bits);
free(bmp);
}
// Allocates a new bitmap
bitmap_t* new_bmp(int w, int h){
bitmap_t* new = malloc(sizeof(bitmap_t));
// Set things
new->width = w;
new->height = h;
new->bits = calloc( w * h, sizeof(bool));
return new;
}
// Get a pixel from the bitmap
bool bmp_get(bitmap_t* bmp, int x, int y){
return bmp->bits[ bmp->width * y + x ];
}
// Put a pixel into the bitmap
void bmp_put(bitmap_t* bmp, int x, int y, bool val){
bmp->bits[ bmp->width * y + x ] = val;
}
// Draw a bitmap to screen, for debug purposes
/* void debug_draw_bmp(bitmap_t* bmp){ */
/* */
/* for(int i=0; i<bmp->width; i++){ */
/* for(int j=0; j<bmp->height; j++){ */
/* if(bmp->bits[i]) printf("#"); */
/* else printf(" "); */
/* } */
/* printf("\n"); */
/* } */
/* */
/* } */