diff options
Diffstat (limited to 'src/bitmap.c')
-rw-r--r-- | src/bitmap.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/bitmap.c b/src/bitmap.c new file mode 100644 index 0000000..bb88b46 --- /dev/null +++ b/src/bitmap.c @@ -0,0 +1,160 @@ +#include "bitmap.h" + +uint32_t bitmap_flip_byte(unsigned char* _v, int _c) +{ + uint32_t ret = 0; + uint32_t counter = (_c-1) * 8; + + for(int i = 0; i < _c; i++) + { + ret |= (uint32_t)(_v[i] << (counter)); + counter -= 8; + } + + return ret; +}//flip + +struct bitmap_pixel_data bitmap_read(char *_file) +{ + struct bitmap_pixel_data ret; + struct bitmap_file_header header; + + ret.R = ret.G = ret.B = NULL; + ret.error = 1; + + FILE *bitmap = fopen(_file,"rb"); + + if(!bitmap) + return ret; + + header = bitmap_read_file_header(bitmap); + + if(header.error) + return ret; + + if(header.biBitCount != 24) + return ret; + + if(header.biCompression != 0) + return ret; + + ret = bitmap_read_pixel_data(bitmap, header); + + + free(header.tables); + fclose(bitmap); + + ret.error = 0; + return ret; +} + +struct bitmap_file_header bitmap_read_file_header(FILE *_file) +{ + struct bitmap_file_header ret; + unsigned char fileheader[_HEADER_SIZE]; + uint32_t read_counter = 0; + + ret.error = 1; + + size_t tt = fread((void*)&fileheader, sizeof(char), _HEADER_SIZE, _file); + read_counter += _HEADER_SIZE; + + if(!tt) + return ret; + + //Copy file header + ret.bfType = (uint16_t) bitmap_flip_byte(&fileheader[BF_TYPE], sizeof(ret.bfType)); + + if(ret.bfType != (uint16_t)IDENTIFIER) + return ret; + + ret.bfSize = (uint32_t) bitmap_flip_byte(&fileheader[BF_SIZE], sizeof(ret.bfSize)); + ret.bfOffBits = *(uint32_t*) &fileheader[BF_OFF_BITS]; + ret.biSize = *(uint32_t*) &fileheader[BI_SIZE]; + ret.biWidth = *(int32_t*) &fileheader[BI_WIDTH]; + ret.biHeight = *(int32_t*) &fileheader[BI_HEIGHT]; + ret.biBitCount = *(uint16_t*) &fileheader[BI_BIT_COUNT]; + ret.biCompression = (uint32_t) bitmap_flip_byte(&fileheader[BI_COMPRESSION], sizeof(ret.biCompression)); + ret.biSizeImage = *(uint32_t*) &fileheader[BI_SIZE_IMAGE]; + ret.biClrUsed = (uint32_t) bitmap_flip_byte(&fileheader[BI_CLR_USED], sizeof(ret.biClrUsed)); + ret.biClrImportant = (uint32_t) bitmap_flip_byte(&fileheader[BI_CLR_IMPORTANT], sizeof(ret.biClrImportant)); + + + //Read to start of Pixel block + //This block contains Colormasks and Colortables. + ret.tablesc = ret.bfOffBits - read_counter; + ret.tables = malloc(sizeof(char)* ret.tablesc); + fread(ret.tables, sizeof(char), ret.tablesc, _file); + ////////// + + ret.error = 0; + return ret; +} + +struct bitmap_pixel_data bitmap_read_pixel_data(FILE *_file, struct bitmap_file_header _header) +{ + uint32_t **bitmap_buff; + + struct bitmap_pixel_data ret; + + uint32_t row_size = _header.biWidth * 3; + while(row_size%4) + row_size++; + + ret.x = _header.biWidth; + ret.y = _header.biHeight < 0 ? -_header.biHeight: _header.biHeight; + + //If biHeight > 0 Data starts with last row!! + + //Allocate 2D array + //!! + //bitmap_buff indeces are flipped!! [y][x]!!!!! + bitmap_buff = malloc(sizeof(*bitmap_buff) * _header.biHeight); + for(int i = 0; i < ret.y; i++) + { + bitmap_buff[i] = malloc(sizeof(*bitmap_buff[i]) * _header.biWidth); + } + + //Copy Bitmap into bitmap_buff + for(int row = 0; row < _header.biHeight; row++) + { + //printf("Row %i\n", row); + //fread(bitmap_buff[row], sizeof(char), row_size, bitmap); + for(int col = 0; col < _header.biWidth; col++) + fread(&bitmap_buff[row][col], 1, 3, _file); + + for(int i = 0; i < row_size - (_header.biWidth * 3); i++) //read excess NULL-Bytes + fgetc(_file); + } + + ret.x = _header.biWidth; + ret.y = _header.biHeight < 0 ? -_header.biHeight: _header.biHeight; + + ret.R = malloc(sizeof(*ret.R) * ret.x); + ret.G = malloc(sizeof(*ret.G) * ret.x); + ret.B = malloc(sizeof(*ret.B) * ret.x); + for(int i = 0; i < ret.x; i++) + { + ret.R[i] = malloc(sizeof(*ret.R[i]) * ret.y); + ret.G[i] = malloc(sizeof(*ret.G[i]) * ret.y); + ret.B[i] = malloc(sizeof(*ret.B[i]) * ret.y); + } + + for(int y = 0; y < ret.y; y++) + { + for(int x = 0; x < ret.x; x++) + { + int row = _header.biHeight > 0 ? (ret.y - 1) - y : y; + + ret.R[x][y] = (bitmap_buff[row][x] & 0xff0000)>>16; + ret.G[x][y] = (bitmap_buff[row][x] & 0x00ff00)>>8; + ret.B[x][y] = (bitmap_buff[row][x] & 0x0000ff); + } + } + + for(int i = 0; i < ret.y; i++) + free(bitmap_buff[i]); + free(bitmap_buff); + + return ret; +} |