参考
https://www.cnblogs.com/wainiwann/p/7086844.html
bmp.h#ifndef _READ_BMP_H_
#define _READ_BMP_H_
#include <stddef.h>
#include <stdint.h>
typedef struct {
size_t width, height;
uint8_t *data;
} *bmp_t;
bmp_t bmp_init(const char *filename);
void bmp_deinit(bmp_t bmp);
uint32_t bmp_get_pixel(const bmp_t bmp, size_t x, size_t y);
#endif
bmp.c#include "bmp.h"
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#define BI_RGB 0
typedef struct tagBITMAPFILEHEADER {
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
} __attribute__((packed)) BITMAPFILEHEADER,*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER {
uint32_t biSize;
uint32_t biWidth;
uint32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
uint32_t biXPelsPerMeter;
uint32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
} __attribute__((packed)) BITMAPINFOHEADER,*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER;
static bmp_t parse_bmp(uint8_t *base) {
PBITMAPFILEHEADER bfh = (PBITMAPFILEHEADER)base;
PBITMAPINFOHEADER bih = (PBITMAPINFOHEADER)(bfh + 1);
uint8_t *bmp_data = base + bfh->bfOffBits;
if(!(bih->biBitCount == 24 && bih->biCompression == BI_RGB)) return NULL;
bmp_t bmp = malloc(sizeof(*bmp));
if(!bmp) return NULL;
bmp->width = bih->biWidth;
bmp->height = bih->biHeight;
bmp->data = malloc(bmp->width * bmp->height * 4);
if(!bmp->data) {
free(bmp); return NULL;
}
size_t row_size = bmp->width * 3;
row_size = row_size & 0x03 ? (row_size & ~0x03) + 4 : row_size;
uint32_t *dest_pixel = (uint32_t *)bmp->data;
for(size_t h = 0; h < bmp->height; ++h) {
uint8_t *row_base = bmp_data + (bmp->height - h - 1) * row_size;
for(size_t w = 0; w < bmp->width; ++w) {
uint8_t *rgb = row_base + w * 3;
uint32_t src_pixel = rgb[0] | rgb[1] << 8 | rgb[2] << 16;
dest_pixel[h * bmp->width + w] = src_pixel;
}
}
return bmp;
}
bmp_t bmp_init(const char *filename) {
if(!filename) return NULL;
int fd = open(filename, O_RDONLY);
if(fd < 0) return NULL;
struct stat stat_buf;
fstat(fd, &stat_buf);
uint8_t *bmp_file = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if(bmp_file == MAP_FAILED) {
close(fd); return NULL;
}
bmp_t bmp = parse_bmp(bmp_file);
munmap(bmp_file, stat_buf.st_size);
close(fd);
return bmp;
}
void bmp_deinit(bmp_t bmp) {
if(bmp) free(bmp->data);
free(bmp);
}
uint32_t bmp_get_pixel(const bmp_t bmp, size_t x, size_t y) {
if(!(x < bmp->width && y < bmp->height)) return 0;
return ((uint32_t *)bmp->data)[y * bmp->width + x];
}
main.c#include "bmp.h"
#include <SDL.h>
int main(void) {
bmp_t bmp = bmp_init("pic.bmp");
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *win = SDL_CreateWindow("hello world", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, \
bmp->width, bmp->height, SDL_WINDOW_SHOWN);
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
for(size_t h = 0; h < bmp->height; ++h) {
for(size_t w = 0; w < bmp->width; ++w) {
uint32_t pixel = bmp_get_pixel(bmp, w, h);
uint8_t a = (pixel >> 24) & 0xff;
uint8_t r = (pixel >> 16) & 0xff;
uint8_t g = (pixel >> 8) & 0xff;
uint8_t b = (pixel >> 0) & 0xff;
SDL_SetRenderDrawColor(ren, r, g, b, a);
SDL_RenderDrawPoint(ren, w, h);
}
}
SDL_RenderPresent(ren);
SDL_Delay(3000);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
bmp_deinit(bmp);
return 0;
}
|