zoukankan      html  css  js  c++  java
  • 位图对齐及格式

    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);
    }

  • 相关阅读:
    vb.net structure 定义静态数组
    调色板原理 & 编程
    CView::OnPreparePrinting
    MFC单文档程序架构解析
    基于Eclipse远程调试解决的预上线首页打开特别慢的问题
    Shiro Filter引发的思考
    Shiro Filter中利用Callable和Runnable的委派模式
    Shiro DefaultFilter
    防止Form表单重复提交的客户端及服务器端的方式
    Shiro Filter的设计概念
  • 原文地址:https://www.cnblogs.com/dearplain/p/2869914.html
Copyright © 2011-2022 走看看