AceInfinity
Emeritus, Contributor
I understand that this can be done by finding the fixed offset of the image data through stream seek functions, and then read into a byte array, and removing all the padding from there, but this is more of an introduction code to a side project I have, so I have the full structures in place for future things.
This example code will read an uncompressed (non RLE-encoded) 24-bit BMP and output the raw image data in BGR format in a similar hex table format to stdout along with some other information parsed from the information header. With some modification you can write this data to a file...
I take the raw data and remove all of the bitmap padding until I get an array of BGR structs. This will enable me to re-write the bitmap into different dimensions while maintaining the image size (in terms of # of pixels) if I wanted.
I really want to use this and combine it with an algorithm for sharp and clean upscaling -- for higher resolutions. I still have to implement an algorithm for this but I have something in my head currently to do this.
Anyways here's the code. Thought I'd post it to help others out. Compiled with GCC:
ANSI C (C89) standard compliant code :thumbsup2:
This example code will read an uncompressed (non RLE-encoded) 24-bit BMP and output the raw image data in BGR format in a similar hex table format to stdout along with some other information parsed from the information header. With some modification you can write this data to a file...
I take the raw data and remove all of the bitmap padding until I get an array of BGR structs. This will enable me to re-write the bitmap into different dimensions while maintaining the image size (in terms of # of pixels) if I wanted.
I really want to use this and combine it with an algorithm for sharp and clean upscaling -- for higher resolutions. I still have to implement an algorithm for this but I have something in my head currently to do this.
Anyways here's the code. Thought I'd post it to help others out. Compiled with GCC:
Code:
[NO-PARSE]#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define OFFSET_HEX_FMT "%.8X | "
#pragma pack(1)
typedef struct
{
/* 0x00 */ short signature; /* BMP signature (must be 0x4D42) */
/* 0x02 */ int filesize; /* BMP filesize - unreliable */
/* 0x06 */ short reserved_1; /* reserved (must be 0) */
/* 0x08 */ short reserved_2; /* reserved (must be 0) */
/* 0x0A */ int image_offset; /* offset of image data (in bytes) */
} BMP_HEADER;
#pragma pack(1)
typedef struct
{
/* 0x0E */ int size; /* sizeof BMPINFOHEADER (40) */
/* 0x12 */ int img_width; /* image width */
/* 0x16 */ int img_height; /* image height */
/* 0x1A */ short planes; /* number of image planes (1) */
/* 0x1C */ short bits; /* bits per pixel (1, 4, 8, or 24) */
/* 0x1E */ int compression; /* compression type (0 = none, 1 = RLE-8, 2 = RLE-4) */
/* 0x22 */ int img_size; /* sizeof image data in bytes (including padding) */
/* 0x26 */ int horizontal_resolution; /* horizontal resolution (pixels per meter) - unreliable */
/* 0x2A */ int vertical_resolution; /* vertical resolution (pixels per meter) - unreliable */
/* 0x2E */ int bgr_colors; /* number of bgr_colors in image (or zero) */
/* 0x32 */ int important_bgr_colors; /* number of important bgr_colors (or zero) */
} BMP_INFO_HEADER;
typedef struct
{
unsigned char blue;
unsigned char green;
unsigned char red;
} BGR;
int main(void)
{
int ret = 0;
int i, offset, num_pixels, pad_len;
unsigned char *raw_data = NULL;
BGR *bgr_colors = NULL;
BMP_HEADER header = { 0 };
BMP_INFO_HEADER info_header = { 0 };
FILE *fp = fopen("untitled.bmp", "rb");
if (!fp)
{
ret = -1;
goto end;
}
fread(&header, 1, sizeof(BMP_HEADER), fp);
fread(&info_header, 1, sizeof(BMP_INFO_HEADER), fp);
if (info_header.bits != 24)
{
fputs("Error: Not a 24bit bitmap.\n", stderr);
ret = -1;
goto end;
}
printf("Image dimensions: %d x %d\n", info_header.img_width, info_header.img_height);
printf("Image size: %d bytes\n", info_header.img_size);
fputs("\n", stdout);
/* -----------------------------------
* Read RAW image data from file
* ----------------------------------- */
raw_data = malloc(info_header.img_size);
fread(raw_data, 1, info_header.img_size, fp);
/* ----------------------------------------------------
* Copy pixel data to BGR array (without padding)
* ---------------------------------------------------- */
pad_len = info_header.img_width % 4;
num_pixels = info_header.img_size / 3;
bgr_colors = malloc(sizeof(BGR) * num_pixels);
for (i = 0; i < num_pixels; ++i)
{
memcpy(&bgr_colors[i],
(raw_data + i) + (pad_len * (i / info_header.img_width)),
sizeof(BGR));
}
/* ------------------------------
* Display RAW image data
* ------------------------------ */
offset = 0;
printf("RAW Image Data:\n");
printf("%*c00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n", 11, ' ');
printf("%*c-----------------------------------------------\n", 11, ' ');
printf(OFFSET_HEX_FMT, offset);
for (i = 0; i < info_header.img_size; ++i)
{
printf("%.2X ", raw_data[i]);
if ((i + 1) % 16 == 0)
{
fputs("\n", stdout);
printf(OFFSET_HEX_FMT, (offset += 16));
}
}
/*for (i = 0; i < num_pixels; ++i)
{
printf("%.2X %.2X %.2X ",
bgr_colors[i].blue,
bgr_colors[i].green,
bgr_colors[i].red);
}*/
end:
if (fp) fclose(fp);
if (raw_data) free(raw_data);
if (bgr_colors) free(bgr_colors);
exit(ret);
}[/NO-PARSE]
ANSI C (C89) standard compliant code :thumbsup2:
Last edited: