qq_43049500 2022-06-20 17:08 采纳率: 0%
浏览 26
已结题

将bmp图转换为整型矩阵出现灰度级缺失

将bmp图转换为整型矩阵出现灰度级缺失
问题相关代码
// R2Gv1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <fstream>
#pragma pack(1)//可以自定义结构体对齐方式
using namespace std;

typedef unsigned char BYTE;//一个字节
typedef unsigned short WORD;//两个字节
typedef unsigned int DWORD;//4个字节
                           //位图文件头 14个字节
typedef struct tagBITMAPFILEHEADER {
    WORD bfType; /* 说明文件的类型 必须是0x424D,即字符串“BM”,也就是说所有.bmp文件的头两个字节都是“BM”*/
    DWORD bfSize; /* 说明文件的大小,包括这14个字节,以字节为单位 */
    WORD bfReserved1; /* 保留,设置为0 */
    WORD bfReserved2; /* 保留,设置为0 */
    DWORD bfOffBits; /* 说明从BITMAPFILEHEADER结构开始到实际的图像数据之间的字节偏移量,以字节为单位 */
} BITMAPFILEHEADER;
//位图信息头 固定大小为40个字节
typedef struct tagBITMAPINFOHEADER {
    DWORD biSize;//信息头大小
    DWORD biWidth;//图像宽度
    DWORD biHeight;//图像高度
    WORD biPlanes;//位平面数,必须为1
    WORD biBitCount;//每像素位数。常用的值为1(黑白二色图), 4(16色图), 8(256色), 24(真彩色图)或32(新的.bmp格式支持32位色)
    DWORD  biCompression; //压缩类型:有效的值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS(都是一些Windows定义好的常量)
    DWORD  biSizeImage;  //压缩图像大小字节数 biSizeImage=biWidth’ × biHeight,biWidth’必须是4的整倍数,(所以不是biWidth,而是biWidth’,表示大于或等于biWidth的,最接近4的整倍数)
    DWORD  biXPelsPerMeter; //水平分辨率,单位是每米的象素个数
    DWORD  biYPelsPerMeter; //垂直分辨率,单位是每米的象素个数
    DWORD  biClrUsed; //位图实际用到的色彩数,如果该值为零,则用到的颜色数为2^biBitCount
    DWORD  biClrImportant; //本位图中重要的色彩数,如果该值为零,则认为所有的颜色都是重要的。
} BITMAPINFOHEADER;  //位图信息头定义
                     //调色板的定义 4个字节
                     /*真彩色是无调色板部分的
                     如真彩色图是不需要调色板的,BITMAPINFOHEADER后直接是位图数据。
                     调色板实际上是一个数组,共有biClrUsed个元素(如果该值为零,则有2^biBitCount个元素),数组中每个元素的类型是一个RGBQUAD结构,共占4个字节*/
typedef struct tagRGBQUAD {
    BYTE rgbBlue; //该颜色的蓝色分量
    BYTE rgbGreen; //该颜色的绿色分量
    BYTE rgbRed; //该颜色的红色分量
    BYTE rgbReserved; //保留值
}RGBQUAD;//调色板定义
         /*
         要注意一下几点:
         (1)每一行的字节数必须是4的整倍数,如果不是,则需要补齐。如241补齐为244.
         (2)一般来说,.bMP文件的数据从下到上,从左到右的。也就是说,从文件中最先读到的是图象最下面一行的左边第一个象素,
         然后是左边第二个象素……接下来是倒数第二行左边第一个象素,左边第二个象素……依次类推 ,最后得到的是最上面一行的最右一个象素。
         (3)图像是24位或是32位数据的位图的话,位图数据区就不是索引而是实际的像素值了。
         (4)24位RGB按照BGR的顺序来存储每个像素的各颜色通道的值,一个像素的所有颜色分量值都存完后才存下一个像素,不进行交织存储。
         (5)32位数据按照BGRA的顺序存储,其余与24位位图的方式一样。
         */

int main()
{
    BITMAPFILEHEADER bmpFlieHead;
    BITMAPINFOHEADER bmpInfHead;

    //int lineByte = (bmpWidth * biBitCount / 8 + 3) / 4 * 4;//灰度图像有颜色表,且颜色表表项为256
    FILE *fpbmp = fopen("E:\\docs\\620.bmp","rb");//二进制读 打开
    FILE *fpGray = fopen("E:\\docs\\3222.bmp", "wb");//二进制写 打开
    fread(&bmpFlieHead, 14, 1, fpbmp);
    fread(&bmpInfHead, 40, 1, fpbmp);
    char* buffer = new char[bmpFlieHead.bfSize - 54]();
    int bmpWidth = bmpInfHead.biWidth;
    int bmpHeight = bmpInfHead.biHeight;
    fread(buffer, bmpFlieHead.bfSize - 54, 1, fpbmp);
    int lineByte = (bmpWidth*bmpInfHead.biBitCount / 8+ 3) / 4 * 4;

    //从这里我开始改动
    int** AA;
    AA = new int*[480];
    for (int i = 0; i < 480; i++)
    {
        AA[i] = new int[640];
    }
    int lineGray;

    for (int i = 0; i < bmpHeight; i++)
    {
        lineGray = 0;
        for (int j = 0; j < lineByte - 2; j++)
        {
            char color = buffer[i*lineByte + j + 2];
            AA[i][lineGray] = color + 128;//因为转换后有正负号,+128将范围控制在0~255;
            //buffer[i*lineByte + j + 1] = color;
            //buffer[i*lineByte + j + 2] = color;
            j += 2;
            lineGray++;
        }
    }
    
    ofstream outfile;
    outfile.open("E:\\docs\\gray.txt", ofstream::app);
    for (int i = 0; i < 480; i++)
    {
        for (int j = 0; j < 640; j++)
        {
            outfile << AA[i][j] << " ";
        }
        outfile << endl;
    }

    //memset(buffer, 100,(bmpFlieHead.bfSize - 54));
    /*fwrite(&bmpFlieHead, 14, 1, fpGray);
    fwrite(&bmpInfHead, 40, 1, fpGray);
    fwrite(buffer, bmpFlieHead.bfSize - 54, 1, fpGray);*/
    fclose(fpGray);
    delete[] buffer;
    return 0;
}

代码部分借鉴wu_qz原创文章

版权声明:本文为CSDN博主「wu_qz」的原创文章,遵循CC 4.0 BY SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https ://blog.csdn.net/Wu_qz/article/details/80958745

运行结果及报错内容

img

我想要达到的结果

img

  • 写回答

1条回答 默认 最新

  • 爱晚乏客游 2022-06-21 09:36
    关注

    img


    为什么加128?假设原本就是255的灰阶,你加上128不就是超过255了吗,转成bmp的话自动阶段变成255,也就会是你现实的那样变白。
    灰度图像算法不是这么计算的,一般来说是RGB三通道各自的分量相加为灰度值,而不是直接加128.比较常用的公式是
    Gray = R0.299 + G0.587 + B*0.114
    当然还有一些其他的公式,这里就不贴了,你可以自己找一下

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 6月21日
  • 创建了问题 6月20日

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器