空桑澈 2023-01-19 14:16 采纳率: 100%
浏览 50
已结题

对24位bmp图像实现等比例缩放

并保存缩放后的文件,如何修改下列代码


#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#pragma pack(1)//结构体中各成员按1字节对齐

struct BITMAPFILEHEADER//定义一个存储头文件数据结构体
{
    unsigned short bfType;        // 保存文件类型。'BM'
    unsigned long bfSize;        //位图文件总字节数
    unsigned short bfReserved1; //位图文件保留字段,必须为0
    unsigned short bfReserved2; //位图文件保留字段,必须为0
    unsigned long bfOffBits;    //RGB数据偏移地址,位图数据起始位置
    };

struct BITMAPINFOHEADER//定义一个存储位图信息的结构体
{
    unsigned long biSize;           //本结构占用字节数
    unsigned long biWidth;           //位图像素宽度
    unsigned long biHeight;           //位图像素高度
    unsigned short biPlanes;       // bmp图片的平面数量,为1
    unsigned short biBitCount;       //每个像素所占的位数
    unsigned long biCompression;   //位图压缩类型,不压缩(为0)
    unsigned long biSizeImage;       //位图图像数据所占字节数
    unsigned long biXPelsPerMeter; //位图水平分辨率,每米像素数
    unsigned long biYPelsPerMeter; //位图垂直分辨率,每米像素数
    unsigned long biClrUsed;       //位图实际使用的颜色表中的颜色数
    unsigned long biClrImportant;  //位图显示过程中重要的颜色数
};

//zoom函数用于缩放,BITMAPFILEHEADER head, BITMAPINFOHEADER info为原图像头信息,缩放倍数为2,char字符串类型指针变量
void zoom(BITMAPFILEHEADER head, BITMAPINFOHEADER info, char *input, char *output, double rate)
{//r:打开文件仅供读取,w:打开文件仅供写入,b:二进制
    FILE *fr = fopen(input, "rb");
    FILE *fw = fopen(output, "wb");

    //若读取不成功
    if (fr == NULL || fw == NULL)
    {
        printf("图片错误\n");
        return;
    }

    //读取原图像的头信息
    fread(&head, sizeof(BITMAPFILEHEADER), 1, fr);
    fread(&info, sizeof(BITMAPINFOHEADER), 1, fr);

    unsigned int old_Width = info.biWidth;//获取原图像的宽信息
    unsigned int old_height = info.biHeight;//获取原图像的高信息
    unsigned char *old_data = (unsigned char *)malloc(old_Width * old_height * 3);//获取原图像的位图数据

    ////定位到图像数据位置
    fseek(fr, 54, SEEK_SET);
    fread(old_data, old_Width * old_height * 3, 1, fr);

    //修改原图像的宽高
    unsigned int new_Width, new_Height;

    new_Width = (int)(rate * old_Width);//新宽等于倍数乘原宽
    new_Height = (int)(rate * old_height);//新高等于倍数乘原高
//修改头信息
    head.bfSize = new_Width * new_Height * 3 + 54;

    info.biWidth = new_Width;
    info.biHeight = new_Height;

    //将修改后的头信息写进新图像
    fwrite(&head, sizeof(BITMAPFILEHEADER), 1, fw);
    fwrite(&info, sizeof(BITMAPINFOHEADER), 1, fw);

    //缩放数据
    int i = 0, j = 0;
    unsigned long X, Y;
    unsigned char *pd;
    unsigned char *ps;
    unsigned char *new_data = (unsigned char *)malloc(new_Width * new_Height * 3);

    for (i = 0; i < new_Height; i++)
    {
        Y = i / rate;
        pd = new_data + i * new_Width * 3;
        ps = old_data + Y * old_Width * 3;

        for (j = 0; j < new_Width; j++)
        {
            X = j / rate;
            memcpy(pd + j * 3, ps + X * 3, 3);//拷贝数据
        }
    }

    //新文件数据定位
    fseek(fw, 54, SEEK_SET);
    fwrite(new_data, new_Width * new_Height * 3, 1, fw);
    printf("已成功缩放图像\n");

    //释放空间
    free(new_data);
    free(old_data);

    //关闭fr,fw
    fclose(fr);
    fclose(fw);
}

int main(int argc, char *argv[])
{
    //申明存储图像数据的结构体
    BITMAPFILEHEADER old_head;
    BITMAPINFOHEADER old_info;

    //初始化结构体变量
    memset(&old_head, 0, sizeof(BITMAPFILEHEADER));
    memset(&old_info, 0, sizeof(BITMAPINFOHEADER));

    //将缩放比例转化为double类型
    double rate = atof(argv[2]) / 100.0;
    zoom(old_head, old_info, argv[1], argv[3], rate);

    return 0;
}
  • 写回答

2条回答 默认 最新

  • ksgpjhqf 2023-01-19 17:23
    关注

    这是一个命令行程序,需要打开cmd,输入命令运行。如cmd进入程序所在的文件夹后,输入命令:图片缩放.exe "新建位图图像.bmp" 50 "缩放后的图像.bmp"
    你的代码没有考虑bmp每行按4字节对齐的情况。
    修改后的代码:

     
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    #pragma pack(1)//结构体中各成员按1字节对齐
     
    struct BITMAPFILEHEADER//定义一个存储头文件数据结构体
    {
        unsigned short bfType;        // 保存文件类型。'BM'
        unsigned long bfSize;        //位图文件总字节数
        unsigned short bfReserved1; //位图文件保留字段,必须为0
        unsigned short bfReserved2; //位图文件保留字段,必须为0
        unsigned long bfOffBits;    //RGB数据偏移地址,位图数据起始位置
        };
     
    struct BITMAPINFOHEADER//定义一个存储位图信息的结构体
    {
        unsigned long biSize;           //本结构占用字节数
        unsigned long biWidth;           //位图像素宽度
        unsigned long biHeight;           //位图像素高度
        unsigned short biPlanes;       // bmp图片的平面数量,为1
        unsigned short biBitCount;       //每个像素所占的位数
        unsigned long biCompression;   //位图压缩类型,不压缩(为0)
        unsigned long biSizeImage;       //位图图像数据所占字节数
        unsigned long biXPelsPerMeter; //位图水平分辨率,每米像素数
        unsigned long biYPelsPerMeter; //位图垂直分辨率,每米像素数
        unsigned long biClrUsed;       //位图实际使用的颜色表中的颜色数
        unsigned long biClrImportant;  //位图显示过程中重要的颜色数
    };
     
    //zoom函数用于缩放,BITMAPFILEHEADER head, BITMAPINFOHEADER info为原图像头信息,缩放倍数为2,char字符串类型指针变量
    void zoom(BITMAPFILEHEADER head, BITMAPINFOHEADER info, char *input, char *output, double rate)
    {//r:打开文件仅供读取,w:打开文件仅供写入,b:二进制
        FILE *fr = fopen(input, "rb");
        FILE *fw = fopen(output, "wb");
     
        //若读取不成功
        if (fr == NULL || fw == NULL)
        {
            printf("图片错误\n");
            return;
        }
     
        //读取原图像的头信息
        fread(&head, sizeof(BITMAPFILEHEADER), 1, fr);
        fread(&info, sizeof(BITMAPINFOHEADER), 1, fr);
     
        unsigned int old_Width = info.biWidth;//获取原图像的宽信息
        unsigned int old_height = info.biHeight;//获取原图像的高信息
        unsigned char *old_data = (unsigned char *)malloc((old_Width * 3+3>>2<<2)*old_height);//获取原图像的位图数据
     
        ////定位到图像数据位置
        fseek(fr, 54, SEEK_SET);
        fread(old_data, (old_Width * 3+3>>2<<2)*old_height, 1, fr);
     
        //修改原图像的宽高
        unsigned int new_Width, new_Height;
     
        new_Width = (int)(rate * old_Width);//新宽等于倍数乘原宽
        new_Height = (int)(rate * old_height);//新高等于倍数乘原高
    //修改头信息
        head.bfSize = (new_Width * 3+3>>2<<2) * new_Height + 54;
     
        info.biWidth = new_Width;
        info.biHeight = new_Height;
     
        //将修改后的头信息写进新图像
        fwrite(&head, sizeof(BITMAPFILEHEADER), 1, fw);
        fwrite(&info, sizeof(BITMAPINFOHEADER), 1, fw);
     
        //缩放数据
        int i = 0, j = 0;
        unsigned long X, Y;
        unsigned char *pd;
        unsigned char *ps;
        unsigned char *new_data = (unsigned char *)malloc((new_Width *3+3>>2<<2)* new_Height);
     
        for (i = 0; i < new_Height; i++)
        {
            Y = i / rate;
            pd = new_data + i * (new_Width * 3+3>>2<<2);
            ps = old_data + Y * (old_Width * 3+3>>2<<2);
     
            for (j = 0; j < new_Width; j++)
            {
                X = j / rate;
                memcpy(pd + j * 3, ps + X * 3, 3);//拷贝数据
            }
        }
     
        //新文件数据定位
        fseek(fw, 54, SEEK_SET);
        fwrite(new_data, (new_Width *3+3>>2<<2), new_Height, fw);
        printf("已成功缩放图像\n");
     
        //关闭fr,fw
        fclose(fr);
        fclose(fw); 
        
        //释放空间
        free(new_data);
        free(old_data);
    }
     
    int main(int argc, char *argv[])
    {
        //申明存储图像数据的结构体
        BITMAPFILEHEADER old_head;
        BITMAPINFOHEADER old_info;
     
        //初始化结构体变量
        memset(&old_head, 0, sizeof(BITMAPFILEHEADER));
        memset(&old_info, 0, sizeof(BITMAPINFOHEADER));
     
        //将缩放比例转化为double类型
        double rate = atof(argv[2]) / 100.0;
        zoom(old_head, old_info, argv[1], argv[3], rate);
     
        return 0;
    }
    
    

    执行结果:

    img

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 2月3日
  • 已采纳回答 1月26日
  • 创建了问题 1月19日

悬赏问题

  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因