【问题标题】:raw bitmap data to jpeg or png C++原始位图数据到 jpeg 或 png C++
【发布时间】:2012-07-06 05:40:43
【问题描述】:

我有 bytearray,其中每三个字节描述 1 个像素 (RGB)。任务是将其转换为 jpeg 或 png。

实际上,我正在使用 Zint(用于生成条形码的开源库),它使用 libpng 生成图像文件并将其保存到文件系统,但是在 Zint 中,函数 png_plot() 除了生成图像之外还将其保存在磁盘上,这是不可取的。

因此我认为有两种方法:
1. 从位图字节数组到 bmp -> jpeg / png(使用其他一些库)
2. 写hook或者类似png_plot()的东西

你能给我一些建议吗? 谢谢。

更新:@peacemaker


FILE *f;
zint_symbol *my_symbol;
my_symbol = ZBarcode_Create();
ZBarcode_Encode_and_Buffer(my_symbol, (unsigned char *)argv[1], 0, 0);
f = fopen("bitmap.bmp", "w");
fwrite(my_symbol->bitmap, sizeof(*(my_symbol->bitmap)), my_symbol->bitmap_height * my_symbol->bitmap_width, f);
ZBarcode_Delete(my_symbol);
fclose(f);

【问题讨论】:

  • 你能显示你正在使用的代码吗?

标签: c++ bitmap png jpeg libpng


【解决方案1】:

为了在图像格式之间进行转换,最简单的方法是使用 MFCATL 共享并在头文件 atlimage.h 中定义的类 CImage

CImage image; 
HRESULT res = image.Load("in.bmp");
image.Save("out.jpg");
image.Save("out.gif");
image.Save("out.png");
image.Save("out.tif");





如果您有一个 RGB 缓冲区并想创建一个位图:只需创建一个位图头并将其保存到文件中,然后将 RGB 缓冲区添加到其中。

要创建标头,您可以使用标头 WinGDI.h 中定义的 GDI 中的 BITMAPFILEHEADERBITMAPINFOHEADERRGBQUAD 结构

这里是一个如何填充标题数据的示例:

BITMAPINFOHEADER bmpInfoHdr;

bmpInfoHdr.biSize = sizeof(BITMAPINFOHEADER);
bmpInfoHdr.biHeight = nHeight;
bmpInfoHdr.biWidth =  nWidthPadded;
bmpInfoHdr.biPlanes = 1;
bmpInfoHdr.biBitCount = bitsPerPixel;           
bmpInfoHdr.biSizeImage = nHeight * nWidthPadded * nSPP; 
bmpInfoHdr.biCompression =  BI_RGB; 
bmpInfoHdr.biClrImportant = 0;  
bmpInfoHdr.biClrUsed = 0;
bmpInfoHdr.biXPelsPerMeter = 0;
bmpInfoHdr.biYPelsPerMeter = 0;
bmpFileHdr.bfType = BITMAP_FORMAT_BMP;
bmpFileHdr.bfSize =  (DWORD) (sizeof(BITMAPFILEHEADER) + bmpInfoHdr.biSize +
                      sizeof(RGBQUAD)*numColors + bmpInfoHdr.biSizeImage);
bmpFileHdr.bfReserved1 = 0;
bmpFileHdr.bfReserved2 = 0;
bmpFileHdr.bfOffBits = (DWORD) (sizeof(BITMAPFILEHEADER) + bmpInfoHdr.biSize + 
                        sizeof(RGBQUAD)*numColors);


请注意,位图是倒置存储的,并且图像的宽度必须在 DWORD 上对齐,RLE 压缩的位图除外。(它们必须是 4 字节的倍数,必要时添加填充)。

if ((nWidth%4) != 0)
    nPadding = ((nWidth/4) + 1) * 4;

保存缓冲区时,为每一行添加所需的填充...


总而言之,这些是从 rgb 缓冲区创建位图文件所需的步骤:

//1. create bmp header 

//2. save header to file:
 write(file, &bmpFileHdr, sizeof(BITMAPFILEHEADER));
 write(file, &bmpInfoHdr, sizeof(BITMAPINFOHEADER));
 write(file, &colorTable, numColors * sizeof(RGBQUAD));

//3. add rgb buffer to file:
for(int h=0; h<nHeight; h++) {
   for(int w=0; w<nWidth; w++) {
      //3.a) add row to file
      //3.b) add padding for this row to file
   }
}

【讨论】:

    【解决方案2】:

    我使用了来自 ATL 的 CImage 类。

    int width=0, height=0;
    char * val = "9788994774480"; 
    zint_symbol *my_symbol;
    my_symbol = ZBarcode_Create();
    
    //ZBarcode_Encode_and_Buffer(my_symbol,(unsigned char *) val, 0, 0);
    ZBarcode_Encode(my_symbol, (unsigned char *) val, 0);
    ZBarcode_Buffer(my_symbol, 0);
    
    height = my_symbol->bitmap_height;
    width = my_symbol->bitmap_width;
    char * imgBits = my_symbol->bitmap;
    
    CImage img;
    img.Create(width, height, 24 /* bpp */, 0 /* No alpha channel */);
    
    int nPixel = 0;
    for(int row = 0; row < height; row++)
    {
        for(int col = 0; col < width; col++)
        {
            BYTE r = (BYTE)imgBits[nPixel];
            BYTE g = (BYTE)imgBits[nPixel+1];
            BYTE b = (BYTE)imgBits[nPixel+2];
            img.SetPixel(col, row , RGB(r, g, b));
    
            nPixel += 3;
        }
    }
    
    img.Save("CImage.bmp", Gdiplus::ImageFormatBMP);
    
    ZBarcode_Delete(my_symbol);
    

    【讨论】:

      【解决方案3】:

      除了使用 SetPixel 之外,还有其他方法吗?我遇到了 SetPixel 的主要性能问题,需要一种替代方法...我尝试使用 CreateDIBSection 无济于事。条码显示倾斜且无法使用。这是我的代码:

      void *bits = (unsigned char*)(my_symbol->bitmap);
      HBITMAP hBitmap = CreateDIBSection(pDC->GetSafeHdc(), &info, DIB_RGB_COLORS, (void **)&pDestData, NULL, 0);
      memcpy(pDestData, my_symbol->bitmap, info.bmiHeader.biSizeImage);
      img.Attach(hBitmap);
      

      产生相同结果的另一个选项是:

          BITMAPINFO info;
          BITMAPINFOHEADER BitmapInfoHeader;    
          BitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);   
          BitmapInfoHeader.biWidth = my_symbol->bitmap_width;
          BitmapInfoHeader.biHeight = -(my_symbol->bitmap_height);
          BitmapInfoHeader.biPlanes = 1;   
          BitmapInfoHeader.biBitCount = 24;   
          BitmapInfoHeader.biCompression = BI_RGB;  
          BitmapInfoHeader.biSizeImage = 0;   
          BitmapInfoHeader.biXPelsPerMeter = 0;   
          BitmapInfoHeader.biYPelsPerMeter = 0;   
          BitmapInfoHeader.biClrUsed = 0;   
          BitmapInfoHeader.biClrImportant = 0;
      
          info.bmiHeader = BitmapInfoHeader;
      
          HBITMAP hbmp = CreateDIBitmap(dc, &BitmapInfoHeader, CBM_INIT, (LPVOID *)my_symbol->bitmap, (LPBITMAPINFO)&info, DIB_RGB_COLORS);
          img.Attach(hbmp);
      

      【讨论】:

        猜你喜欢
        • 2012-10-06
        • 1970-01-01
        • 1970-01-01
        • 2018-02-28
        • 1970-01-01
        • 2015-04-16
        • 2015-08-10
        • 2010-09-25
        • 2017-03-22
        相关资源
        最近更新 更多