我试图加载一个位图文件,并在Windows上的C++程序中显示图像。它看起来几乎没有问题,但由于某些原因,它似乎有点水平挤压,并且在图像的右端开始重复。
另外,如果是黑白色,颜色看起来很好,但如果是红色,它就会出现各种不同颜色的条纹,所以看起来我没有正确处理RGBA值,因为它们是正确的,但我不确定它们是如何布局的。
以下是我程序中图像的一些截图(它们是扑克牌图像)。
黑白:
红色:
这是红心2的源码文件。
这是我的代码,如果要我猜的话,我想问题出在了这里 debug_render_bitmap
功能或 debug_load_bitmap
函数。(注意:我使用CPU将窗口位图渲染到屏幕上,存储在一个全局缓冲区中)。
#include <windows.h>
#include <stdint.h>
struct win32_offscreen_buffer {
BITMAPINFO info;
void *memory;
int width;
int height;
int bytes_per_pixel;
int pitch;
};
struct read_file_result {
unsigned int contents_size;
void *contents;
};
struct bitmap_result {
BITMAPFILEHEADER *file_header;
BITMAPINFOHEADER *info_header;
unsigned int *pixels;
unsigned int stride;
};
win32_offscreen_buffer global_buffer;
bool should_quit = false;
uint32_t safe_truncate_uint64(uint64_t value) {
uint32_t result = (uint32_t)value;
return result;
}
void free_file_memory(void *memory) {
if (memory) {
VirtualFree(memory, 0, MEM_RELEASE);
}
}
read_file_result read_entire_file(LPCSTR filename) {
read_file_result result = {};
HANDLE file_handle = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (file_handle != INVALID_HANDLE_VALUE) {
LARGE_INTEGER file_size;
if(GetFileSizeEx(file_handle, &file_size)) {
uint32_t file_size32 = safe_truncate_uint64(file_size.QuadPart);
result.contents = VirtualAlloc(0, file_size32, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (result.contents) {
DWORD bytes_read;
if (ReadFile(file_handle, result.contents, file_size32, &bytes_read, 0) && (file_size32 == bytes_read)) {
// File read successfully.
result.contents_size = file_size32;
} else {
// TODO: Logging
free_file_memory(result.contents);
result.contents = 0;
}
} else {
// TODO: Logging
}
} else {
// TODO: Logging
}
CloseHandle(file_handle);
} else {
// TODO: Logging
}
return result;
}
bitmap_result debug_load_bitmap(char* filename) {
bitmap_result bmp_result = {};
read_file_result file_result = read_entire_file(filename);
unsigned char *contents = (unsigned char *)file_result.contents;
bmp_result.file_header = (BITMAPFILEHEADER *)contents;
bmp_result.info_header = (BITMAPINFOHEADER *)(contents + 14);
bmp_result.pixels = (unsigned int *)(contents + bmp_result.file_header->bfOffBits);
bmp_result.stride = ((((bmp_result.info_header->biWidth * bmp_result.info_header->biBitCount) + 31) & ~31) >> 3);
return bmp_result;
}
void debug_render_bitmap(bitmap_result bmp) {
int width = bmp.info_header->biWidth;
int height = bmp.info_header->biHeight;
unsigned char *dest_row = (unsigned char *)global_buffer.memory;
unsigned char *source_row = (unsigned char *)(bmp.pixels + ((bmp.stride / 4) * (height - 1)));
for (int y = 0; y < height; y++) {
unsigned int *dest = (unsigned int *)dest_row;
unsigned int *source = (unsigned int *)source_row;
for (int x = 0; x < width; x++) {
*dest = *source;
dest++;
source++;
}
dest_row += global_buffer.pitch;
source_row -= bmp.stride;
}
}
如果有帮助的话,这里是位图信息头值的截图。
如果有人能告诉我这里发生了什么,那将是非常感激的。
对于绘制位图,有更简单的方法。你不需要自己去解析.bmp文件。给两个例子如下,你可以试试。
第一个方法使用 LoadImage
功能. 参考 "如何在窗口上绘制图像?"
case WM_CREATE:
{
hBitmap = (HBITMAP)LoadImage(hInst, L"C:\\projects\\native_poker\\card-BMPs\\c08.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
BITMAP bitmap;
HDC hdcMem;
HGDIOBJ oldBitmap;
hdc = BeginPaint(hWnd, &ps);
hdcMem = CreateCompatibleDC(hdc);
oldBitmap = SelectObject(hdcMem, hBitmap);
GetObject(hBitmap, sizeof(bitmap), &bitmap);
BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, oldBitmap);
DeleteDC(hdcMem);
EndPaint(hWnd, &ps);
}
break;
第二种方法使用GDI+。 参考 "加载和显示位图".
#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
//...
VOID OnPaint(HDC hdc)
{
Graphics graphics(hdc);
Image *image = Image::FromFile(L"C:\\projects\\native_poker\\card-BMPs\\c08.bmp");
graphics.DrawImage(image, 10, 10);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
OnPaint(hdc);
EndPaint(hWnd, &ps);
}
break;
//...
}