You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C/C++实现BMP图像读写平移后Visual Studio输出格式不支持问题

问题根因分析

  • 核心错误:未处理BMP文件的行对齐规则。BMP格式规定每一行像素数据的字节数必须向上对齐到4的整数倍,不足的位置用0字节填充。你当前直接用3 * width * height计算像素总大小,仅在宽度是4的倍数时成立,对于宽度不是4的倍数的图像,读取、写入的像素数据长度和实际文件不匹配,导致输出文件头信息和实际数据不一致,系统无法识别格式。
  • 次要问题:平移函数中新分配的像素数组未初始化,超出有效平移区域的像素是随机垃圾值;代码存在多处内存泄漏,BMP结构体的pixels指针申请的堆内存全程没有释放。
  • 潜在问题:BMP newImage = image是浅拷贝,只会复制pixels指针的地址,不会复制实际像素数据,后续操作容易出现野指针、重复释放问题。

修复方案

  1. 新增行对齐计算逻辑,读取、写入时按对齐后的行大小处理数据
  2. 平移函数中先初始化新像素数组为全黑(或自定义背景色)
  3. 补充内存释放逻辑,避免内存泄漏

修复后代码示例

#include <iostream>
#include <string>
#include <cstring>
using namespace std;

struct BMP {
    int width;
    int height;
    int rowSize; // 对齐后的单行字节数
    unsigned char header[54];
    unsigned char *pixels;
    int size;
};

// 读取BMP图像
BMP readBMP(string filename) {
    BMP image;
    FILE *f = fopen(filename.c_str(), "rb");
    if(!f) {
        cout << "文件打开失败" << endl;
        exit(1);
    }
    fread(image.header, sizeof(unsigned char), 54, f);

    image.width = *(int*)&image.header[18];
    image.height = *(int*)&image.header[22];
    // 计算对齐后的单行字节数,总像素大小
    image.rowSize = (image.width * 3 + 3) / 4 * 4;
    image.size = image.rowSize * abs(image.height);
    image.pixels = new unsigned char[image.size];

    // 按对齐后的大小读取像素数据
    fread(image.pixels, sizeof(unsigned char), image.size, f);
    fclose(f);

    // BGR转RGB,注意要按行处理,跳过对齐填充的0字节
    for(int y = 0; y < abs(image.height); y++) {
        for(int x = 0; x < image.width; x++) {
            int idx = y * image.rowSize + x * 3;
            swap(image.pixels[idx], image.pixels[idx + 2]);
        }
    }
    return image;
}

// 写入BMP图像
void writeBMP(string filename, BMP image) {
    FILE *out = fopen(filename.c_str(), "wb");
    if(!out) {
        cout << "输出文件创建失败" << endl;
        exit(1);
    }
    fwrite(image.header, sizeof(unsigned char), 54, out);

    // RGB转回BGR,同样按行处理跳过填充字节
    for(int y = 0; y < abs(image.height); y++) {
        for(int x = 0; x < image.width; x++) {
            int idx = y * image.rowSize + x * 3;
            swap(image.pixels[idx], image.pixels[idx + 2]);
        }
    }
    // 按对齐后的大小写入像素数据
    fwrite(image.pixels, sizeof(unsigned char), image.size, out);
    fclose(out);
}

// 图像平移
BMP translation(BMP image, int tx, int ty) {
    BMP newImage = image;
    newImage.pixels = new unsigned char[image.size];
    // 初始化新图像像素为全黑
    memset(newImage.pixels, 0, image.size);

    for(int y = 0; y < abs(image.height); y++) {
        for(int x = 0; x < image.width; x++) {
            int xx = x - tx;
            int yy = y + ty;
            if(xx >=0 && xx < image.width && yy >=0 && yy < abs(image.height)) {
                int srcIdx = yy * image.rowSize + xx * 3;
                int dstIdx = y * image.rowSize + x * 3;
                newImage.pixels[dstIdx] = image.pixels[srcIdx];
                newImage.pixels[dstIdx + 1] = image.pixels[srcIdx + 1];
                newImage.pixels[dstIdx + 2] = image.pixels[srcIdx + 2];
            }
        }
    }
    return newImage;
}

// 释放BMP内存
void freeBMP(BMP &image) {
    if(image.pixels) {
        delete[] image.pixels;
        image.pixels = nullptr;
    }
}

int main() {
    BMP image = readBMP("sample_640×426.bmp");
    writeBMP("Output-11.bmp", image);

    int x0 = 100, y0 = 50;
    BMP image_t = translation(image, x0, y0);
    writeBMP("Out_translate.bmp", image_t);

    // 释放内存
    freeBMP(image);
    freeBMP(image_t);
    return 0;
}

内容的提问来源于stack exchange,提问作者user17279105

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 05:54:03