#include #include #include #include typedef unsigned char uch; // 檔案結構 #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() //辅助计算函数 float linear_single(float x, float x1, float x2, float f1, float f2){ return floor(f1 * (x2 - x) / (x2 - x1) + f2 * (x - x1) / (x2 - x1)); } void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t height, uint32_t bits, float radio_w, float radio_h){ if(!(name && raw_img)){ perror("Error bmpWrite."); return; } // 檔案資訊 struct BmpFileHeader file_h = { .bfTybe=0x4d42, .bfReserved1=0, .bfReserved2=0, .bfOffBits=54, }; uint32_t new_width = floor(width*radio_w); uint32_t new_height = floor(height*radio_h); file_h.bfSize = file_h.bfOffBits + new_width*new_height * bits/8; if(bits==8) {file_h.bfSize+= 1024, file_h.bfOffBits+= 1024;} // 圖片資訊 struct BmpInfoHeader info_h = { .biSize=40, .biPlanes=1, .biCompression=0, .biXPelsPerMeter=0, .biYPelsPerMeter=0, .biClrUsed=0, .biClrImportant=0, }; info_h.biWidth = new_width; info_h.biHeight = new_height; info_h.biBitCount = bits;// 多少位的圖 info_h.biSizeImage = new_width*new_height * bits/8; if(bits == 8) {info_h.biClrUsed=256;} // 寫入檔頭 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); // 寫調色盤 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); } } // char newpixels[new_width*new_height]; unsigned char **newpixels=(unsigned char**)malloc(new_width*new_height*3); // 寫入圖片資訊 size_t alig = ((new_width*bits/8)*3) % 4; for(int j = new_height-1; j >= 0; --j) { for(unsigned i = 0; i < new_width; ++i) { uint32_t idx = j*new_width +i; if(bits == 24) { // RGB圖片 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) { // 灰階圖 fwrite((char*)&raw_img[idx], sizeof(char), sizeof(uch), pFile); } } // 對齊4byte for(size_t i = 0; i < alig; ++i) { fwrite("", sizeof(char), sizeof(uch), pFile); } } fclose(pFile); free(newpixels); //記得釋放空間 } 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; } // 檔案資訊 struct BmpFileHeader file_h; // 圖片資訊 struct BmpInfoHeader info_h; // 讀取檔頭 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); // 讀取長寬 *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)); // 讀取讀片資訊轉RAW檔資訊 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圖片 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) { // 灰階圖 fread((char*)&(*raw_img)[idx], sizeof(char), sizeof(uch), pFile); } } fseek(pFile , (long)alig , SEEK_CUR); } fclose(pFile); } // 圖像結構 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, float radio_w, float radio_h) { const Imgraw* p = _this; bmpWrite(name, p->data, p->width, p->height, p->bits, radio_w, radio_h); } /*==============================================================*/ int main(int argc, char const *argv[]) { float radio_w, radio_h; printf("Enter a radio of width :") ; scanf("%f", &radio_w); printf("Enter a radio of height :") ; scanf("%f", &radio_h); printf("%f :: %f\n", radio_w, radio_h); // 建構 Imgraw img = {0, 0, 0, NULL}; // 讀圖 Imgraw_Read(&img, "./input/bw2x3.bmp"); // 寫圖 Imgraw_Writ(&img, "./output/bw2x3(output).bmp", radio_w, radio_h); return 0; } /*==============================================================*/