|
-
Jul 23rd, 2003, 01:05 AM
#1
Thread Starter
Fanatic Member
Stupid question about GetDIBits [resolved]
I'm sure a similar question has been asked, but I wasn't able to find the answer to it. I'm trying to write a function similar to BitBlt in vc++ and I need to perform some calculations on each pixel of the Source DC. I breifly thought of using SetPixel but then realized that using a Dib would definitly be much faster (you directly modify the pixels in an array).
Anyway, long story short, I'm new to c++. If a function is returning an array, how do I set up the buffer for that array? The size of the Dib may vary, therefore I need to dynamically create the array based on the dimensions of the image being modified.
Do I need to allocate the entire array before calling the function, or will the function reallocate my array so the data will fit? Should the array be two dimensions or one?
BTW, my native toungue in VB6.
Last edited by agent; Jul 29th, 2003 at 11:28 PM.
-
Jul 23rd, 2003, 01:16 AM
#2
Dynamic arrays should be one-dimensional. For allocating, use new[]. And functions should never reallocate arrays, so the caller should allocate enough.
What are you writing the function for?
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Jul 23rd, 2003, 01:21 AM
#3
Thread Starter
Fanatic Member
i'm writing a userinterface graphics function for use with a vb app. big project that involves mounting a computer in my car with some map software on it. custom ui for the computer for use with a touch screen adater...
-
Jul 23rd, 2003, 05:11 AM
#4
Hyperactive Member
Here's 2 functions which wraps about GetDibBits() and SetDibBits()
Code:
pBGR MyGetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight)
{
BITMAPINFO bi;
BOOL bRes;
pBGR buf;
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = nWidth;
bi.bmiHeader.biHeight = - nHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = nWidth * 4 * nHeight;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
// buf = new sBGR[nWidth * nHeight];
buf = (pBGR) malloc(nWidth * 4 * nHeight);
bRes = GetDIBits(hdc, hBmp, 0, nHeight, buf, &bi, DIB_RGB_COLORS);
if (!bRes) {
// delete [] buf;
free(buf);
buf = 0;
}
return buf;
}
Note:Please remember to delete the pointer away at the end of your program.
Code:
int MySetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight, pBGR buf)
{
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = nWidth ;
bi.bmiHeader.biHeight = - nHeight ;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = nWidth * 4 * nHeight;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
return ( SetDIBits(hdc , hBmp ,0, nHeight ,buf,&bi,DIB_RGB_COLORS) );
}
This is the structure they uses (note they are incompatible with COLORREF)
Code:
// The Representation of a 32 bit color table entry
#pragma pack(push)
#pragma pack(1)
typedef struct ssBGR {
unsigned char b;
unsigned char g;
unsigned char r;
unsigned char pad;
} sBGR;
typedef sBGR *pBGR;
#pragma pack(pop)
An example of how to use the array. The code below converts the pixels to greyscale
Code:
for(int y=0;y<height;++y)
{
for(int x=0;x<width;++x)
{
sBGR temp_col=pDIBbits[y * width+x];
int OrigRed =(int)(temp_col.r);
int OrigGreen=(int)(temp_col.g);
int OrigBlue =(int)(temp_col.b);
OrigRed =(int) ( (float)(OrigRed) * 0.299);
OrigGreen=(int) ( (float)(OrigGreen) * 0.587);
OrigBlue =(int) ( (float)(OrigBlue) * 0.114);
int Grey=OrigRed+OrigGreen+OrigBlue;
if(Grey>255) Grey=255;
sBGR tempBGR;
tempBGR.r=Grey;
tempBGR.g=Grey;
tempBGR.b=Grey;
pDIBbits[y * width+x]=tempBGR;
}
}
-
Jul 23rd, 2003, 08:50 AM
#5
What's the problem with the BitBlt API?
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Jul 23rd, 2003, 10:04 AM
#6
Hyperactive Member
Originally posted by CornedBee
What's the problem with the BitBlt API?
Originally posted by agent
...and I need to perform some calculations on each pixel of the Source DC. I breifly thought of using SetPixel but then realized that using a Dib would definitly be much faster (you directly modify the pixels in an array).
-
Jul 23rd, 2003, 12:29 PM
#7
Oh, sorry.
But isn't that a waste? Unless you are combining source and target somehow, wouldn't it be better to modify the image first and then simply blit it? Or if you are combining, have you looked if the blit modes satisfy your needs? Or maybe other blitting functions (e.g. AlphaBlend)?
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Jul 23rd, 2003, 01:18 PM
#8
Thread Starter
Fanatic Member
i'm combining the images using an 8-bit alphamask. here's the prototype so you can understand it a bit better.
Code:
BOOL AlphaBlit(
HDC hDcDest, //Destination (i.e. the Screen)
int ix, //Location on the Destination to blit
int iy,
int iWidth //Size of blit
int iHeight
HDC hDcSource //Source image
HDC hDcMask //Source image's mask (8-bits)
DWORD dwRasterop //See bitblt
);
It will act similarly to BitBlt except that it combines the Destination and the Source using the Mask before using BitBlt to blit it to the Destination using the specified raster operation.
-
Jul 23rd, 2003, 07:27 PM
#9
Hyperactive Member
FYI, there is a AlphaBlend Windows API. Have you taken a look at it?
-
Jul 23rd, 2003, 09:04 PM
#10
Thread Starter
Fanatic Member
the info i have on alphablend is that it does not support alphamasks. if you have any updated info on the function let me know where you got it from. otherwise, i'm happy to write the function myself
-
Jul 23rd, 2003, 09:32 PM
#11
Hyperactive Member
Maybe I'm dumb. What is alphamask?
-
Jul 24th, 2003, 12:35 AM
#12
Thread Starter
Fanatic Member
having some wierd effects with the graphics now. it started off by drawing only a black box where the image should be. i disabled the blending algorythm and it is supposed to emulate BitBlt now (copies the source to the dest at full opacity). unfortunatly, it's drawing from the upper right hand corner of the screen and in monochrome. maybe somebody could help me figure out why i can't get this to at least draw in color? I included the relevent source code.
the behavior i'm looking for is to blit an image onto an existing image, varying the opacity based on the pixels in the mask image. this will be used in some interactive transparent user interface controls and possible a game or too.
Code:
#include "resource.h"
#include <windows.h>
// The Representation of a 32 bit color table entry
#pragma pack(push)
#pragma pack(1)
typedef struct ssBGR {
unsigned char b;
unsigned char g;
unsigned char r;
unsigned char pad;
} sBGR;
typedef sBGR *pBGR;
#pragma pack(pop)
pBGR MyGetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight);
int MySetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight, pBGR buf);
/*
SoftBlt
x and y on screen (point api)
x, y, width, height of source (rect) (this param used for both Source and Mask)
Screen (hDc)
Source (hDc)
SourceMask (hDc)
Laymans translation of the following code
STEP 1 - get dib section of current screen (same size as source)
STEP 2 - get dib section of source
STEP 3 - get dib section of mask
STEP 4 - combine all three dib sections' arrays using the blend algorythm
STEP 5 - create a temporary dc and create a bitmap of the correct size
STEP 6 - use SetDIBits to blit the image to the temporary dc
STEP 7 - BitBlt the contents of the temporary dc to hDcDest using the rasterop specified
STEP 8 - Clean Up...
***work only within the bounds of the source rect***
MATH
The following function is executed for each channel of each pixel
The mask's value is the same for each channel and is the average of the three channels.
m = (mask.r + mask.g + mask.b) / 3
d is the destination pixel
s is the source pixel
m is the mask pixel
d = s * (m + ((1 - m) * d))
*/
BOOL __stdcall SoftBlt(HDC hdcDest, int nLeft, int nTop, int nWidth, int nHeight, HDC hdcSrc, HDC hdcSrcMask)
{
//STEP 1 - 3
HDC hdcTMPDest = CreateCompatibleDC(hdcDest);
HBITMAP hbTMPDest = CreateCompatibleBitmap(hdcTMPDest, nWidth, nHeight);
SelectObject(hdcTMPDest, hbTMPDest);
BitBlt(hdcTMPDest, 0, 0, nWidth, nHeight, hdcDest, nLeft, nTop, SRCCOPY);
pBGR dibDest = MyGetDibBits(hdcTMPDest, (HBITMAP) GetCurrentObject(hdcTMPDest, OBJ_BITMAP), nWidth, nHeight);
pBGR dibSource = MyGetDibBits(hdcSrc, (HBITMAP) GetCurrentObject(hdcSrc, OBJ_BITMAP), nWidth, nHeight);
pBGR dibMask = MyGetDibBits(hdcSrcMask, (HBITMAP) GetCurrentObject(hdcSrcMask, OBJ_BITMAP), nWidth, nHeight);
//STEP 4
for (int y = 0; y < nHeight; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
sBGR bgrDest = dibDest[y * nWidth + x];
sBGR bgrSource = dibSource[y * nWidth + x];
sBGR bgrMask = dibMask[y * nWidth + x];
unsigned char mask = (bgrMask.b + bgrMask.g + bgrMask.r) / 3;
//Blend function
/*
bgrDest.r = bgrSource.r * (mask + ((1 - mask) * bgrDest.r));
bgrDest.g = bgrSource.g * (mask + ((1 - mask) * bgrDest.g));
bgrDest.b = bgrSource.b * (mask + ((1 - mask) * bgrDest.b));
*/
bgrDest = bgrSource; // <--- this is temporary, makes it act like bitblt
dibDest[y * nWidth + x] = bgrDest;
}
}
//STEP 5
HDC hdcTmp = CreateCompatibleDC(hdcDest);
HBITMAP hbTmp = CreateCompatibleBitmap(hdcTmp, nWidth, nHeight);
SelectObject(hdcTmp, hbTmp);
//STEP 6
MySetDibBits(hdcTmp, hbTmp, nWidth, nHeight, dibDest);
//STEP 7
BitBlt(hdcDest, nLeft, nTop, nWidth, nHeight, hdcTmp, 0, 0, SRCCOPY);
//Step 8
DeleteObject(hbTMPDest);
DeleteObject(hbTmp);
DeleteDC(hdcTMPDest);
DeleteDC(hdcTmp);
free(dibDest);
free(dibSource);
free(dibMask);
return 1;
}
pBGR MyGetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight)
{
BITMAPINFO bi;
BOOL bRes;
pBGR buf;
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = nWidth;
bi.bmiHeader.biHeight = - nHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = nWidth * 4 * nHeight;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
// buf = new sBGR[nWidth * nHeight];
buf = (pBGR) malloc(nWidth * 4 * nHeight);
bRes = GetDIBits(hdc, hBmp, 0, nHeight, buf, &bi, DIB_RGB_COLORS);
if (!bRes) {
// delete [] buf;
free(buf);
buf = 0;
}
return buf;
}
int MySetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight, pBGR buf)
{
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = nWidth ;
bi.bmiHeader.biHeight = - nHeight ;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = nWidth * 4 * nHeight;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
return ( SetDIBits(hdc , hBmp ,0, nHeight ,buf,&bi,DIB_RGB_COLORS) );
}
Last edited by agent; Jul 24th, 2003 at 12:38 AM.
-
Jul 24th, 2003, 01:50 AM
#13
Sorry, no idea where that particular problem is.
Have you considered combining the alpha mask with the image and then AlphaBlending it?
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Jul 24th, 2003, 06:19 AM
#14
Hyperactive Member
Color in red is what I change.
The arguement I used for hdcDest parameter is the hDC I get from GetDC();
As a thumb of rule, always use the main DC (from GetDC() ) for CreateCompatibleDC() and CreateCompatibleBitmap().
Code:
BOOL __stdcall SoftBlt(HDC hdcDest, int nLeft, int nTop, int nWidth, int nHeight, HDC hdcSrc, HDC hdcSrcMask)
{
//STEP 1 - 3
HDC hdcTMPDest = CreateCompatibleDC(hdcDest);
HBITMAP hbTMPDest = CreateCompatibleBitmap(hdcTMPDest, nWidth, nHeight);
SelectObject(hdcTMPDest, hbTMPDest);
BitBlt(hdcTMPDest, 0, 0, nWidth, nHeight, hdcDest, nLeft, nTop, SRCCOPY);
pBGR dibDest = MyGetDibBits(hdcTMPDest, (HBITMAP) GetCurrentObject(hdcTMPDest, OBJ_BITMAP), nWidth, nHeight);
pBGR dibSource = MyGetDibBits(hdcSrc, (HBITMAP) GetCurrentObject(hdcSrc, OBJ_BITMAP), nWidth, nHeight);
pBGR dibMask = MyGetDibBits(hdcSrcMask, (HBITMAP) GetCurrentObject(hdcSrcMask, OBJ_BITMAP), nWidth, nHeight);
//STEP 4
for (int y = 0; y < nHeight; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
sBGR bgrDest = dibDest[y * nWidth + x];
sBGR bgrSource = dibSource[y * nWidth + x];
sBGR bgrMask = dibMask[y * nWidth + x];
unsigned char mask = (bgrMask.b + bgrMask.g + bgrMask.r) / 3;
//Blend function
/*
bgrDest.r = bgrSource.r * (mask + ((1 - mask) * bgrDest.r));
bgrDest.g = bgrSource.g * (mask + ((1 - mask) * bgrDest.g));
bgrDest.b = bgrSource.b * (mask + ((1 - mask) * bgrDest.b));
*/
bgrDest = bgrSource; // <--- this is temporary, makes it act like bitblt
dibDest[y * nWidth + x] = bgrDest;
}
}
//STEP 5
HDC hdcTmp = CreateCompatibleDC(hdcDest);
HBITMAP hbTmp = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
SelectObject(hdcTmp, hbTmp);
//STEP 6
MySetDibBits(hdcTmp, hbTmp, nWidth, nHeight, dibDest);
//STEP 7
BitBlt(hdcDest, nLeft, nTop, nWidth, nHeight, hdcTmp, 0, 0, SRCCOPY);
//Step 8
DeleteObject(hbTMPDest);
DeleteObject(hbTmp);
DeleteDC(hdcTMPDest);
DeleteDC(hdcTmp);
free(dibDest);
free(dibSource);
free(dibMask);
return 1;
}
-
Jul 28th, 2003, 12:22 AM
#15
Thread Starter
Fanatic Member
well now it in color, but it's still blitting from the upper left corner of the screen instead of from the picturebox's hDC in vb.
also, would you be able to tell me if i have the right formula for alpha bleneding? if not, do you know what it is?
Originally posted by transcendental
Maybe I'm dumb. What is alphamask?
an alphamask is a separate image that maps the opacity of each pixel it lines up with in the first image using the grey value of each pixel (0 through 255)
my function averages the three channels for each pixel to get a decent grey value (works good even if the image is already greyscale)
-
Jul 28th, 2003, 01:11 AM
#16
Hyperactive Member
well now it in color, but it's still blitting from the upper left corner of the screen instead of from the picturebox's hDC in vb.
Use the picturebox's hDC then. I have never used picturebox control so can't help you much.
The below is the MyAlphablend function(it calls the pixelate() function). All the parameters are self-explanatory. As for the 'Alpha' parameter, 0 means the source bitmap is fully transparent, 255 means the source is opaque. In other words, Alpha is the Alpha level.
Code:
void MyAlphaBlend(pBGR pDest, int nWidth, int nHeight, pBGR pSrc, BYTE Alpha)
{
for(int y=0;y<nHeight;++y)
{
for(int x=0;x<nWidth;++x)
{
int i =y *nWidth+x;
pDest[i]=Pixelate(pDest[i],pSrc[i],Alpha);
}
}
}
sBGR Pixelate(sBGR dest,sBGR source,BYTE Alpha)
{
float FinalRed,FinalGreen,FinalBlue;
FinalRed = (Alpha/255.0f*(float)source.r) + ((1.0f-Alpha/255.0f)*(float)dest.r);
FinalGreen= (Alpha/255.0f*(float)source.g) + ((1.0f-Alpha/255.0f)*(float)dest.g);
FinalBlue = (Alpha/255.0f*(float)source.b) + ((1.0f-Alpha/255.0f)*(float)dest.b);
int nFinalRed,nFinalGreen,nFinalBlue;
if(FinalRed>=FinalGreen && FinalRed>=FinalBlue)
{
if(FinalRed>255.0f)
{
nFinalRed=255;
nFinalGreen=(int)(FinalGreen/FinalRed*255.0f);
nFinalBlue =(int)(FinalBlue/FinalRed*255.0f);
}
else
{
nFinalRed =(int)(FinalRed);
nFinalGreen=(int)(FinalGreen);
nFinalBlue =(int)(FinalBlue);
}
}
else if(FinalGreen>=FinalRed && FinalGreen>=FinalBlue)
{
if(FinalGreen>255.0f)
{
nFinalRed =(int)(FinalRed/FinalGreen*255.0f);
nFinalGreen=255;
nFinalBlue =(int)(FinalBlue/FinalGreen*255.0f);
}
else
{
nFinalRed =(int)(FinalRed);
nFinalGreen=(int)(FinalGreen);
nFinalBlue =(int)(FinalBlue);
}
}
else if(FinalBlue>=FinalRed && FinalBlue>=FinalGreen)
{
if(FinalBlue>255.0f)
{
nFinalRed =(int)(FinalRed/FinalBlue*255.0f);
nFinalGreen=(int)(FinalGreen/FinalBlue*255.0f);
nFinalBlue=255;
}
else
{
nFinalRed =(int)(FinalRed);
nFinalGreen=(int)(FinalGreen);
nFinalBlue =(int)(FinalBlue);
}
}
sBGR tempBGR;
tempBGR.r=nFinalRed;
tempBGR.g=nFinalGreen;
tempBGR.b=nFinalBlue;
return tempBGR;
}
-
Jul 28th, 2003, 10:18 PM
#17
Thread Starter
Fanatic Member
your function applies the transparancy to the whole image. my function needs to have per-pixel transparancy. i'll post a separate question about the math behind the blend function.
also, i fixed the picturebox problem. turned out to be on VB's side (what else is new...) If the AutoRedraw property is false, then the hDC property of the box returns the screen's hDC. kinda stupid, but...
-
Jul 29th, 2003, 04:35 AM
#18
Hyperactive Member
Well, that's for you to modify to your needs. That AlphaBlend function had served my purpose and I'm not going to touch it anymore.
-
Jul 29th, 2003, 11:27 PM
#19
Thread Starter
Fanatic Member
Originally posted by transcendental
Well, that's for you to modify to your needs. That AlphaBlend function had served my purpose and I'm not going to touch it anymore.;)
thanks very much. i ended up using it and it solved my problem. for more info, see also http://www.vbforums.com/showthread.php?threadid=255453
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|