【问题标题】:Gdiplus::Bitmap to BYTE array?Gdiplus::Bitmap 到 BYTE 数组?
【发布时间】:2011-03-21 09:08:15
【问题描述】:

这是我的尝试(丑陋的 GDI+ GDI 混合...)

// ...
BYTE               pixels[BMP_WIDTH * BMP_HEIGHT * BMP_BPP];
HBITMAP            hBitmap;
Gdiplus::Bitmap    cBitmap(BMP_WIDTH, BMP_HEIGHT, PixelFormat32bppRGB);
Gdiplus::Graphics  cGraphics(&cBitmap);
Gdiplus::Pen       cPen(Gdiplus::Color(255, 255, 0, 0));

cGraphics.DrawRectangle(&cPen, 0, 0, cBitmap.GetWidth() - 1, cBitmap.GetHeight() - 1);

// and here it get's real ugly, I'd like to change that...
cBitmap.GetHBITMAP(Gdiplus::Color(255, 255, 255), &hBitmap);
GetBitmapBits(hBitmap, sizeof(pixels), pixels);
// ...

有人告诉我要使用 LockBits,但我真的不明白怎么做。我试过了,但我失败了,所以我也不打算发布那个尝试。

【问题讨论】:

    标签: c++ gdi+ bitmap


    【解决方案1】:

    您可以使用Bitmap::LockBits 来访问原始数据数组。 Here 您可以阅读有关如何使用 Bitmap::LockBits 的信息。

    【讨论】:

      【解决方案2】:

      您是否尝试在创建位图时提供字节:

      int width = BMP_WIDTH;
      int height = BMP_HEIGHT;
      int stride = 4 * width;
      BYTE bytes[stride * height];
      
      Gdiplus::Bitmap  cBitmap(width, height, stride, PixelFormat32bppRGB, bytes);
      

      【讨论】:

      • 这是一个简单的案例,在一般情况下应该注意stride % 4 == 0(并非所有 3 个分量 RGB 都有效)。
      【解决方案3】:

      下面是我将如何使用 GdiPlusBitmap.h 中定义的 GDIPlus Bitmap.LockBits 方法:

      请注意,由于位图通常是 DWORD 对齐的,您可能希望丢弃对齐所需的这些未使用的数据,正如 malat 正确评论的那样..

          Gdiplus::BitmapData bitmapData;
          Gdiplus::Rect rect(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
      
          //get the bitmap data
          if(Gdiplus::Ok == bitmap.LockBits(
                              &rect, //A rectangle structure that specifies the portion of the Bitmap to lock.
                              Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeWrite, //ImageLockMode values that specifies the access level (read/write) for the Bitmap.
                              bitmap.GetPixelFormat(),// PixelFormat values that specifies the data format of the Bitmap.
                              &bitmapData //BitmapData that will contain the information about the lock operation.
                              ))
          {
               //get the lenght of the bitmap data in bytes
               int len = bitmapData.Height * std::abs(bitmapData.Stride);
      
               BYTE* buffer = new BYTE[len];
               memcpy(bitmapData.Scan0, buffer, len);//copy it to an array of BYTEs
      
               //... 
      
               //cleanup
               bitmap.UnlockBits(&bitmapData);        
               delete []buffer;
          }
      

      【讨论】:

      • 不,这不起作用,bitmapData.StridebitmapData.Width * sizeof( bitmapData.PixelFormat) 不同,因为它还包含未使用的数据。这需要一个 for 循环来丢弃未使用的数据。
      【解决方案4】:

      这是我写的东西,它在传递文件路径时返回一个向量向量(其中包含的向量表示图像中的像素列):

      #include <vector>
      std::vector<std::vector<unsigned>> getPixels(const wchar_t *filename, int &width, int &height) {
          Gdiplus::Bitmap bitmap(filename);
      
          //Pass up the width and height, as these are useful for accessing pixels in the vector o' vectors.
          width = bitmap.GetWidth();
          height = bitmap.GetHeight();
      
          auto *bitmapData = new Gdiplus::BitmapData;
      
          //Lock the whole bitmap so we can read pixel data easily.
          Gdiplus::Rect rect(0, 0, width, height);
          bitmap.LockBits(&rect, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, bitmapData);
      
          //Get the individual pixels from the locked area.
          auto *pixels = static_cast<unsigned *>(bitmapData->Scan0);
      
          //Vector of vectors; each vector is a column.
          std::vector<std::vector<unsigned>> resultPixels(width, std::vector<unsigned>(height));
      
          const int stride = abs(bitmapData->Stride);
          for(int x = 0; x < width; x++) {
              for(int y = 0; y < height; y++) {
                  //Get the pixel colour from the pixels array which we got earlier.
                  const unsigned pxColor = pixels[y * stride / 4 + x];
      
                  //Get each individual colour component. Bitmap colours are in reverse order.
                  const unsigned red = (pxColor & 0xFF0000) >> 16;
                  const unsigned green = (pxColor & 0xFF00) >> 8;
                  const unsigned blue = pxColor & 0xFF;
      
                  //Combine the values in a more typical RGB format (as opposed to the bitmap way).
                  const int rgbValue = RGB(red, green, blue);
      
                  //Assign this RGB value to the pixel location in the vector o' vectors.
                  resultPixels[x][y] = rgbValue;
              }
          }
      
          //Unlock the bits that we locked before.
          bitmap.UnlockBits(bitmapData);
          return resultPixels;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-28
        • 2019-01-03
        • 1970-01-01
        • 2011-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多