Raw bitmap data in jpeg or png C ++

I have a bytearray where every three bytes describe 1 pixel (RGB). The challenge is to convert it to jpeg or png.

In fact, I use Zint (open source lib to generate barcodes), which uses libpng to create an image file and save it to the file system, but in the Zintthe function png_plot (), in addition to generating the image, it also saves it to disk. which is undesirable.

As a result, I think there are two ways:
1.from bitmap bytearray to bmp -> jpeg / png (using some other lib)
2. Recording hook or similar to png_plot ()

Can you give me some advice? Thanks.

Update: for @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);
+4
source share
3 answers

The easiest way to convert between image formats is to use the CImage class, shared by MFC and ATL, and defined in the atlimage.h header file.

 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 an RGB buffer and want to create a bitmap: just create and save the bitmap header in a file and add an RGB buffer to it.

To create a header, you can use BITMAPFILEHEADER , BITMAPINFOHEADER and RGBQUAD from the GDI defined in the WinGDI.h header

Here is an example of how to populate 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 in mind that bitmaps are stored in reverse order and that the image width should be aligned to DWORD, except for Rm-compressed bitmaps (they must be a multiple of 4 bytes, add indentation if necessary).

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

When saving the buffer, add the required padding to each line ...


To summarize, these are the necessary steps to create a bitmap file from the rgb buffer:

 //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 } } 
+3
source

I used the ATL CImage class.

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

Is there a way to do this differently than using SetPixel? I am experiencing serious performance issues with SetPixel and need an alternative method ... I tried using CreateDIBSection to no avail. The barcode is displayed oblique and unusable. here is my code for this:

 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 gives the same result is the following:

  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
source

All Articles