bmp_v1/test.cpp

135 lines
5.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <stdlib.h>
#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;
}