• 位图对齐及格式


    http://baike.baidu.com/view/189487.htm

    有关RGB三色空间我想大家都很熟悉,这里我想说的是在Windows下RGB颜色阵列存储的格式其实BGR。也就是说,对于24位的RGB位图像素数据格式是:

    蓝色B值 绿色G值 红色R值

    对于32位的RGB位图像素数据格式是:

    蓝色B值 绿色G值 红色R值 透明通道A值

    透明通道也称Alpha通道,该值是该像素点的透明属性,取值在0(全透明)到255(不透明)之间。对于24位的图像来说,因为没有Alpha通道,故整个图像都不透明。

    由于Windows在进行行扫描的时候最小的单位为4个字节,所以当
    图片宽 X 每个像素的字节数 != 4的整数倍
    时要在每行的后面补上缺少的字节,以0填充(一般来说当图像宽度为2的幂时不需要对齐)。位图文件里的数据在写入的时候已经进行了行对齐,也就是说加载的时候不需要再做行对齐。但是这样一来图片数据的长度就不是:宽 X 高 X 每个像素的字节数了,我们需要通过下面的方法计算正确的数据长度:
    //Calculate the image data size
    int iLineByteCnt = (((m_iImageWidth*m_iBitsPerPixel) + 3) >> 2) << 2;
    m_iImageDataSize = iLineByteCnt * m_iImageHeight;

    3D(OpenGL)的不同之处
    如果你是想用刚才我们得到的数据生成纹理对象,那么你还要请出下面的问题。
    首先,用来生成纹理的数据不需要对齐,也就是说不能在每行的后面加上对齐的字节。当然在OpenGL里要求纹理图片的尺寸为2的幂,所以这个问题实际上不存在;
    其次,我们得到的图形数据格式是BGR(BGRA),所以在生成纹理的时候,需指定格式为GL_BGR_EXT(GL_BGRA_EXT);否则需要做BGR->RGB(BGRA->RGBA)的转化。

    ------------------------------------------

    1、加载文件头
    //Load the file header
    BITMAPFILEHEADER header;
    memset(&header,0,sizeof(header));
    inf.read((char*)&header,sizeof(header));
    if(header.bfType != 0x4D42)
    return false;
    这个很简单,没有什么好说的。
    2、加载位图信息头
    //Load the image information header
    BITMAPINFOHEADER infoheader;
    memset(&infoheader,0,sizeof(infoheader));
    inf.read((char*)&infoheader,sizeof(infoheader));
    m_iImageWidth = infoheader.biWidth;
    m_iImageHeight = infoheader.biHeight;
    m_iBitsPerPixel = infoheader.biBitCount;
    这里我们得到了3各重要的图形属性:宽,高,以及每个像素颜色所占用的位数。
    3、行对齐
    由于Windows在进行行扫描的时候最小的单位为4个字节,所以当
    图片宽 X 每个像素的字节数 != 4的整数倍
    时要在每行的后面补上缺少的字节,以0填充(一般来说当图像宽度为2的幂时不需要对齐)。位图文件里的数据在写入的时候已经进行了行对齐,也就是说加载的时候不需要再做行对齐。但是这样一来图片数据的长度就不是:宽 X 高 X 每个像素的字节数了,我们需要通过下面的方法计算正确的数据长度:
    //Calculate the image data size
    int iLineByteCnt = (((m_iImageWidth*m_iBitsPerPixel) + 3) >> 2) << 2;
    m_iImageDataSize = iLineByteCnt * m_iImageHeight;
    4、加载图片数据
    对于24位和32位的位图文件,位图数据的偏移量为sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER),也就是说现在我们可以直接读取图像数据了。
    if(m_pImageData) delete []m_pImageData;
    m_pImageData = new unsigned char[m_iImageDataSize];
    inf.read((char*)m_pImageData,m_iImageDataSize);
    如果你足够细心,就会发现内存m_pImageData里的数据的确是BGR格式,可以用个纯蓝色或者是纯红色的图片测试一下。
    5、绘制
    好了,数据和属性我们都有了,现在就可以拿来随便用了,就和吃馒头一样,爱粘白糖粘白糖,爱粘红糖粘红糖。下面是我的GDI绘制代码,仅作参考。
    void CImage::DrawImage(HDC hdc,int iLeft,int iTop,int iWidth,int iHeight)
    {
    if(!hdc || m_pImageData == NULL)
    return;
    BITMAPINFO bmi;
    memset(&bmi,0,sizeof(bmi));
    bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
    bmi.bmiHeader.biWidth = m_iImageWidth;
    bmi.bmiHeader.biHeight = m_iImageHeight;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = m_iBitsPerPixel;
    bmi.bmiHeader.biCompression = BI_RGB;
    bmi.bmiHeader.biSizeImage = m_iImageDataSize;
    StretchDIBits(hdc,iLeft,iTop,iWidth,iHeight,
    0,0,m_iImageWidth,m_iImageHeight,
    m_pImageData,&bmi,DIB_RGB_COLORS,SRCCOPY);
    }

  • 相关阅读:
    游戏引擎中的光照算法
    深入剖析GPU Early Z优化
    UE4联机编译光照
    深入剖析MSAA
    Unity 使用xLua遇到的坑
    扩展SQLite使其能从apk文件中读取db
    tolua#代码简要分析
    虚幻4垃圾回收剖析
    虚幻4蓝图虚拟机剖析
    java转成xml
  • 原文地址:https://www.cnblogs.com/dearplain/p/2869914.html
Copyright © 2020-2023  润新知