diff --git a/bmp.c b/bmp.c index 5edcd51..d0735d3 100644 --- a/bmp.c +++ b/bmp.c @@ -28,12 +28,20 @@ struct BmpInfoHeader { #pragma pack() -void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t height, uint16_t bits) +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)) { 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, @@ -41,7 +49,7 @@ 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 + width*height * bits/8; + file_h.bfSize = file_h.bfOffBits + newWidth*newHeight * bits/8; if(bits==8) {file_h.bfSize+= 1024, file_h.bfOffBits+= 1024;} // 圖片資訊 struct BmpInfoHeader info_h = { @@ -53,10 +61,10 @@ void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t hei .biClrUsed=0, .biClrImportant=0, }; - info_h.biWidth = width; - info_h.biHeight = height; + info_h.biWidth = newWidth; + info_h.biHeight = newHeight; info_h.biBitCount = bits; - info_h.biSizeImage = width*height * bits/8; + info_h.biSizeImage = newWidth*newHeight * bits/8; if(bits == 8) {info_h.biClrUsed=256;} // 寫入檔頭 FILE *pFile = NULL; @@ -88,20 +96,18 @@ void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t hei 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; + // unsigned long oldWidth, oldHeight, oldSize, newWidth, newHeight, newSize; - oldWidth = width; - oldHeight = height; + // oldWidth = width; + // oldHeight = height; unsigned char *sourceData = (unsigned char*)malloc(oldSize);//该指针指向源位图文件图像数据的内存空间 - fseek(src_file, 54, SEEK_SET);//使文件的指针指向文件的第55个字节 - fread(sourceData, oldSize, 1, src_file);//将src_file中的图像数据存储到sourceData指向的内存空间 - - double radio = 1.0;// test 倍數 + 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; + // newWidth = ((int)(oldWidth * radio) + 3) / 4 * 4;//图像显示不出来原因在于图像长或宽不是4的倍数 下面这一步可以保证得到的宽高是4的倍数 + // newHeight = ((int)(oldHeight * radio) + 3) / 4 * 4; - //10.使用最邻近插值算法进行图片缩放 + //10.使用最邻近插值算法进行图片缩放 unsigned int x,y,X,Y;//源位图文件像素点宽高和目标位图文件像素点宽高 unsigned char *destData = (unsigned char*)malloc(newSize);//该指针指向目标位图文件图像数据的内存空间 unsigned char *sourceWhere, *destWhere;//修改像素的对应位置 @@ -186,9 +192,9 @@ 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) { +void Imgraw_Writ(const Imgraw* _this, const char* name, const char* old_name) { const Imgraw* p = _this; - bmpWrite(name, p->data, p->width, p->height, p->bits); + bmpWrite(name, p->data, p->width, p->height, p->bits, old_name, 1.0); } /*==============================================================*/ int main(int argc, char const *argv[]) { @@ -197,7 +203,7 @@ int main(int argc, char const *argv[]) { // 讀圖 Imgraw_Read(&img, "./input/bw2x1.bmp"); // 寫圖 - Imgraw_Writ(&img, "./output/bw2x1(output).bmp"); + Imgraw_Writ(&img, "./output/bw2x1(output).bmp", "./input/bw2x1.bmp"); return 0; } /*==============================================================*/ \ No newline at end of file diff --git a/bmp.exe b/bmp.exe index 1cdba70..8a88592 100644 Binary files a/bmp.exe and b/bmp.exe differ diff --git a/bmp_copy_demo.c b/bmp_copy_demo.c new file mode 100644 index 0000000..048bdf4 --- /dev/null +++ b/bmp_copy_demo.c @@ -0,0 +1,180 @@ +#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) +{ + if(!(name && raw_img)) { + perror("Error bmpWrite."); + return; + } + // 檔案資訊 + 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;} + // 圖片資訊 + 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;} + // 寫入檔頭 + 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 = ((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圖片 + 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) { + 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}; + // 讀圖 + Imgraw_Read(&img, "./input/bw2x1.bmp"); + // 寫圖 + Imgraw_Writ(&img, "./output/bw2x1(output).bmp"); + return 0; +} +/*==============================================================*/ \ No newline at end of file diff --git a/bmp_copy_demo.exe b/bmp_copy_demo.exe new file mode 100644 index 0000000..82909f2 Binary files /dev/null and b/bmp_copy_demo.exe differ