NO

Author Topic: A pattern brush similar to the one used by Photoshop for backgrounds  (Read 2902 times)

laurro

  • Guest
Maybe someone will need such a function.
Code: [Select]

#include <windows.h>


void __stdcall photoshop_fill(HDC, RECT *);
HBRUSH __stdcall photoshop_brush(void);
HBRUSH __stdcall photoshop_brush0(void);
void __stdcall photoshop_fill_slow(HDC);


void __stdcall photoshop_fill(HDC hdc, RECT *rc)
{
BITMAP bmp;
static
unsigned int lut[16] = { 0xffffff, 0xffffff,
0xffffff, 0xffffff, 0xffffff, 0xffffff,
0xffffff, 0xffffff, 0xcccccc, 0xcccccc,
0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc,
0xcccccc, 0xcccccc
};
unsigned int *lutX = NULL;
unsigned int *lutY = NULL;
void *dib = NULL;
DWORD *p = NULL;
BITMAPINFOHEADER *bi = NULL;
UINT x;
long width = 16;
long height = 16;
HGDIOBJ hbitmap = NULL;
HBRUSH brush = NULL;
HBRUSH brush0 = NULL;
POINT pt;
if (hdc)
{
hbitmap = GetCurrentObject(hdc, OBJ_BITMAP);
if (hbitmap)
{
memset(&bmp, 0, sizeof(BITMAP));
if (GetObject(hbitmap, sizeof(BITMAP), &bmp))
{
if (bmp.bmBitsPixel != 1)
{
dib = malloc(1024 + sizeof(BITMAPINFOHEADER));
if (!dib)
return;
else
{
bi = (BITMAPINFOHEADER *)dib;
memset(bi, 0, sizeof(BITMAPINFOHEADER));
bi->biSize = sizeof(BITMAPINFOHEADER);
bi->biWidth = width;
bi->biHeight = -height;
bi->biPlanes = 1;
bi->biBitCount = 32;
bi->biSizeImage = 1024;
bi++;
p = (DWORD *)bi;
lutY = lut;
  y_:
height--;
lutX = lut;
x = width;
  x_:
x--;
*p = *lutX;
*p ^= *lutY;
*p ^= 0xffffff;
p++;
lutX++;
if (x)
goto x_;
lutY++;
if (height)
goto y_;
brush = CreateDIBPatternBrushPt(dib, 0);
free(dib);
if (brush)
{
brush0 = SelectObject(hdc, brush);
GetBrushOrgEx(hdc, &pt);
if (rc)
{
SetBrushOrgEx(hdc, rc->left, rc->top, NULL);
PatBlt(hdc, rc->left, rc->top, rc->right, rc->bottom, PATCOPY);
SetBrushOrgEx(hdc, pt.x, pt.y, NULL);
}
else
{
SetBrushOrgEx(hdc, 0, 0, NULL);
PatBlt(hdc, 0, 0, bmp.bmWidth, bmp.bmHeight, PATCOPY);
SetBrushOrgEx(hdc, pt.x, pt.y, NULL);
}
SelectObject(hdc, brush0);
DeleteObject(brush);
}
}
}
}
}
}
}





HBRUSH __stdcall photoshop_brush(void)
{
static
const BITMAPINFOHEADER bi = { sizeof(BITMAPINFOHEADER), 16, -16, 1, 32, 0, 1024, 0, 0, 0, 0 };
static
const DWORD data[8] = { 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00 };
int index = -1;
int i = 0;
int modulo;
int modulo_temp;
DWORD mask;
DWORD *pixel0 = NULL;
void *dib = malloc(1024 + sizeof(BITMAPINFOHEADER));
if (!dib)
return NULL;
memcpy(dib, &bi, sizeof(BITMAPINFOHEADER));
pixel0 = (DWORD *)dib;
pixel0 += (sizeof(BITMAPINFOHEADER) / sizeof(DWORD));
for (int y = 0; y < 16; y++)
{
for (int x = 0; x < 16; x++)
{
modulo_temp = modulo = i;
modulo_temp >>= 5;
modulo_temp <<= 5;
modulo = modulo - modulo_temp;
if (modulo == 0)
index++;
mask = 1;
mask <<= modulo;
mask &= data[index];
mask >>= modulo;
if (mask)
*pixel0 = 0x00ffffff;
else
*pixel0 = 0x00cccccc;
i++;
pixel0++;
}
}
HBRUSH brush = CreateDIBPatternBrushPt(dib, 0);
free(dib);
return brush;
}





HBRUSH __stdcall photoshop_brush0(void)
{
static
DWORD data[266] = {
0x28, 0x10, 0xfffffff0, 0x200001, 0x0, 0x400, 0x0, 0x0, 0x0, 0x0, 0xffffff,
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xcccccc,
0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x00000000
};
DWORD *p0 = data;
DWORD *p1 = data;
UINT offset = sizeof(BITMAPINFOHEADER) / sizeof(DWORD);
p1 += (offset + 16);
if (!*p1)
{
for (int i = 0; i < 7; i++)
{
p0 = data + offset;
for (int j = 0; j < 16; j++)
{
*p1 = *p0;
p0++;
p1++;
}
}
p0 = p1;
p0--;
for (int i = 0; i < 128; i++)
{
*p1 = *p0;
p0--;
p1++;
}
}
return CreateDIBPatternBrushPt((void *)data, 0);
}





void __stdcall photoshop_fill_slow(HDC hdc)
{
if (hdc)
{
HGDIOBJ hbitmap = GetCurrentObject(hdc, OBJ_BITMAP);
if (hbitmap)
{
BITMAP bmp;
memset(&bmp, 0, sizeof(BITMAP));
if (GetObject(hbitmap, sizeof(BITMAP), &bmp))
{
long width = bmp.bmWidth;
width = (width + 3) & ~3;
long height = bmp.bmHeight;
if (bmp.bmBitsPixel != 1)
{
long size = height;
if (width > height)
size = width;
unsigned int *lut = malloc(size * sizeof(unsigned int));
unsigned int *lutX = NULL;
unsigned int *lutY = NULL;
if (lut)
{
int modulo_temp;
int modulo;
int _switch = 0;
lutX = lut;
for (int i = 0; i < size; i++)
{
modulo_temp = modulo = i;
modulo_temp >>= 3;
modulo_temp <<= 3;
modulo = modulo - modulo_temp;
if (modulo == 0)
{
_switch = ~_switch;
_switch &= 1;
}
if (_switch)
*lutX = 0xffffff;
else
*lutX = 0xcccccc;
lutX++;
}
BITMAPINFO bi;
memset(&bi, 0, sizeof(BITMAPINFO));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = width;
bi.bmiHeader.biHeight = -height;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biSizeImage = (width * height) << 2;
void *pixel0 = NULL;
HBITMAP hBitmap = NULL;
hBitmap = CreateDIBSection(hdc, &bi, 0, &pixel0, NULL, 0);
if (!hBitmap)
{
free(lut);
return;
}
else
{
UINT x;
DWORD *p = (DWORD *)pixel0;
lutY = lut;
  y_:
height--;
lutX = lut;
x = width;
  x_:
x--;
*p = *lutX;
*p ^= *lutY;
*p ^= 0xffffff;
p++;
lutX++;
x--;
*p = *lutX;
*p ^= *lutY;
*p ^= 0xffffff;
p++;
lutX++;
x--;
*p = *lutX;
*p ^= *lutY;
*p ^= 0xffffff;
p++;
lutX++;
x--;
*p = *lutX;
*p ^= *lutY;
*p ^= 0xffffff;
p++;
lutX++;
if (x)
goto x_;
lutY++;
if (height)
goto y_;
HDC hisHDC = CreateCompatibleDC(hdc);
SelectObject(hisHDC, hBitmap);
BitBlt(hdc, 0, 0, bmp.bmWidth, bmp.bmHeight, hisHDC, 0, 0, SRCCOPY);
DeleteDC(hisHDC);
DeleteObject(hBitmap);
free(lut);
}
}
}
}
}
}
}




 There are in fact three(four) functions , but the last one is too slow.
The first function, photoshop_fill(), take two arguments , an HDC and an RECT struct pointer, the last one is optional,
can be NULL, in this case the entire 'hdc' it will be filled with the pattern, otherwise an rectangle described by 'rc' it will
be filled. Data for rc: from point x (rc.left) and y(rc.top) draw an rectangle with width(rc.right) and height(rc.bottom).
The second and the third function are similar, but photoshop_brush0() is slightly more efficient in speed and behavior
than photoshop_brush() with the disadvantage of being much larger in size. They don't take arguments and returns
a brush. The last one it is a ineficient one, is here just because is an example of 'loop unrolling' with bitmaps(very few
real situations permits this kind of optimizations on bitmaps).

 Laur