|
-
July 18th, 2005, 06:14 AM
#16
Re: getting RGB from a 16-bit bitmap
dont worry about it now man, I got it all going and I'm more than happy about that 
thanks again for the function, it's just fine, I had a few x, y values swapped, is all, thats why the screen only had 3/4 of the pixels.
-
July 18th, 2005, 10:10 AM
#17
Re: getting RGB from a 16-bit bitmap
ok good to hear it worked out for you. 
anytime mate.
Cheers
-
October 23rd, 2005, 10:52 PM
#18
Re: getting RGB from a 16-bit bitmap
I know you solved your problem TiMBuS, but I thought I would post a solution/improvement for all the novices like me who need to see it so we can learn it!
This is the entire OnClick() event for a button on my main form:
Code:
void __fastcall TFrmMain::Button3Click(TObject *Sender)
{
TPoint ptOrigin = FrmMain->GetClientOrigin(); //This ensures all drawing begins in the
ptOrigin.x+=PaintBox->Left; //client area of MY form. my 'lpCapturedBits'
ptOrigin.y+=PaintBox->Top; //was captured using user32.dll PrintWindow()
//and represents ONLY an alien window, NOT the
//whole screen! You can omit this, and set the
//rcDrawArea TRect to the entire screen to
//accomplish what TiMBuS was trying. I created
//ptOrigin, rcDrawArea, BitsPerPixel, and
//BitPosition for 3 reasons: To eliminate
//redundancy, to make modifications easier, and
//to make this code easier to read! NOTE: PaintBox
//is a TPaintbox, and I am using C++ Builder 6.0
//on Windows XP--->Thus the call to PrintWindow()...
TRect rcDrawArea;
rcDrawArea.left=ptOrigin.x;
rcDrawArea.top=ptOrigin.y;
rcDrawArea.right=ptOrigin.x+PaintBox->Width;
rcDrawArea.bottom=ptOrigin.y+PaintBox->Height;
int BitsPerPixel=4; //Add function here to determine screen color depth...Mine is 32 Bit
//32 Bit Color Depth: BitsPerPixel=4
//24 Bit Color Depth: BitsPerPixel=3
//16 Bit Color Depth: BitsPerPixel=2
//THIS IS WHERE TiMBuS had his problem! In fact, merely replacing 3
//as a multiplier in his code might have been enough for him. I
//think this code is more flexible, and should be faster, though!
//PS: I tried it and it worked GREAT for me!
int BitPosition=0;
for (int y = 0; y < rcDrawArea.Height(); ++y)
{
for (int x = 0; x < rcDrawArea.Width(); ++x)
{ //BitPosition avoids the same math being done 3x in a row, with the same values!
BitPosition=x*BitsPerPixel+(y*rcDrawArea.Width()*BitsPerPixel);
if (RGB(lpCapturedBits[BitPosition+2], lpCapturedBits[BitPosition+1], lpCapturedBits[BitPosition]) == RGB(255, 255, 255))
{
hdc = GetDC(NULL);
SetPixel(hdc, ptOrigin.x+x, ptOrigin.y+y, RGB(255, 0, 0));//You can Omit ptOrigin if using the WHOLE SCREEN
ReleaseDC(NULL, hdc);
}
}
}
}
My notes and explanations are in the code... My code, in particular, uses a capture of an alien window via User32.dll PrintWindow() to set the value of lpCapturedBits[]. I THINK you need to be running Windows XP to call that function... here is the breakdown on how to access lpCapturedBits, As I have seen it referenced MANY times in these posts, and never explained for those of use who still need the Dummy Books...
Code:
int BitsPerPixel=4;
int captureSize = BitsPerPixel * captureWidth * captureHeight;
lpCapturedBits = new char[captureSize];
//'lpCapturedBits' is is my image data array, it is globally declared
GetBitmapBits(memBM, captureSize, lpCapturedBits);
'lpCapturedBits' is basically raw bitmap pixel bits stacked inside... For example, with bitPosition determined by desired pixel coords, and bits per pixel:
Code:
int bitPosition = ( ( y*captureWidth )+x )*BitsPerPixel;
//You may have to fudge your x,y values a bit... I had y=y+3 in this equation
//to make my image line up, due to OTHER FACTORS
lpCapturedBits[BitPosition]=blueBit;
lpCapturedBits[BitPosition+1]=greenBit;
lpCapturedBits[BitPosition+2]=redBit;
lpCapturedBits[BitPosition+3]=alphaBit; //I don't use this, it is the transparency channel,
//and the elusive "4th bit" that causes so many
//beginners like me headaches!
int PixelColor = RGB( redBit, greenBit, blueBit );
I am just learning this stuff, so I figure as a novice, I can explain it to other novices!
~Maui
Last edited by mauigb; October 23rd, 2005 at 10:59 PM.
-
January 3rd, 2006, 09:20 AM
#19
Re: getting RGB from a 16-bit bitmap
Hi,
sorry to bump the old thread, but just thought better to post here than start a new thread where I'll be told to do a forum search ... I've just did, plus google search
Anyway, I just don't get it, it seems that all articles are missing some vital info which holds me off from continuing my work. What I'm trying to do is a simple thing (which became complicated) - get RGB values from a 16-bit 565 WORD value. Here's the problem. I have 3 variables (red, green, blue) of WORD type, which contain R, G and B values respectively. I pack these three values based on the algorythm found in MSDN (see source code). I get a 16-bit value containing all 3 RGB components. Then I'm trying to decode it back to separate R, G and B values, and I'm not getting those, even remotely.
Initial RGB values are - 100 110 120 (dec)
After decomposing I get 5 47 24 (dec)
Below is the source code:
Code:
#include <iostream.h>
#include <windows.h>
int main ()
{
WORD red = 100;
WORD green = 110;
WORD blue = 120;
WORD pixel565 = (red << 11) | (green << 5) | blue;
WORD red_mask = 0xF800;
WORD green_mask = 0x7E0;
WORD blue_mask = 0x1F;
BYTE red_value = (pixel565 & red_mask) >> 11;
BYTE green_value = (pixel565 & green_mask) >> 5;
BYTE blue_value = pixel565 & blue_mask;
cout << "R = " << (int)red_value << "\n";
cout << "G = " << (int)green_value << "\n";
cout << "B = " << (int)blue_value << "\n";
return 0;
}
Was is wrong with it? Something is obviously missing. But all the articles explain only that, so from their words this should be enough...well, maybe but it just doesn't work
Any help is much appreciated,
Oleg
Last edited by Xatrix; January 3rd, 2006 at 09:23 AM.
-
January 3rd, 2006, 09:46 AM
#20
Re: getting RGB from a 16-bit bitmap
Before "WORD pixel565 = (red << 11) | (green << 5) | blue;" you need to make sure the red, green and blue values are truncated to the appropriate size: red and blue are 5 bits, green is 6 bits.
-
January 3rd, 2006, 09:57 AM
#21
Re: getting RGB from a 16-bit bitmap
ohh, that's it! Thank you, Marc!
(wish it would have been mentioned in other sources cause that was the vital info which was omitted)
-
January 4th, 2006, 04:26 PM
#22
Re: getting RGB from a 16-bit bitmap
Sorry, for resurrecting this old topic, but it showed up as "HOT THREADS..." in my CodeGuru Newsletter which I was reading because I was bored. 
I have a question about golanshahar's method though. I always thought that if you create a compatible DC context it will be in the same color format as the source (i.e. Display). In your code you create a compatible device context which could be of any color depth (8, 16, 24, 32 bpp) and selecting a 24 bpp bitmap into it.
What happens if you set your display to 256 colors and run this sample? Since you are delaing with device dependent bitmaps, wouldn't the colors be really distorted? Or am I missing something?
 Originally Posted by golanshahar
i have a function i once wrote that convert bitmap to 24 bit color, you can take a look and modify it for your purposes. it uses the ::CreateDIBSection(..) api.
all you need to provide to the fuction is the:
const int &nWidth // width of the image
const int &nHeight// height of the image
const HBITMAP // handle to the bitmap of the 16 bit you have ( you can have by ::CreateBitmap(..) api or from ::LoadImage(..) api
BYTE *lpDesBits // out - pointer to 24 bit data bits that you sould alloc before calling the function in a size of witdh*height*3
Code:
void Get24BitImage ( const int &nWidth, const int &nHeight,const HBITMAP &hBitmap , BYTE *lpDesBits)
{
HDC hDC = ::GetDC( 0 );
HDC memDC1 = ::CreateCompatibleDC ( hDC );
HDC memDC2 = ::CreateCompatibleDC ( hDC );
BYTE *lpBits = NULL;
BITMAPINFO bmi;
::ZeroMemory( &bmi, sizeof(BITMAPINFO) );
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = nWidth;
bmi.bmiHeader.biHeight = nHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = BI_RGB;
HBITMAP hDIBMemBM = ::CreateDIBSection( 0, &bmi, DIB_RGB_COLORS, (void**)&lpBits, NULL, NULL );
HBITMAP hOldBmp1 = (HBITMAP)::SelectObject(memDC1, hDIBMemBM );
HBITMAP hOldBmp2 = (HBITMAP) ::SelectObject ( memDC2,hBitmap);
::BitBlt( memDC1, 0, 0, nWidth, nHeight, memDC2, 0, 0, SRCCOPY );
for ( int i = 0 ; i < nHeight ; i++)
::CopyMemory(&lpDesBits[i*3*nWidth],&lpBits[nWidth*3*(nHeight-1-i)],nWidth*3);
// clean up
::SelectObject ( memDC1, hOldBmp1 );
::SelectObject ( memDC2,hOldBmp2 );
::ReleaseDC ( 0, hDC );
::DeleteObject ( hDIBMemBM );
::DeleteObject ( hOldBmp1 );
::DeleteObject ( hOldBmp2 );
::DeleteObject ( memDC1 );
::DeleteObject ( memDC2 );
}
Cheers
-
January 4th, 2006, 05:07 PM
#23
Re: getting RGB from a 16-bit bitmap
 Originally Posted by Partizan
Sorry, for resurrecting this old topic, but it showed up as "HOT THREADS..." in my CodeGuru Newsletter which I was reading because I was bored. 
dont you have something better to do when you are bored ?
kidding.
I have a question about golanshahar's method though. I always thought that if you create a compatible DC context it will be in the same color format as the source (i.e. Display). In your code you create a compatible device context which could be of any color depth (8, 16, 24, 32 bpp) and selecting a 24 bpp bitmap into it.
What happens if you set your display to 256 colors and run this sample? Since you are delaing with device dependent bitmaps, wouldn't the colors be really distorted? Or am I missing something?
well no you are not missing something. in fact you are right. however dont forget that this answer was given to a specific question 
if you seek for better solution that is not device depended the better/fast way is to work with the raw bits and simply turn each RGB24 to RGB16 , here look at this sample that i worte:
Code:
void ColorConversion24To16 ( BYTE *lpBits24, int Width, int Height, BYTE *lpBits16 )
{
int nPos16 = 0;
int Size = Width*Height*3;
for ( int nPos24 = 0 ; nPos24 < Size ; nPos24+=3 ,nPos16+=2)
{
BYTE Red24 = lpBits24[nPos24+2]; // 8-bit red
BYTE Green24 = lpBits24[nPos24+1]; // 8-bit green
BYTE Blue24 = lpBits24[nPos24+0]; // 8-bit blue
BYTE Red16 = Red24 >> 3; // 5-bit red
BYTE Green16 = Green24 >> 2; // 6-bit green
BYTE Blue16 = Blue24 >> 3; // 5-bit blue
unsigned short RGB2Bytes = Blue16 + (Green16<<5) + (Red16<<(5+6));
lpBits16[nPos16] = LOBYTE(RGB2Bytes);
lpBits16[nPos16+1]= HIBYTE(RGB2Bytes);
}
}
// usage
int Width = 100;
int Height = 100;
BYTE *lpBits24 = new BYTE[Width*Height*3];
BYTE *lpBits16 = new BYTE[Width*Height*2];
ColorConversion24To16( lpBits24,Width,Height,lpBits16);
delete [] lpBits24;
delete [] lpBits16;
it getting two raw bits (input as 24 and output as 16) and simply convert each 24 bit pixel to 16 bit.
NOTE: i didnt test it much but it should work.
/EDIT Opps i just realized that i coverted the other way around ( from 24 to 16 instead 16 to 24 ) i need to get some sleep. but anyway you got the idea.
Cheers
-
January 4th, 2006, 05:48 PM
#24
Re: getting RGB from a 16-bit bitmap
 Originally Posted by golanshahar
well no you are not missing something. in fact you are right. however dont forget that this answer was given to a specific question 
In that case you threw me off with one of your replies to philkr, saying that your method will work with ANY bitmap. You should note that it will work with "any" bitmap only if you are upconverting that "any" bitmap. 
 Originally Posted by golanshahar
if you seek for better solution that is not device depended the better/fast way is to work with the raw bits and simply turn each RGB24 to RGB16 , here look at this sample that i worte:
Thanks. I'm using similar in-memory manipulations on DIBs to change color depth. I find this method fast and accurate.
-
January 4th, 2006, 05:57 PM
#25
Re: getting RGB from a 16-bit bitmap
 Originally Posted by Partizan
In that case you threw me off with one of your replies to philkr, saying that your method will work with ANY bitmap. You should note that it will work with "any" bitmap only if you are upconverting that "any" bitmap. 
i meant to every input format!
...while in my function it will work on every input format...
which is true. (while your dc is compatible with 24 )
Cheers
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
|