我有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);
答案 0 :(得分:3)
为了在图像格式之间进行转换,最简单的方法是使用CImage和MFC共享的类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中的BITMAPINFOHEADER,RGBQUAD和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);
请记住,位图是颠倒存储的,并且除了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);