This commit is contained in:
SunnyGor 2023-01-08 12:53:33 +08:00
commit 05dfcbf7b5
9 changed files with 225 additions and 0 deletions

175
bmp.c Normal file
View File

@ -0,0 +1,175 @@
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
typedef unsigned char uch;
// ™n°¸½Y˜
#pragma pack(2)
struct BmpFileHeader {
uint16_t bfTybe;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
};
struct BmpInfoHeader {
uint32_t biSize;
uint32_t biWidth;
uint32_t biHeight;
uint16_t biPlanes; // 1=defeaul, 0=custom
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
uint32_t biXPelsPerMeter; // 72dpi=2835, 96dpi=3780
uint32_t biYPelsPerMeter; // 120dpi=4724, 300dpi=11811
uint32_t biClrUsed;
uint32_t biClrImportant;
};
#pragma pack()
void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t height, uint16_t bits)
{
if(!(name && raw_img)) {
perror("Error bmpWrite.");
return;
}
// ™n°¸ÙYÓ<59>
struct BmpFileHeader file_h = {
.bfTybe=0x4d42,
.bfReserved1=0,
.bfReserved2=0,
.bfOffBits=54,
};
file_h.bfSize = file_h.bfOffBits + width*height * bits/8;
if(bits==8) {file_h.bfSize+= 1024, file_h.bfOffBits+= 1024;}
// ˆDƬÙYÓ<59>
struct BmpInfoHeader info_h = {
.biSize=40,
.biPlanes=1,
.biCompression=0,
.biXPelsPerMeter=0,
.biYPelsPerMeter=0,
.biClrUsed=0,
.biClrImportant=0,
};
info_h.biWidth = width;
info_h.biHeight = height;
info_h.biBitCount = bits;
info_h.biSizeImage = width*height * bits/8;
if(bits == 8) {info_h.biClrUsed=256;}
// ŒÈë™nî^
FILE *pFile = NULL;
// pFile = fopen(name,"wb+");
fopen_s(&pFile, name,"wb+");
if(!pFile) {
perror("Error opening file.");
return;
}
fwrite((char*)&file_h, sizeof(char), sizeof(file_h), pFile);
fwrite((char*)&info_h, sizeof(char), sizeof(info_h), pFile);
// Œ‘Õ{É«±P
if(bits == 8) {
for(unsigned i = 0; i < 256; ++i) {
uch c = i;
fwrite((char*)&c, sizeof(char), sizeof(uch), pFile);
fwrite((char*)&c, sizeof(char), sizeof(uch), pFile);
fwrite((char*)&c, sizeof(char), sizeof(uch), pFile);
fwrite("", sizeof(char), sizeof(uch), pFile);
}
}
// ŒÈëˆDƬÙYÓ<59>
size_t alig = ((width*bits/8)*3) % 4;
for(int j = height-1; j >= 0; --j) {
for(unsigned i = 0; i < width; ++i) {
uint32_t idx = j*width +i;
if(bits == 24) { // RGBˆDƬ
fwrite((char*)&raw_img[idx*3 +2], sizeof(char), sizeof(uch), pFile);
fwrite((char*)&raw_img[idx*3 +1], sizeof(char), sizeof(uch), pFile);
fwrite((char*)&raw_img[idx*3 +0], sizeof(char), sizeof(uch), pFile);
}
else if(bits == 8) { // »ÒëAˆD
fwrite((char*)&raw_img[idx], sizeof(char), sizeof(uch), pFile);
}
}
// Œ¦ýR4byte
for(size_t i = 0; i < alig; ++i) {
fwrite("", sizeof(char), sizeof(uch), pFile);
}
}
fclose(pFile);
}
void bmpRead(const char* name, uch** raw_img, uint32_t* width, uint32_t* height, uint16_t* bits)
{
if(!(name && raw_img && width && height && bits)) {
perror("Error bmpRead.");
return;
}
// ™n°¸ÙYÓ<59>
struct BmpFileHeader file_h;
// ˆDƬÙYÓ<59>
struct BmpInfoHeader info_h;
// ×xÈ¡™nî^
FILE *pFile = NULL;
// pFile = fopen(name, "rb+");
fopen_s(&pFile, name, "rb+");
if(!pFile) {
perror("Error opening file.");
return;
}
fread((char*)&file_h, sizeof(char), sizeof(file_h), pFile);
fread((char*)&info_h, sizeof(char), sizeof(info_h), pFile);
// ×xÈ¡éLŒ
*width = info_h.biWidth;
*height = info_h.biHeight;
*bits = info_h.biBitCount;
size_t ImgSize = ((size_t)*width) * ((size_t)*height) * 3;
*raw_img = (uch*)calloc(ImgSize, sizeof(uch));
// ×xÈ¡×xƬÙYÓ<59>ÞDRAW™nÙYÓ<59>
fseek(pFile, file_h.bfOffBits, SEEK_SET);
size_t alig = ((info_h.biWidth*info_h.biBitCount/8)*3) % 4;
for(int j = *height-1; j >= 0; --j) {
for(unsigned i = 0; i < *width; ++i) {
uint32_t idx = j*(*width)+i;
if(*bits == 24) { // RGBˆDƬ
fread((char*)&(*raw_img)[idx*3 +2],
sizeof(char), sizeof(uch), pFile);
fread((char*)&(*raw_img)[idx*3 +1],
sizeof(char), sizeof(uch), pFile);
fread((char*)&(*raw_img)[idx*3 +0],
sizeof(char), sizeof(uch), pFile);
} else if(*bits == 8) { // »ÒëAˆD
fread((char*)&(*raw_img)[idx],
sizeof(char), sizeof(uch), pFile);
}
}
fseek(pFile , (long)alig , SEEK_CUR);
}
fclose(pFile);
}
// ˆDÏñ½Y˜
typedef struct Imgraw {
uint32_t width, height;
uint16_t bits;
uch* data;
} Imgraw;
void Imgraw_Read(const Imgraw* _this, const char* name) {
const Imgraw* p = _this;
bmpRead(name, &p->data, &p->width, &p->height, &p->bits);
}
void Imgraw_Writ(const Imgraw* _this, const char* name) {
const Imgraw* p = _this;
bmpWrite(name, p->data, p->width, p->height, p->bits);
}
/*==============================================================*/
int main(int argc, char const *argv[]) {
// ½¨˜‹
Imgraw img = {0, 0, 0, NULL};
// ×xˆD
Imgraw_Read(&img, "./input/bw2x1.bmp");
// ŒˆD
Imgraw_Writ(&img, "./output/bw2x1(output).bmp");
return 0;
}
/*==============================================================*/

BIN
bmp.exe Normal file

Binary file not shown.

50
bmp.h Normal file
View File

@ -0,0 +1,50 @@
// BMP-related data types based on Microsoft's own
#include <stdint.h>
// aliases for C/C++ primitive data types
// https://msdn.microsoft.com/en-us/library/cc230309.aspx
typedef uint8_t BYTE;
typedef uint32_t DWORD;
typedef int32_t LONG;
typedef uint16_t WORD;
// information about the type, size, and layout of a file
// https://msdn.microsoft.com/en-us/library/dd183374(v=vs.85).aspx
typedef struct
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} __attribute__((__packed__))
BITMAPFILEHEADER;
// information about the dimensions and color format
// https://msdn.microsoft.com/en-us/library/dd183376(v=vs.85).aspx
typedef struct
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} __attribute__((__packed__))
BITMAPINFOHEADER;
// relative intensities of red, green, and blue
// https://msdn.microsoft.com/en-us/library/dd162939(v=vs.85).aspx
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;

BIN
input/bw2x1.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 B

BIN
input/bw2x3.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 B

BIN
input/hello.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

BIN
output/bw2x1(output).bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 B

BIN
output/bw2x3(output).bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 B

BIN
output/hello(output).bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB