简体   繁体   English

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

[英]raw bitmap data to jpeg or png C++

I have bytearray where every three bytes describes 1 pixel (RGB). 我有bytearray,其中每三个字节描述1个像素(RGB)。 The task is to convert it to jpeg or png. 任务是将其转换为jpeg或png。

Actually, I am using Zint (open source lib for generating barcodes) that uses libpng to generate image file and save it to file system, but in Zintthe function png_plot() except generating image also save it on disk which is undesirable. 实际上,我使用Zint(用于生成条形码的开源库)使用libpng生成图像文件并将其保存到文件系统,但在Zint中,除了生成图像之外,函数png_plot()还将其保存在磁盘上,这是不合需要的。

As result I think there two ways: 结果我认为有两种方式:
1. from bitmap bytearray to bmp -> jpeg / png (using some other lib) 1.从位图bytearray到bmp - > jpeg / png(使用其他一些lib)
2. writing hook or some similar to png_plot() 2.写钩子或类似于png_plot()

Can you give me some advices? 你能给我一些建议吗? Thank you. 谢谢。

Upd: for @peacemaker 更新:对于@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);

In order to convert between image formats, the easiest way would be using the class CImage shared by MFC and ATL and defined in the header file atlimage.h. 为了在图像格式之间进行转换,最简单的方法是使用由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");





If you have a RGB buffer and want to create a bitmap: just create and save a bitmap header into a file and add the RGB buffer to it. 如果您有一个RGB缓冲区并想要创建一个位图:只需创建一个位图标题并将其保存到文件中,然后将RGB缓冲区添加到该文件中。

To create the header you can use the BITMAPFILEHEADER , BITMAPINFOHEADER and RGBQUAD structures from GDI defined in the header WinGDI.h 要创建标头,可以使用标头WinGDI.h中定义的GDI中BITMAPFILEHEADERBITMAPINFOHEADERRGBQUAD结构。

Here is an example on how to fill the header data: 以下是如何填充标题数据的示例:

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


Keep into account that the bitmaps are stored upside-down and that the width of the image must be aligned on a DWORD except for RLE-compressed bitmaps.(they must be multiple of 4 bytes, add a padding if necessary). 请注意位图是颠倒存储的,并且图像的宽度必须在DWORD上对齐,但RLE压缩的位图除外(它们必须是4个字节的倍数,必要时添加填充)。

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

When saving your buffer, add the needed padding to each row... 保存缓冲区时,为每行添加所需的填充...


Summarizing, these are the needed steps to create a bitmap file from a rgb buffer: 总而言之,这些是从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
   }
}

I used the CImage Class from ATL. 我使用了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);

is there anyway to do this other than using SetPixel? 除了使用SetPixel之外,还有其他方法吗? I am experiencing major performance issues with SetPixel and need an alternative method... I have tried using CreateDIBSection to no avail. 我遇到了SetPixel的主要性能问题,需要一种替代方法......我尝试使用CreateDIBSection无济于事。 The barcode displays slanted and is unusable. 条形码显示倾斜且无法使用。 here is my code for that: 这是我的代码:

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

Another option that produces the same result is this: 产生相同结果的另一个选项是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM