Reputation: 1671
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:
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
Upvotes: 2
Views: 1699
Reputation: 3317
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;
Upvotes: 6