diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..b4250d8 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,20 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "compilerPath": "C:\\MinGW\\bin\\gcc.exe", + "cStandard": "c11", + "cppStandard": "gnu++14", + "intelliSenseMode": "windows-gcc-x86" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f9e65c2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,46 @@ +{ + "files.associations": { + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "random": "cpp", + "string": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp" + } +} \ No newline at end of file diff --git a/bmp.exe b/bmp.exe deleted file mode 100644 index 8a88592..0000000 Binary files a/bmp.exe and /dev/null differ diff --git a/bmp_copy_demo.c b/bmp_copy_demo.c index 048bdf4..e98aefb 100644 --- a/bmp_copy_demo.c +++ b/bmp_copy_demo.c @@ -85,15 +85,11 @@ void bmpWrite(const char* name, const uch* raw_img, for(unsigned i = 0; i < width; ++i) { uint32_t idx = j*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); + 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); + fwrite((char*)&raw_img[idx], sizeof(char), sizeof(uch), pFile); } } // 對齊4byte @@ -137,15 +133,11 @@ void bmpRead(const char* name, uch** raw_img, 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); + 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); + fread((char*)&(*raw_img)[idx], sizeof(char), sizeof(uch), pFile); } } fseek(pFile , (long)alig , SEEK_CUR); diff --git a/bmp_copy_demo.exe b/bmp_copy_demo.exe deleted file mode 100644 index 82909f2..0000000 Binary files a/bmp_copy_demo.exe and /dev/null differ diff --git a/idk.c b/idk.c new file mode 100644 index 0000000..eaae38d --- /dev/null +++ b/idk.c @@ -0,0 +1,181 @@ +#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() + + +void bmpWrite(const char* name, const uch* raw_img, + uint32_t width, uint32_t height, uint16_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 = width*radio_w; + uint32_t new_height = 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); + } + } + // 寫入圖片資訊 + size_t alig = ((new_width*bits/8)*3) % 4; + for(int j = 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); +} +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", radio_w, radio_h); + + // 建構 + Imgraw img = {0, 0, 0, NULL}; + // 讀圖 + Imgraw_Read(&img, "./input/bw2x1.bmp"); + // 寫圖 + Imgraw_Writ(&img, "./output/bw2x1(output).bmp", radio_w, radio_h); + return 0; +} +/*==============================================================*/ \ No newline at end of file diff --git a/input/hello.bmp b/input/hello.bmp index ea7d688..7c6eeea 100644 Binary files a/input/hello.bmp and b/input/hello.bmp differ diff --git a/output/hello(output).bmp b/output/hello(output).bmp index 78f9524..dfd4367 100644 Binary files a/output/hello(output).bmp and b/output/hello(output).bmp differ diff --git a/output/rotate90N.bmp b/output/rotate90N.bmp new file mode 100644 index 0000000..c09f6be Binary files /dev/null and b/output/rotate90N.bmp differ diff --git a/test.cpp b/test.cpp deleted file mode 100644 index 6842b73..0000000 --- a/test.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include -#include -#include -#pragma pack(1)//必须在结构体定义之前使用,这是为了让结构体中各成员按1字节对齐 -// 文件头结构体 -typedef struct tagBITMAPFILEHEADER { - unsigned short bfType; // 保存图片类型,读取时需要注释掉,文本标识符只能单独进行读写 2 - unsigned long bfSize; // 文件大小 4 - unsigned short bfReserved1; // 保留,设置为0 2 - unsigned short bfReserved2; // 保留,设置为0 2 - unsigned long bfOffBits; // 从文件头到实际的图像数据之间的字节的偏移量(没调色板的话是54) 4 -} BITMAPFILEHEADER; - -//图像信息头结构体 -typedef struct tagBITMAPINFOHEADER { - unsigned long biSize; // 此结构体的大小 - unsigned long biWidth; // 图像的宽 - unsigned long biHeight; // 图像的高 - unsigned short biPlanes; // 颜色平面数 恒为1 - unsigned short biBitCount; // 一像素所占的位数 Windows系统有8,16,24 - unsigned long biCompression; // 说明图象数据压缩的类型,0为不压缩 - unsigned long biSizeImage; // 图像大小, 值等于上面文件头结构中bfSize-bfOffBits - unsigned long biXPelsPerMeter; // 说明水平分辨率,用像素/米表示 一般为0 - unsigned long biYPelsPerMeter; // 说明垂直分辨率,用像素/米表示 一般为0 - unsigned long biClrUsed; // 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项) - unsigned long biClrImportant; // 说明对图象显示有重要影响的颜色索引的数目 如果是0表示都重要 -} BITMAPINFOHEADER; - -void changeBmpFile(const char *src, const char *dest, double proportion) { //源文件名,目标文件名,放大或缩小比例 - //1.源位图文件文件头和信息头 - BITMAPFILEHEADER src_fileHeader; - BITMAPINFOHEADER src_infoHeader; - - //2.目标位图文件文件头和信息头 - BITMAPFILEHEADER dest_fileHeader; - BITMAPINFOHEADER dest_infoHeader; - - //3.源位图文件对象&目标位图文件对象 - FILE *src_file; - FILE *dest_file; - - //4.源位图文件以读取(允许读和写)模式打开&目标位图文件以写入(只允许写)模式打开 - src_file = fopen(src,"rb+"); - dest_file = fopen(dest,"wb+"); - if(src_file == NULL || dest_file == NULL) { - printf("文件打开失败,程序结束...\n"); - exit(-1); - } - - //5.读取源位图文件的标识符信息&文件头&信息头 -// unsigned short fileIdentifier; -// fread(&fileIdentifier, sizeof(unsigned short), 1, src_file); - fread(&src_fileHeader, sizeof(BITMAPFILEHEADER), 1, src_file); - fread(&src_infoHeader, sizeof(BITMAPINFOHEADER), 1, src_file); - - //6.一个位图文件的像素占据的内存空间 = 位数 ? 8,例如24位图一个像素占据3字节内存 - int byte = src_infoHeader.biBitCount / 8;//表示每个像素由几个字节表示,对于24位位图文件来说,byte值为3 - - //7.获取源位图文件和目标位图文件的长宽(以像素为单位)以及尺寸(位图文件图像数据的字节大小) - unsigned long oldWidth, oldHeight, oldSize, newWidth, newHeight, newSize; - - oldWidth = src_infoHeader.biWidth; - oldHeight = src_infoHeader.biHeight; - newWidth = ((int)(src_infoHeader.biWidth * proportion) + 3) / 4 * 4;//图像显示不出来原因在于图像长或宽不是4的倍数 下面这一步可以保证得到的宽高是4的倍数 - newHeight = ((int)(src_infoHeader.biHeight * proportion) + 3) / 4 * 4; - printf("源位图文件高为:%d\n", oldHeight); - printf("源位图文件宽为:%d\n", oldWidth); - printf("目标位图文件高为:%d\n", newHeight); - printf("目标位图文件宽为:%d\n", newWidth); - - oldSize = oldWidth * oldHeight * byte; - newSize = newWidth * newHeight * byte; - - //8.sourceData是一个指针,指向源位图文件的图像存储数据 - unsigned char *sourceData = (unsigned char*)malloc(oldSize);//该指针指向源位图文件图像数据的内存空间 - fseek(src_file, 54, SEEK_SET);//使文件的指针指向文件的第55个字节 - fread(sourceData, oldSize, 1, src_file);//将src_file中的图像数据存储到sourceData指向的内存空间 - - //9.目标位图文件文件头和信息头内容的更改 - dest_fileHeader = src_fileHeader; - dest_infoHeader = src_infoHeader; - - dest_fileHeader.bfSize = 54 + newSize; - - dest_infoHeader.biWidth = newWidth; - dest_infoHeader.biHeight = newHeight; - dest_infoHeader.biSizeImage = newSize; - -// fwrite(&fileIdentifier, sizeof(unsigned short), 1, dest_file); - fwrite(&dest_fileHeader, sizeof(BITMAPFILEHEADER), 1, dest_file); - fwrite(&dest_infoHeader, sizeof(BITMAPINFOHEADER), 1, dest_file); - - //10.使用最邻近插值算法进行图片缩放 - unsigned int x,y,X,Y;//源位图文件像素点宽高和目标位图文件像素点宽高 - unsigned char *destData = (unsigned char*)malloc(newSize);//该指针指向目标位图文件图像数据的内存空间 - unsigned char *sourceWhere, *destWhere;//修改像素的对应位置 - for(Y = 0; Y < newHeight; Y++) { - y = Y / proportion; - destWhere = destData + Y * newWidth * byte; - sourceWhere = sourceData + y * oldWidth * byte; - for(X = 0; X < newWidth; X++) { - x = X / proportion; - memcpy(destWhere + X * byte, sourceWhere + x * byte, byte); - } - } - - //11.写入数据并且释放内存&关闭文件流 - fwrite(destData, newSize, 1, dest_file); - free(destData); - free(sourceData); - fclose(src_file); - fclose(dest_file); -} - -int main(int argc,char *argv[]) { - printf("******位图文件压缩程序******\n"); - - // if(argc >= 4) { - // changeBmpFile(argv[1],argv[3],atoi(argv[2]) / 100.0); - // printf("缩放成功!\n"); - - changeBmpFile("./input/hello.bmp","./output/test(output).bmp",100.0 / 100.0); - printf("缩放成功!\n"); - // } else if(argc == 1){ - // printf("未传入参数,需要在控制台进行位图文件的压缩!!!"); - // return 0; - // }else { - // printf("参数不足 ,程序结束...\n"); - // exit(-1); - // } - - return 0; -} diff --git a/test.exe b/test.exe deleted file mode 100644 index ba55ee3..0000000 Binary files a/test.exe and /dev/null differ diff --git a/bmp.c b/transfer.c similarity index 59% rename from bmp.c rename to transfer.c index d0735d3..05141e0 100644 --- a/bmp.c +++ b/transfer.c @@ -1,8 +1,10 @@ #include #include #include +#include typedef unsigned char uch; + // 檔案結構 #pragma pack(2) struct BmpFileHeader { @@ -27,21 +29,16 @@ struct BmpInfoHeader { }; #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, uint16_t bits, const char* old_name, double radio) -{ - if(!(name && raw_img)) { +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; } - - unsigned long oldWidth, oldHeight, oldSize, newWidth, newHeight, newSize; - oldWidth = width; - oldHeight = height; - - newWidth = ((int)(oldWidth * radio) + 3) / 4 * 4;//图像显示不出来原因在于图像长或宽不是4的倍数 保证得到的宽高是4的倍数 - newHeight = ((int)(oldHeight * radio) + 3) / 4 * 4; - // 檔案資訊 struct BmpFileHeader file_h = { .bfTybe=0x4d42, @@ -49,8 +46,13 @@ void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t hei .bfReserved2=0, .bfOffBits=54, }; - file_h.bfSize = file_h.bfOffBits + newWidth*newHeight * bits/8; + + 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, @@ -61,10 +63,10 @@ void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t hei .biClrUsed=0, .biClrImportant=0, }; - info_h.biWidth = newWidth; - info_h.biHeight = newHeight; - info_h.biBitCount = bits; - info_h.biSizeImage = newWidth*newHeight * bits/8; + 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; @@ -86,43 +88,20 @@ void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t hei 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 = ((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; + 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); - - // unsigned long oldWidth, oldHeight, oldSize, newWidth, newHeight, newSize; - - // oldWidth = width; - // oldHeight = height; - unsigned char *sourceData = (unsigned char*)malloc(oldSize);//该指针指向源位图文件图像数据的内存空间 - fseek(old_name, 54, SEEK_SET);//使文件的指针指向文件的第55个字节 - fread(sourceData, oldSize, 1, old_name);//将src_file中的图像数据存储到sourceData指向的内存空间 - - // newWidth = ((int)(oldWidth * radio) + 3) / 4 * 4;//图像显示不出来原因在于图像长或宽不是4的倍数 下面这一步可以保证得到的宽高是4的倍数 - // newHeight = ((int)(oldHeight * radio) + 3) / 4 * 4; - - //10.使用最邻近插值算法进行图片缩放 - unsigned int x,y,X,Y;//源位图文件像素点宽高和目标位图文件像素点宽高 - unsigned char *destData = (unsigned char*)malloc(newSize);//该指针指向目标位图文件图像数据的内存空间 - unsigned char *sourceWhere, *destWhere;//修改像素的对应位置 - for(Y = 0; Y < newHeight; Y++) { - y = Y / radio; - destWhere = destData + Y * newWidth * 3; - sourceWhere = sourceData + y * oldWidth * 3; - for(X = 0; X < newWidth; X++) { - x = X / radio; - memcpy(destWhere + X * 3, sourceWhere + x * 3, 3); - } - } - - } - else if(bits == 8) { // 灰階圖 + } else if(bits == 8) { // 灰階圖 fwrite((char*)&raw_img[idx], sizeof(char), sizeof(uch), pFile); } } @@ -132,6 +111,8 @@ void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t hei } } fclose(pFile); + + free(newpixels); //記得釋放空間 } void bmpRead(const char* name, uch** raw_img, uint32_t* width, uint32_t* height, uint16_t* bits) { @@ -166,15 +147,11 @@ void bmpRead(const char* name, uch** raw_img, uint32_t* width, uint32_t* height, 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); + 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); + fread((char*)&(*raw_img)[idx], sizeof(char), sizeof(uch), pFile); } } fseek(pFile , (long)alig , SEEK_CUR); @@ -188,22 +165,29 @@ typedef struct Imgraw { 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 char* old_name) { +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, old_name, 1.0); + 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/bw2x1.bmp"); + Imgraw_Read(&img, "./input/bw2x3.bmp"); // 寫圖 - Imgraw_Writ(&img, "./output/bw2x1(output).bmp", "./input/bw2x1.bmp"); + Imgraw_Writ(&img, "./output/bw2x3(output).bmp", radio_w, radio_h); return 0; } /*==============================================================*/ \ No newline at end of file diff --git a/try.c b/try.c new file mode 100644 index 0000000..5a820ed --- /dev/null +++ b/try.c @@ -0,0 +1,290 @@ +#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)); +} + +// 鍙岀嚎鎬ф彃鍊煎嚱鏁 +// 鍙傝 https://zh.wikipedia.org/wiki/%E5%8F%8C%E7%BA%BF%E6%80%A7%E6%8F%92%E5%80%BC +char linear_insert(uch** old_pixels, uint32_t row, uint32_t col, uint32_t old_width, uint32_t old_height, float radio_w, float radio_h){ + float x = row / radio_h; + float y = col / radio_w; + // 濡傛灉鏁存暟鏍肩偣灏辩洿鎺ヨ繑鍥 + int x1 = floor(x); + int x2 = ceil(x); + int y1 = floor(y); + int y2 = ceil(y); + if (x2 >= old_height){x2 = x1;} + + if (y2 >= old_width){y2 = y1;} + if (x1 == x2 && y1 == y2){return old_pixels[x1][y1];} + if (x1 == x2){ + int x = x1; + uint32_t idx1 = x*old_width+y; + uint32_t idx2 = x*old_width+y; + float r = linear_single(y, y1, y2, old_pixels[x][idx1 + 0], old_pixels[x][idx2 + 0]); + float g = linear_single(y, y1, y2, old_pixels[x][idx1 + 1], old_pixels[x][idx2 + 1]); + float b = linear_single(y, y1, y2, old_pixels[x][idx1 + 2], old_pixels[x][idx2 + 2]); + return (char)r, (char)g, (char)b; + } + if (y1 == y2){ + int y = y1; + uint32_t idx = x*old_width+y; + float r = linear_single(x, x1, x2, old_pixels[x1][idx + 0], old_pixels[x2][idx + 0]); + float g = linear_single(x, x1, x2, old_pixels[x1][idx + 1], old_pixels[x2][idx + 1]); + float b = linear_single(x, x1, x2, old_pixels[x1][idx + 2], old_pixels[x2][idx + 2]); + return (char)r, (char)g, (char)b; + } + uint32_t idx1 = x*old_width+y; + uint32_t idx2 = x*old_width+y; + float fy1_r = linear_single(x, x1, x2, old_pixels[x1][idx1 + 0], old_pixels[x2][idx1 + 0]); + float fy1_g = linear_single(x, x1, x2, old_pixels[x1][idx1 + 1], old_pixels[x2][idx1 + 1]); + float fy1_b = linear_single(x, x1, x2, old_pixels[x1][idx1 + 2], old_pixels[x2][idx1 + 2]); + float fy2_r = linear_single(x, x1, x2, old_pixels[x1][idx2 + 0], old_pixels[x2][idx2 + 0]); + float fy2_g = linear_single(x, x1, x2, old_pixels[x1][idx2 + 1], old_pixels[x2][idx2 + 1]); + float fy2_b = linear_single(x, x1, x2, old_pixels[x1][idx2 + 2], old_pixels[x2][idx2 + 2]); + float r = linear_single(y, y1, y2, fy1_r, fy2_r); + float g = linear_single(y, y1, y2, fy1_g, fy2_g); + float b = linear_single(y, y1, y2, fy1_b, fy2_b); + return (char)r, (char)g, (char)b; +} + +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); + // } + // } + + + 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鍦栫墖 + char* r, g, b = linear_insert(&raw_img, j, i, width, height, radio_w, radio_h); + fwrite(b, sizeof(char), sizeof(uch), pFile); + fwrite(g, sizeof(char), sizeof(uch), pFile); + fwrite(r, 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** oldpixels, uint32_t* width, uint32_t* height, uint16_t* bits) +{ + if(!(name && oldpixels && 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; + unsigned char **oldpixels=(unsigned char**)malloc((*width)*(*height)*3); + + // 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*)&(*oldpixels)[idx*3 +2], sizeof(char), sizeof(uch), pFile); + fread((char*)&(*oldpixels)[idx*3 +1], sizeof(char), sizeof(uch), pFile); + fread((char*)&(*oldpixels)[idx*3 +0], sizeof(char), sizeof(uch), pFile); + } else if(*bits == 8) { // 鐏伴殠鍦 + fread((char*)&(*oldpixels)[idx], sizeof(char), sizeof(uch), pFile); + } + } + fseek(pFile , (long)alig , SEEK_CUR); + } + fclose(pFile); + + +//--------------------------------------------------------------------------- + // 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); +//---------------------------------------------------------------------------- + + // for(int j = *height-1; j >= 0; --j) { + // for(unsigned i = 0; i < *width; ++i) { + // uint32_t idx = j*(*width)+i; + // for(int k = 0; k < 3; k++){ + // printf((char*)&(*raw_img)[idx*3 + k]); + // printf("\t"); + // } + // printf("\t done \t"); + // } + // printf("\n"); + // } +} + +// 鍦栧儚绲愭 +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/bw2x1.bmp"); + // 瀵湒 + Imgraw_Writ(&img, "./output/bw2x1(output).bmp", radio_w, radio_h); + return 0; +} +/*==============================================================*/ \ No newline at end of file