原始位图数据到jpeg或png C ++

时间:2012-07-05 18:56:16

标签: c++ bitmap png jpeg libpng

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

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

结果我认为有两种方式:
1.从位图bytearray到bmp - > jpeg / png(使用其他一些lib)
2.写钩子或类似于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);

3 个答案:

答案 0 :(得分:3)

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

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中定义的BITMAPFILEHEADER中的BITMAPINFOHEADERRGBQUADGDI结构

以下是有关如何填充标题数据的示例:

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


请记住,位图是颠倒存储的,并且除了RLE压缩的位图之外,图像的宽度必须在DWORD上对齐。(它们必须是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
   }
}

答案 1 :(得分:0)

我使用了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);

答案 2 :(得分:0)

除了使用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);