Question

UPDATE:

Thanks to Denis Anisimov I solved my problem by replacing:

for (int i = 0; i < Width * Height; i++)
    {
        pRgb[0] = RValue;
        pRgb[1] = GValue;
        pRgb[2] = BValue;
        pRgb += 3;
    }

with:

int BytesPerLine = Width * 3;
if (BytesPerLine % 4 != 0)
    BytesPerLine += 4 - BytesPerLine % 4;
PBYTE Line = NULL;
for (int y = 0; y < Height; y++) 
{
    Line = pRgb;
    for (int x = 0; x < Width; x++) 
    {
        Line[0] = RValue;
        Line[1] = GValue;
        Line[2] = BValue;
        Line += 3;
    }
    pRgb += BytesPerLine;
}

When creating device independent bitmap I sometimes get strange line artifacts. It only occurs when I change window, in which I draw, width. During resize I delete old bitmap and create new using custom function. Because I have direct access to bitmap's bits, I change their colors directly, but that is where problem occurs (I think), because FillRect works perfectly. I may be not accessing bits pointer correctly. Here are pictures when it works and other with artifacts:

enter image description here enter image description here

This code shows how I draw in window:

case WM_PAINT:
    {
        PAINTSTRUCT ps;
        BeginPaint(hWnd, &ps);
        Painter Paint;
        if (temp != NULL)
        {
            DeleteObject(temp);
            temp = NULL;
        }
        temp = Paint.Create24BitBitmap(NULL, ps.rcPaint.right - ps.rcPaint.left - 5, ps.rcPaint.bottom - ps.rcPaint.top - 5, 20, 70, 0);
        HDC MemoryDC = CreateCompatibleDC(ps.hdc);
        SelectObject(MemoryDC, temp);
        BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left - 5, ps.rcPaint.bottom - ps.rcPaint.top - 5, MemoryDC, 0, 0, SRCCOPY);
        DeleteDC(MemoryDC);
        EndPaint(hWnd, &ps);
    }
    break;
case WM_NCPAINT:
    {
        RedrawWindow(hWnd, NULL, NULL, RDW_ERASENOW | RDW_INVALIDATE | RDW_INTERNALPAINT);
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    break;

And this one shows how I create bitmap:

HBITMAP Create24BitBitmap(HDC *hDC, int Width, int Height, BYTE RValue, BYTE GValue, BYTE BValue)
    {
        Width = ((Width < 1)?1:Width);
        Height = ((Height < 1)?1:Height);
        RValue = ((RValue > 254)?255:((RValue < 0)?0:RValue));
        GValue = ((GValue > 254)?255:((GValue < 0)?0:GValue));
        BValue = ((BValue > 254)?255:((BValue < 0)?0:BValue));

        HDC MemoryDC = NULL;
        if (hDC != NULL)
            MemoryDC = CreateCompatibleDC(*hDC);
        else
            MemoryDC = CreateCompatibleDC(NULL);

        BITMAPINFO BitmapInfo;
        ZeroMemory(&BitmapInfo,sizeof(BITMAPINFO));
        BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        BitmapInfo.bmiHeader.biWidth = Width;
        BitmapInfo.bmiHeader.biHeight = Height;
        BitmapInfo.bmiHeader.biPlanes = 1;
        BitmapInfo.bmiHeader.biBitCount = 24;
        BitmapInfo.bmiHeader.biCompression = BI_RGB;

        PBYTE pRgb = NULL;
        HBITMAP hBitmap = CreateDIBSection(MemoryDC, &BitmapInfo, DIB_RGB_COLORS, (void**)&pRgb, NULL, NULL);

        DeleteDC(MemoryDC);

        if (hBitmap == NULL)
        {
            MessageBox(NULL, TEXT("\"Create24BitBitmap\" function failed."), TEXT("ERROR!"), MB_ICONERROR);
            exit(EXIT_FAILURE);
        }

        for (int i = 0; i < Width * Height; i++)
        {
            pRgb[0] = RValue;
            pRgb[1] = GValue;
            pRgb[2] = BValue;
            pRgb += 3;
        }
        return hBitmap;
    }

So the question would be how to correctly access bitmap bits? Or are there other things that may cause this artifact?

Here you can find compiled program: http://www.putlocker.com/file/D555A03E41032615

Was it helpful?

Solution

This code is wrong:

for (int i = 0; i < Width * Height; i++)
    {
        pRgb[0] = RValue;
        pRgb[1] = GValue;
        pRgb[2] = BValue;
        pRgb += 3;
    }

Start of every line of bitmap must be aligned to 4-byte boundaries.

Update:

You should use something like this:

BytesPerLine := Width * 3;
if BytesPerLine mod 4 <> 0 then
  Inc(BytesPerLine, 4 - BytesPerLine mod 4);
for y := 0 to Height - 1 do
  begin
    Line := pRgb;
    for x := 0 to Width - 1 do
      begin
        Line[0] := RValue;
        Line[1] := GValue;
        Line[2] := BValue;
        Inc(Line, 3);
      end;
    Inc(pRgb, BytesPerLine);
  end;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top