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.
Printable View
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.
ok good to hear it worked out for you. :)
anytime mate.
Cheers
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:
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:
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);
}
}
}
}
'lpCapturedBits' is basically raw bitmap pixel bits stacked inside... For example, with bitPosition determined by desired pixel coords, and bits per pixel: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);
I am just learning this stuff, so I figure as a novice, I can explain it to other novices!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 );
~Maui
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:
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 :(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;
}
Any help is much appreciated,
Oleg
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.
ohh, that's it! Thank you, Marc! :wave:
(wish it would have been mentioned in other sources cause that was the vital info which was omitted)
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?
Quote:
Originally Posted by golanshahar
dont you have something better to do when you are bored :D ?Quote:
Originally Posted by Partizan
kidding.
well no you are not missing something. in fact you are right. however dont forget that this answer was given to a specific question :)Quote:
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?
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:
it getting two raw bits (input as 24 and output as 16) and simply convert each 24 bit pixel to 16 bit.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;
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. :D but anyway you got the idea.
Cheers
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. :)Quote:
Originally Posted by golanshahar
Thanks. I'm using similar in-memory manipulations on DIBs to change color depth. I find this method fast and accurate.Quote:
Originally Posted by golanshahar
i meant to every input format!Quote:
Originally Posted by Partizan
which is true. (while your dc is compatible with 24 )Quote:
...while in my function it will work on every input format...
Cheers