将原始位图数据转换为JPEG或PNG格式的C++代码

6
我有一个字节数组,其中每三个字节描述一个像素(RGB)。任务是将其转换为jpeg或png格式。
实际上,我正在使用Zint(用于生成条形码的开源库),它使用libpng生成图像文件并将其保存到文件系统中,但在Zint中,函数png_plot() 除了生成图像还将其保存在磁盘上,这是不希望发生的情况。
因此,我认为有两种方法:
1.从位图字节数组转换为bmp -> jpeg / png(使用其他一些库)
2.编写钩子或类似的东西来替代png_plot()函数
你能给我一些建议吗? 谢谢。
更新:对@peacemaker

FILE *f;<br>
zint_symbol *my_symbol;<br>
my_symbol = ZBarcode_Create();<br>

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

你能展示一下你正在使用的代码吗? - peacemaker
3个回答

4
为了在图像格式之间进行转换,最简单的方法是使用由MFCATL共享的CImage类,该类定义在头文件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缓冲区添加到其中。
要创建标题,可以使用BITMAPFILEHEADERBITMAPINFOHEADERRGBQUAD结构,这些结构在WinGDI.h头文件中由GDI定义。
以下是如何填充标题数据的示例:
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;

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


总结一下,创建位图文件需要以下步骤:
//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
   }
}

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接