RGBA数据使用c++存本地bmp文件

我从内存中的位图想得到其中的buffer数据,而且是32位的rgba 格式的,用下边的函数:

内存中的位图得buffer的方法:其中的回调可以得到数据

void CPaintManagerUI::BitmapCreate(HWND hWnd,HDC dc)
{
	HDC hdcWindow;
	HDC hdcMemDC = NULL;
	HBITMAP hbmScreen = NULL;
	BITMAP bmpScreen;

	// Retrieve the handle to a display device context for the client 
	hdcWindow = dc; 

	// Create a compatible DC which is used in a BitBlt from the window DC
	hdcMemDC = CreateCompatibleDC(hdcWindow);

	if (!hdcMemDC)
	{
		MessageBox(hWnd, "CreateCompatibleDC has failed", "Failed", MB_OK);
		goto done;
	}

	// Get the client area for size calculation
	RECT rcClient;
	GetWindowRect(hWnd, &rcClient);

	//This is the best stretch mode
	SetStretchBltMode(hdcWindow, HALFTONE);
	// Create a compatible bitmap from the Window DC
	hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);

	if (!hbmScreen)
	{
		MessageBox(hWnd, "CreateCompatibleBitmap Failed", "Failed", MB_OK);
		goto done;
	}

	// Select the compatible bitmap into the compatible memory DC.
	SelectObject(hdcMemDC, hbmScreen);

	// Bit block transfer into our compatible memory DC.
	if (!BitBlt(hdcMemDC,
		0, 0,
		rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
		hdcWindow,
		0, 0,
		SRCCOPY))
	{
		MessageBox(hWnd, "BitBlt has failed", "Failed", MB_OK);
		goto done;
	}

	// Get the BITMAP from the HBITMAP
	GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen);

	BITMAPFILEHEADER   bmfHeader;
	BITMAPINFOHEADER   bi;

	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = bmpScreen.bmWidth;
	bi.biHeight = bmpScreen.bmHeight;
	bi.biPlanes = 1;
	bi.biBitCount = 32;
	bi.biCompression = BI_RGB;
	bi.biSizeImage = 0;
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrUsed = 0;
	bi.biClrImportant = 0;

	DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;

	// Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that 
	// call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc 
	// have greater overhead than HeapAlloc.
	HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);
	char *lpbitmap = (char *)GlobalLock(hDIB);

	// Gets the "bits" from the bitmap and copies them into a buffer 
	// which is pointed to by lpbitmap.
	GetDIBits(hdcWindow, hbmScreen, 0,
		(UINT)bmpScreen.bmHeight,
		lpbitmap,
		(BITMAPINFO *)&bi, DIB_RGB_COLORS);
	
	if (m_fun_ptr) {
		m_fun_ptr(lpbitmap, bmpScreen.bmWidth, bmpScreen.bmHeight);
	}
	bmp_write((unsigned char*)lpbitmap, bmpScreen.bmWidth, bmpScreen.bmHeight,
	"d:\\123.bmp");

	/*
	// A file is created, this is where we will save the screen capture.
	HANDLE hFile = CreateFile("d:\\captureqwsx.bmp",
		GENERIC_WRITE,
		0,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL, NULL);

	// Add the size of the headers to the size of the bitmap to get the total file size
	DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

	//Offset to where the actual bitmap bits start.
	bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);

	//Size of the file
	bmfHeader.bfSize = dwSizeofDIB;

	//bfType must always be BM for Bitmaps
	bmfHeader.bfType = 0x4D42; //BM   

	DWORD dwBytesWritten = 0;
	WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
	WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
	WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
	*/
	//Unlock and Free the DIB from the heap
	GlobalUnlock(hDIB);
	GlobalFree(hDIB);

	//Close the handle for the file that was created
	//CloseHandle(hFile);

	//Clean up
done:
	DeleteObject(hbmScreen);
	DeleteObject(hdcMemDC);
	ReleaseDC(hWnd, hdcWindow);
}

 

图像和视频开发中,经常需要将过程中的裸数据存到本地来看一下数据是否正确。由于bmp文件不需要进行编码所以称为了debug中常用的一种测试格式。在这里,保存一个不使用非c自带外部库保存本地bmp文件的函数,以免日后重复造车。

 

[cpp] view plain copy

  1. //test function for save local bmp  
  2. int bmp_write(unsigned char *image, int imageWidth, int imageHeight, char *filename)  
  3. {  
  4.     unsigned char header[54] = {  
  5.       0x42, 0x4d, 0, 0, 0, 0, 0, 0, 0, 0,  
  6.         54, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 32, 0,  
  7.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
  8.         0, 0, 0, 0  
  9.     };  
  10.   
  11.     long file_size = (long)imageWidth * (long)imageHeight * 4 + 54;  
  12.     header[2] = (unsigned char)(file_size &0x000000ff);  
  13.     header[3] = (file_size >> 8) & 0x000000ff;  
  14.     header[4] = (file_size >> 16) & 0x000000ff;  
  15.     header[5] = (file_size >> 24) & 0x000000ff;  
  16.   
  17.     long width = imageWidth;  
  18.     header[18] = width & 0x000000ff;  
  19.     header[19] = (width >> 8) &0x000000ff;  
  20.     header[20] = (width >> 16) &0x000000ff;  
  21.     header[21] = (width >> 24) &0x000000ff;  
  22.   
  23.     long height = imageHeight;  
  24.     header[22] = height &0x000000ff;  
  25.     header[23] = (height >> 8) &0x000000ff;  
  26.     header[24] = (height >> 16) &0x000000ff;  
  27.     header[25] = (height >> 24) &0x000000ff;  
  28.   
  29.     char fname_bmp[128];  
  30.     sprintf(fname_bmp, "%s.bmp", filename);  
  31.   
  32.     FILE *fp;  
  33.     if (!(fp = fopen(fname_bmp, "wb")))  
  34.       return -1;  
  35.   
  36.     fwrite(header, sizeof(unsigned char), 54, fp);  
  37.     fwrite(image, sizeof(unsigned char), (size_t)(long)imageWidth * imageHeight * 4, fp);  
  38.   
  39.     fclose(fp);  
  40.     return 0;  
  41. }  

使用的方法如下:

 

[cpp] view plain copy

  1. char pc[] = "/data/a.dat";  
  2. bmp_write(raw_image, pic_width, pic_height);  

第一,这个函数接受的裸数据为32位的rgba数据。

第二,只是做save用,所以有可能应该是bgra数据 。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要将 BMP 图像转换为 PNG 格式并添加透明度,您可以使用 C++ 的第三方库,例如 libpng 和 zlib。以下是一个简单的示例代码,它使用这些库来执行所需的 BMP 到 PNG 转换和透明度添加: ``` #include <iostream> #include <fstream> #include <cstring> #include <png.h> #include "CImage.h" void write_png_file(char* file_name, int width, int height, png_bytep* row_pointers) { FILE* fp = fopen(file_name, "wb"); if (!fp) { std::cerr << "Error: Failed to open PNG file for writing\n"; return; } png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!png_ptr) { std::cerr << "Error: Failed to create PNG write structure\n"; fclose(fp); return; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { std::cerr << "Error: Failed to create PNG info structure\n"; png_destroy_write_struct(&png_ptr, nullptr); fclose(fp); return; } if (setjmp(png_jmpbuf(png_ptr))) { std::cerr << "Error: Failed to initialize PNG write\n"; png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return; } png_init_io(png_ptr, fp); if (setjmp(png_jmpbuf(png_ptr))) { std::cerr << "Error: Failed to write PNG image header\n"; png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return; } png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); if (setjmp(png_jmpbuf(png_ptr))) { std::cerr << "Error: Failed to write PNG image data\n"; png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return; } png_write_image(png_ptr, row_pointers); if (setjmp(png_jmpbuf(png_ptr))) { std::cerr << "Error: Failed to complete PNG write\n"; png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return; } png_write_end(png_ptr, nullptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); } void bmp_to_png_with_alpha(const char* bmp_file, const char* png_file) { CImage img; if (!img.Load(bmp_file)) { std::cerr << "Error: Failed to load BMP file\n"; return; } int width = img.GetWidth(); int height = img.GetHeight(); png_bytep* row_pointers = new png_bytep[height]; for (int y = 0; y < height; ++y) { row_pointers[y] = new png_byte[4 * width]; for (int x = 0; x < width; ++x) { COLORREF color = img.GetPixel(x, y); png_byte red = GetRValue(color); png_byte green = GetGValue(color); png_byte blue = GetBValue(color); png_byte alpha = (color != RGB(255, 0, 255)) ? 0xFF : 0x00; png_bytep pixel = &(row_pointers[y][4 * x]); pixel[0] = red; pixel[1] = green; pixel[2] = blue; pixel[3] = alpha; } } write_png_file(png_file, width, height, row_pointers); for (int y = 0; y < height; ++y) { delete[] row_pointers[y]; } delete[] row_pointers; } int main() { const char* bmp_file = "test.bmp"; const char* png_file = "test.png"; bmp_to_png_with_alpha(bmp_file, png_file); return 0; } ``` 在这个示例中,我们首先使用 CImage 类加载 BMP 图像文件。然后,我们遍历每个像素,并将其值转换为 PNG 格式,同时添加透明度(即,如果像素值为 RGB(255, 0, 255),则将其 alpha 值设置为 0,否则将其 alpha 值设置为 255)。最后,我们使用 write_png_file() 函数将转换后的 PNG 图像写入磁盘。 请注意,该示例仅提供了一个基本的转换功能。如果您需要处理大量图像或需要更高级的功能(例如,调整大小、旋转或滤镜等),则可能需要使用更强大的图像处理库,例如 OpenCV 或 ImageMagick。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值