循环问题的位图

时间:2016-12-31 10:58:33

标签: c image-processing

现在我试图用for循环语句实现如下所示的位图,

Desired result

但是我得到了如下输出图像,

Current result

我刚刚使用如下的循环语句。

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

2 个答案:

答案 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

    }

要调试它,首先将目标中的所有内容设置为红色。这有用吗,你得到一个完全红色的图像?然后设置从红色到黑色的颜色渐变。那样有用吗?一旦你完成了这两个步骤,你就非常有信心正确地访问缓冲区。现在任何进一步的问题都必须在源头。