zoukankan      html  css  js  c++  java
  • 使用GetDIBts/SetDIBits高速逐点处理 from http://blog.sina.com.cn/s/blog_552ad2090100e3eu.html

    使用GetDIBts/SetDIBits高速逐点处理

     (2009-07-30 14:38:03)
    标签: 

    杂谈

     
     
     

    之前逐点处理像素的时候都用GetPixel和SetPixel,对比了下坂本千寻系列里用的DIB,才知道那速度真不是一般的慢。前者可以看到扫描线,处理一张1024*800的图需要1~2s,但是后者处理相同大小的图几乎是即时的。

    关于DIB(设备无关位图)和DDB(设备相关位图)有很多概念,经常弄得我云里雾里,实际上用起来,DDB就是和dc相关的位图,不同情况下用CreateBMP(),CreateCompatibleBMP(),LoadBMP(),LoadImage()等创建的就是DDB。DIB就是一片内存,里面存储着位图掐头去尾,只留下RGB(32位真彩,16位真彩),或者像素+色板(8位)的信息。

    创建DIB也比较晕,坂本千寻系列里,读bmp,png,读像素点等函数都是自己写的。但是现在读写图片有很多好用的库,应该好好利用。所以,我的方法是,用CImage类读图->创建双缓存->读图到离屏dc->读内存bmp到DIB->GetDIBits->处理像素点->SetDIBits到屏幕dc。
    //1.创建双缓存,创建DIB
    //HDC hdc,memdc, HBITMAP memBmp为成员变量

    hdc=::GetDC(m_hWnd);
    memdc=CreateCompatibleDC(hdc);
    memBmp=CreateCompatibleBitmap(hdc,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
    SelectObject(memdc,memBmp);
    //CImage *img为成员变量 #include <atlimage.h>
    img=new CImage();
    img->Load(_T("3.bmp"));
    img->Draw(memdc,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),0,0,img->GetWidth(),img->GetHeight());
    //从HBITMAP获取BITMAP
    CBitmap cbmp;
    cbmp.Attach(memBmp);
    cbmp.GetBitmap(&bm);
    //创建DIB实际上就两步
    //1. 在内存new出一片位图大小的空间,new BYTE,new char,GlobalAlloc都有人用
    //2. 填写BITMAPINFO结构

    DWORD size=bm.bmWidthBytes*bm.bmHeight; //每行像素位*图高
    pBuf=new BYTE[size];
        
      
    ZeroMemory(&binfo,sizeof(BITMAPINFO));
    binfo.bmiHeader.biBitCount=bm.bmBitsPixel;      //每个像素多少位,也可直接写24(RGB)或者32(RGBA)
    binfo.bmiHeader.biCompression=0;
    binfo.bmiHeader.biHeight=bm.bmHeight;
    binfo.bmiHeader.biPlanes=1;
    binfo.bmiHeader.biSizeImage=0;
    binfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
    binfo.bmiHeader.biWidth=bm.bmWidth;
    //下面就可以逐点处理了
    //获取位图到内存DIB
    GetDIBits(memdc,memBmp,0,binfo.bmiHeader.biHeight,pBuf,(BITMAPINFO*)&binfo,DIB_RGB_COLORS);
    //逐点处理,这里是用来作淡出效果
    //这里是一个颜色分量8位,而不是一个像素
    for(int i=0;i<binfo.bmiHeader.biSizeImage;i++)
    {
       pBuf[i]=pBuf[i]*level/256;
      
    }

    //全图处理完毕读出到屏幕dc显示
    SetDIBits(hdc,memBmp,0,binfo.bmiHeader.biHeight,pBuf,(BITMAPINFO*)&binfo,DIB_RGB_COLORS);

    原来DIB就是这么简单。

    SetDIBits

     
     

    函数功能

      该函数使用指定的DIB位图中发现的颜色数据来设置位图中的像素。

    函数原型

      int SetDIBits(HDC hdc, HBITMAP hbmp, UINT uStartScan, UINT cScanLines, CONST VOID *lpvBits,CONST BITMAPINFO *lpbmi, UINT fuColorUse);

    参数

      hdc:指向设备环境中的句柄。
     
      hbmp:指向位图的句柄。函数要使用指定DIB中的颜色数据对该位图进行更改。
     
      uStartScan:为参数lpvBits指向的数组中的、与设备无关的颜色数据指定起始扫描线
     
      cScanLines:为包含与设备无关的颜色数据的数组指定扫描线数目。
     
      lpvBits:指向DIB颜色数据的指针,这些数据存储在字节类型的数组中,位图值的格式取决于参数lpbmi指向的BITMAPINFO结构中的成员biBitCount。
     
      lpbmi:指向BITMAPINFO数据结构的指针,该结构包含有关DIB的信息。
     
      fuColorUse:指定是否提供了BITMAPINFO结构中的bmiColors成员,如果提供了,那么bmiColors是否包含了明确的RGB值或调色板索引。参数fuColorUse必须取下列值,各值的含义为:
     
      DIB_PAL_COLORS:颜色表由16bit的索引值数组组成。这些值可以对由hdc参数标识的设备环境中的逻辑调色板进行索引。
     
      DIB_RGB_COLORS:提供了颜色表,并且表中包含了原义的RGB值。

    返回值

      如果函数成功,那么返回值就是复制的扫描线数;如果函数失败,那么返回值是0。
     
      Windows NT:若想获得更多错误信息,请调用GetLastError函数。
     

    备注

      当位图的位要索引到系统调色板时,可获取最佳的位图绘制速度。
     
      应用程序可能通过调用GetSystemPaletteEntries函数来检索系统调色板颜色和索引。在检索到颜色和索引值之后,应用程序可以创建DIB,有关更多的信息,请参考系统调色板(System Paletle)。
     
      只有在参数fuColorUse设置为DIB_PAL_COLORS常量时才使用参数hdc标识的设备环境,否则会忽略hdc参数中的值。
     
      在应用程序调用该函数时,必须把由参数hbmp标识的位图选入到设备环境中。
     
      自底向上的DIB位图的起始点是该位图的左下角处,自顶向下的DIB位图的起源点在该位图的左上角处。
     
      ICM:颜色管理照样进行。如果指定的BITMAPINFO结构不是BITMAPV4HEADER或BITMAPV5HEADER,那么当前设备环境的颜色配置(profile)就用作源颜色配置。如果BITMAPINFO结构不是BITMAPV4HEADER或BITMAPV5HEADER,那么使用RGB颜色。如果指定的BITMAPINFO结构是BITMAPV4HEADER或BITMAPV5HEADER,那么与该位图有关的颜色配置(profile)被用作源颜色。
     
      速查:Windows NT:3.1及以上版本;Windows:95及以上版本;Windows CE:不支持;头文件:wingdi.h:库文件:gdi32.lib。
  • 相关阅读:
    JAVA8 Optional类记录
    Annotation-specified bean name 'customerMapper' for bean class [com.jiutong.zeus.old.mapper.zqp.CustomerMapper] conflicts with existing, non-compatible bean definition of same name and class
    正则 0-100的正整数
    Windows 安装ElasticSearch 安装IK 分词器
    Push failed Invocation failed Server returned invalid Response. java.lang.RuntimeException: Invocation failed Server returned invalid Response.
    BigDecimal 方法使用
    Factory method 'eurekaClient' threw exception; nested exception is java.lang.RuntimeException: Failed to initialize DiscoveryClient!
    子项目的逆向工程-代码生成器
    安装 RabbitMQ
    redis 分布式锁-简易版与 redisson 实验
  • 原文地址:https://www.cnblogs.com/songtzu/p/2828295.html
Copyright © 2011-2022 走看看