diff options
Diffstat (limited to 'src/bmp.c')
-rw-r--r-- | src/bmp.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/bmp.c b/src/bmp.c new file mode 100644 index 0000000..9f79a9f --- /dev/null +++ b/src/bmp.c @@ -0,0 +1,111 @@ + +#include <stdio.h> +#include <stdlib.h> + +#include "meh.h" + +unsigned short getshort(FILE *f){ + unsigned short ret; + ret = getc(f); + ret = ret | (getc(f) << 8); + return ret; +} + +unsigned long getlong(FILE *f){ + unsigned short ret; + ret = getc(f); + ret = ret | (getc(f) << 8); + ret = ret | (getc(f) << 16); + ret = ret | (getc(f) << 24); + return ret; +} + +struct rgb_t{ + unsigned char r, g, b; +}; + +struct bmp_t{ + struct image img; + unsigned long bitmapoffset; + int bpp; + int ncolors; + struct rgb_t *colours; +}; + +struct image *bmp_open(FILE *f){ + struct bmp_t *b; + unsigned long headerend; + + rewind(f); + if(getc(f) != 'B' || getc(f) != 'M') + return NULL; + + b = malloc(sizeof(struct bmp_t)); + b->img.f = f; + + fseek(f, 10, SEEK_SET); + b->bitmapoffset = getlong(f); + + fseek(f, 18, SEEK_SET); + b->img.width = getlong(f); + b->img.height = getlong(f); + + fseek(f, 14, SEEK_SET); + headerend = 14 + getlong(f); + + fseek(f, 28, SEEK_SET); + b->bpp = getshort(f); + + if(b->bpp == 24){ + b->ncolors = 0; + }else{ + int i; + fseek(f, 46, SEEK_SET); + if(!(b->ncolors = getlong(f))){ + b->ncolors = 1 << b->bpp; + } + + b->colours = malloc(b->ncolors * sizeof(struct rgb_t)); + fseek(f, headerend, SEEK_SET); + for(i = 0; i < b->ncolors; i++){ + b->colours[i].b = getc(f); + b->colours[i].g = getc(f); + b->colours[i].r = getc(f); + } + } + + return (struct image *)b; +} + +int bmp_read(struct image *img){ + struct bmp_t *b = (struct bmp_t *)img; + FILE *f = img->f; + + fseek(f, b->bitmapoffset, SEEK_SET); + if(b->bpp == 24){ + int i, x, y; + int row = img->width * 3; + i = img->height * row; + for(y = img->height; y; y--){ + i -= row; + for(x = 0; x < img->width * 3; x+=3){ + img->buf[i + x + 2] = getc(f); + img->buf[i + x + 1] = getc(f); + img->buf[i + x + 0] = getc(f); + } + if(x & 3){ + fseek(f, 4 - (x & 3), SEEK_CUR); + } + } + }else{ + //TODO + } + + return 0; +} + +struct imageformat gif = { + bmp_open, + bmp_read +}; + |