如何修改BMP处理代码将颠倒图像恢复至原始位置?
修复上下颠倒BMP图像的代码修改方案
首先明确BMP的存储规则:
- 当
biHeight为正数时,图像像素从底部到顶部逐行存储 - 当
biHeight为负数时,图像像素从顶部到底部逐行存储
要恢复颠倒的图像,核心是倒序读取原图像的扫描线,同时修正biHeight的符号以匹配正序存储规则。
原代码的两处关键错误
先修正代码里的笔误,这是运行正确的前提:
fread(&triple, sizeof(bi.biHeight), 1, inptr);应改为sizeof(RGBTRIPLE),否则会错误读取字节数fwrite(&triple, sizeof(bi.biHeight), 1, outptr);同理,替换为sizeof(RGBTRIPLE)
完整修改后的代码及说明
// Read infile's BITMAPFILEHEADER BITMAPFILEHEADER bf; fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr); // Read infile's BITMAPINFOHEADER BITMAPINFOHEADER bi; fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr); // Ensure infile is (likely) a 24-bit uncompressed BMP 4.0 if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 || bi.biBitCount != 24 || bi.biCompression != 0) { fclose(outptr); fclose(inptr); printf("Unsupported file format.\n"); return 4; } // 修正biHeight符号:将原倒序存储的标识(正数)改为正序存储标识(负数) int originalHeight = abs(bi.biHeight); bi.biHeight = -originalHeight; // Write outfile's BITMAPFILEHEADER fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr); // Write outfile's BITMAPINFOHEADER(已修正biHeight) fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr); // Calculate padding for scanlines int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4; // 计算每行总字节数(像素数据+填充字节) int scanlineSize = bi.biWidth * sizeof(RGBTRIPLE) + padding; // 倒序读取原图像的扫描线:从最后一行开始,写入输出文件的第一行 for (int i = originalHeight - 1; i >= 0; i--) { // 定位到原文件第i行的起始位置 fseek(inptr, bf.bfOffBits + i * scanlineSize, SEEK_SET); // 读取当前行的所有像素 for (int j = 0; j < bi.biWidth; j++) { RGBTRIPLE triple; fread(&triple, sizeof(RGBTRIPLE), 1, inptr); fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr); } // 写入当前行的填充字节 for (int k = 0; k < padding; k++) { fputc(0x00, outptr); } }
修改核心要点
- 修正biHeight符号:告诉输出文件的阅读器,图像是从上到下正序存储的,符合标准规范
- 倒序定位扫描线:用
fseek直接跳转至原文件的对应行,避免逐行读取时的顺序错误 - 补全填充字节写入:原代码遗漏了填充字节的写入,会导致图像偏移变形,必须补充
- 修正像素读写字节数:确保每次读写的是一个RGB像素的正确字节数
内容的提问来源于stack exchange,提问作者antotot04
相关产品推荐
相关产品推荐

