现在我试图用for循环语句实现如下所示的位图,
但是我得到了如下输出图像,
我刚刚使用如下的循环语句。
for ( int y = 0; y < Picture_y_; y++)
for ( int x = 0; x < Picture_x_; x++)
{
_Copy_Pixel_[((y*Picture_y_ * 3) + x * 3 + 0)] = _Orgin_Pixel_[y*Picture_y_ + x];//B
_Copy_Pixel_[((y*Picture_y_ * 3) + x * 3 + 1)] = _Orgin_Pixel_[y*Picture_y_ + x];//G
_Copy_Pixel_[((y*Picture_y_ * 3) + x * 3 + 2)] = _Orgin_Pixel_[y*Picture_y_ + x];//R
}
我不知道为什么我的形象有异常。
这是完整的代码。
#include <windows.h>
#include "CyApi.h"
#define WIDTHBYTES(w, bitcount) ((((w)*(bitcount)+31)& ~31) >> 3)
#define WIDTHBYTES_(bits) (((bits)+31)/32*4)
int RAW2DIB(HWND);
unsigned char *_Orgin_Pixel_;
unsigned char *_Copy_Pixel_;
unsigned int W_Image = 2560;
unsigned int H_Image = 1920;
unsigned int widthbytes = WIDTHBYTES(W_Image, 24);
unsigned int S_Image = widthbytes * H_Image;
BITMAPINFO *BmInfo;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPWSTR lpszClass = L"First";
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance
, LPWSTR lpszCmdParam, int nCmdShow)
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
WndClass.cbClsExtra=0;
WndClass.cbWndExtra=0;
WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
WndClass.hInstance=hInstance;
WndClass.lpfnWndProc=(WNDPROC)WndProc;
WndClass.lpszClassName=lpszClass;
WndClass.lpszMenuName=NULL;
WndClass.style=CS_HREDRAW | CS_VREDRAW;
RegisterClass(&WndClass);
hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, (HMENU)NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
while (GetMessage(&Message, 0, 0, 0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return Message.wParam;
}
int RAW2DIB(HWND hWnd)
{
unsigned int Picture_x_, Picture_y_, Bitdepth;
LONG len;
BmInfo = (BITMAPINFO*)malloc(sizeof(BITMAPINFO)
BmInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BmInfo->bmiHeader.biWidth = W_Image;
BmInfo->bmiHeader.biHeight = H_Image;
BmInfo->bmiHeader.biPlanes = 1;
BmInfo->bmiHeader.biBitCount = 24;
BmInfo->bmiHeader.biCompression = BI_RGB;
BmInfo->bmiHeader.biSizeImage = (((W_Image * 24 + 31) & ~31) >> 3) * H_Image;
BmInfo->bmiHeader.biXPelsPerMeter = 0;
BmInfo->bmiHeader.biYPelsPerMeter = 0;
BmInfo->bmiHeader.biClrImportant = 0;
BmInfo->bmiHeader.biClrUsed = 0;
_Copy_Pixel_ = (BYTE*)VirtualAlloc(NULL, sizeof(BYTE)*(S_Image), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
Picture_x_ = W_Image;
Picture_y_ = H_Image;
len = WIDTHBYTES_(2560 * 24) * 1920;
_Orgin_Pixel_ = (BYTE*)VirtualAlloc(NULL, sizeof(BYTE)*(W_Image* H_Image), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
for (int y = 0; y < H_Image; y++)
for (int x = 0; x < W_Image; x++)
_Orgin_Pixel_[y * H_Image + x] = x%255;
for ( int y = 0; y < Picture_y_; y++)
for ( int x = 0; x < Picture_x_; x++)
{
_Copy_Pixel_[((y*Picture_y_ * 3) + x * 3 + 0)] = _Orgin_Pixel_[y*Picture_y_ + x];//B
_Copy_Pixel_[((y*Picture_y_ * 3) + x * 3 + 1)] = _Orgin_Pixel_[y*Picture_y_ + x];//G
_Copy_Pixel_[((y*Picture_y_ * 3) + x * 3 + 2)] = _Orgin_Pixel_[y*Picture_y_ + x];//R
}
InvalidateRect(hWnd, NULL, FALSE);
return 0;
}
...
case WM_PAINT
SetDIBitsToDevice(hdc, 0, 0, W_Image, H_Image, 0, 0, 0, H_Image, _Copy_Pixel_, BmInfo, DIB_RGB_COLORS);
答案 0 :(得分:0)
在循环中,您不会考虑扫描线尺寸。位图图像由扫描线组成,扫描线由像素组成,像素由位(字节)组成。扫描线在最近的下一个字边界上排列。
所以len
不等于2560 * 1920
,而neitrher可以将像素作为Copy_Pixel [y * 1920 + x]`进行寻址。
len
应为WIDTHBYTES_(2560*BmInfo->bmiHeader.biBitCount) * 1920
寻址像素应为:
Copy_Pixel[WIDTHBYTES_(x*BmInfo->bmiHeader.biBitCount) + y]
<小时/> 编辑:
你的循环应该是:
int scanlinesize= WIDTHBYTES_(Picture_x_*24);
for ( int y = 0; y < Picture_y_; y++)
for ( int x = 0; x < Picture_x_; x++)
{
_Copy_Pixel_[((y*scanlinesize) + x * 3 + 0)] = _Orgin_Pixel_[y*Picture_y_ + x];//B
_Copy_Pixel_[((y*scanlinesize) + x * 3 + 1)] = _Orgin_Pixel_[y*Picture_y_ + x];//G
_Copy_Pixel_[((y*scanlinesize) + x * 3 + 2)] = _Orgin_Pixel_[y*Picture_y_ + x];//R
}
答案 1 :(得分:0)
这是粗糙的骨架。
unsigned char *_Orgin_Pixel_;
unsigned char *_Copy_Pixel_;
unsigned int W_Image = 2560;
unsigned int H_Image = 1920;
缓冲区是无符号字符,宽度为2560,高度为1920
这一行告诉我们图像的宽度(以字节为单位)是W_Image的复杂函数。它被填充到整数32位字。这是关键。
BmInfo->bmiHeader.biSizeImage = (((W_Image * 24 + 31) & ~31) >> 3) * H_Image;
int scanlinesize= (((W_Image * 24 + 31) & ~31) >> 3)
原始图像的扫描线宽度为
Picture_x = (W_Image * 8 + 31 & ~31) >> 3;
我猜。请查看文档。
for ( int y = 0; y < Picture_y_; y++)
for ( int x = 0; x < Picture_x_; x++)
{
_Copy_Pixel_[((y*Picture_x) + x * 3 + 0)] = _Orgin_Pixel_[y*scanlinesize + x];//B
_Copy_Pixel_[((y*Picture_x) + x * 3 + 1)] = _Orgin_Pixel_[y*scalinesize + x];//G
_Copy_Pixel_[((y*Picture_x) + x * 3 + 2)] = _Orgin_Pixel_[y*scanlinesize + x];//R
}
要调试它,首先将目标中的所有内容设置为红色。这有用吗,你得到一个完全红色的图像?然后设置从红色到黑色的颜色渐变。那样有用吗?一旦你完成了这两个步骤,你就非常有信心正确地访问缓冲区。现在任何进一步的问题都必须在源头。