I didn't like the performance of GetPixel() so I changed the win32 version to
use GetDIBits and do the appropriate transformations. I'm not sure of the real
speed up but I went from 1-2 frames/sec to 12 and the performance issue shifted
to opengl drawing to the screen.
I have a couple of issues with readimage().
1) It fills in alpha. Since it does this it might as well take a transparency
color so you don't have update alpha again.
2) Swapping of colors isn't necessary in some cases so to make it more generic
it shouldn't do that. However, I understand the reasoning and it makes it so
all OS version of readimage() return the same thing. I would propose
indicating RGB or BRG to distinguish this. So if you pass in RGB it will
convert appropriately for all version of readimage(). Same with BRG.
Cheers,
Bruce
At any rate, here is the code. I did some limited testing with both RGB. RGBA
is what I use in my application.
uchar * // O - Pixel buffer or NULL if failed
fltk::readimage(uchar *p, // I - Pixel buffer or NULL to allocate
PixelType type, // Type of pixels to store (RGB and RGBA only
now)
const Rectangle& r, // area to read
int linedelta
) {
int x, y; // Looping vars
int X = r.x();
int Y = r.y();
int w = r.w();
int h = r.h();
int delta = depth(type);
int bitcount;
int imgsize = w * h * 4;
HBITMAP destBmp;
HDC destDC;
HBITMAP oldBmp;
BITMAPINFO *pBitmapInfo;
uchar bitmapInfoBuffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
if (delta != 3 && delta != 4)
return readimage(p, type, r, linedelta);
destBmp = CreateCompatibleBitmap(dc, w, h);
destDC = CreateCompatibleDC(dc);
pBitmapInfo = (BITMAPINFO *)bitmapInfoBuffer;
if (destBmp == NULL || destDC == NULL)
return NULL;
memset((char *)pBitmapInfo, 0, sizeof(bitmapInfoBuffer));
pBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pBitmapInfo->bmiHeader.biWidth = w;
// make 0,0 upper left rather than bottom left
pBitmapInfo->bmiHeader.biHeight = -h;
// use aligned values so we don't get padded data
// The real question is whether to force the caller to use allocate
// 32 bits per pixel or not. I say force since event 24 bits is
// 24 * width + padding.
pBitmapInfo->bmiHeader.biBitCount = 32;
pBitmapInfo->bmiHeader.biPlanes = 1;
pBitmapInfo->bmiHeader.biCompression = BI_RGB;
pBitmapInfo->bmiHeader.biSizeImage = imgsize;
oldBmp = (HBITMAP)SelectObject(destDC, destBmp);
BitBlt(destDC, X, Y, w, h, dc, 0, 0, SRCCOPY);
// Deselect since GetDIBits requires it
SelectObject(destDC, oldBmp);
// Read bmp into pixel buffer
GetDIBits(destDC, destBmp, 0, h, p, pBitmapInfo, DIB_RGB_COLORS);
DeleteDC(destDC);
DeleteObject(destBmp);
// Down convert to 3 byte pixels
if (delta == 3)
{
uchar c1, c2, c3;
if (imgsize >= (3 * 4))
{
c1 = p[0]; c2 = p[1]; c3 = p[2];
p[0] = c3; p[2] = c1; p[1] = c2;
c1 = p[4]; c2 = p[5]; c3 = p[6];
p[3] = c3; p[4] = c1; p[5] = c2;
c1 = p[8]; c2 = p[9]; c3 = p[10];
p[6] = c3; p[7] = c1; p[8] = c2;
} else if (imgsize == (2 * 4))
{
c1 = p[0]; c2 = p[1]; c3 = p[2];
p[0] = c3; p[2] = c1; p[1] = c2;
c1 = p[4]; c2 = p[5]; c3 = p[6];
p[3] = c3; p[4] = c1; p[5] = c2;
return p;
} else if (imgsize == (1 * 4))
{
c1 = p[8]; c2 = p[9]; c3 = p[10];
p[6] = c3; p[7] = c1; p[8] = c2;
return p;
}
// the temp swap is really only necessary for the first 3 pixels overlap
for (int i = 3 * 4, int j = 3 * 3; i < imgsize; j += 3, i += 4)
{
p[j] = p[i+2];
p[j+1] = p[i+1];
p[j+2] = p[i];
}
} else
{
uchar c;
for (int i = 0; i < imgsize; i += 4)
{
// convert BGR to RGB
c = p[i];
p[i] = p[i+2];
p[i+2] = c;
}
}
return p;
}
_______________________________________________
fltk-dev mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-dev