How to get screen pixel color?

Post your questions, suggestions and experiences regarding to Image manipulation, 3d modeling and level editing for the Irrlicht engine here.
terier
Posts: 34
Joined: Sun Oct 05, 2008 4:46 pm

How to get screen pixel color?

Post by terier »

I was wondering: does a function like
SColor IVideoDriver::getPixelScreen(position2d<s32>);
exist? I'm sure there's a way. I get what I need with creating IImage with IVideoDriver::createScreenshot() and using it's method getPixel() but this is very slow and unefficient ...
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

Instead, try rendering to a texture, locking said texture, finding your pixel, etc., and when you're done, unlocking the texture and drawing the texture to the "real" renderer. Of course, shaders are an even faster way of doing that.
terier
Posts: 34
Joined: Sun Oct 05, 2008 4:46 pm

Post by terier »

Can I render to a screen-sized texture? What's the purpose of locking a texture? And can you write a shader for me (I don't know how to write shaders)?
skumar
Posts: 201
Joined: Thu Feb 14, 2008 6:24 pm
Location: kerala state india
Contact:

Post by skumar »

createScreenShot function of the video driver can be used to get the screen as an image in the memory. Then you can get the desired pixed. Please read API regarding IImage class and above stated function.

But this will surely slow down the app.It is not recommended for realtime check .....
skumar
terier
Posts: 34
Joined: Sun Oct 05, 2008 4:46 pm

Post by terier »

I tried createScreenShot and getPixel but it works with 2 FPS ... yes I need a realtime check
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

if you're under Windows, then maybe this can help you ;) :

Code: Select all

// link against Gdi32.lib (libGdi32.a) !!!

#include <windows.h> 

HDC grabDesktop() {
  HWND hwnd;
  HDC ddc;
  HDC mdc;
  RECT sz;
  HBITMAP hbmp;
  hwnd = GetDesktopWindow();
  ddc = GetDC(hwnd);
  GetWindowRect(hwnd, &sz);
  mdc = CreateCompatibleDC(ddc);
  hbmp = CreateCompatibleBitmap(ddc, sz.right, sz.bottom);
  SelectObject(mdc, hbmp);
  BitBlt(mdc, 0, 0, sz.right, sz.bottom, ddc, 0, 0, SRCCOPY);
  ReleaseDC(hwnd, ddc);
  return (mdc);
} 

int main(int argc, char* argv[]) {
  HDC hDC;
  COLORREF cref;

  // to get the pixel at 100,100
  int posX = 100; 
  int posY = 100;

  hDC = grabDesktop();
  cref = GetPixel(hDC, posX, posY);
  printf("%02X %02X %02X", GetRValue(cref), GetGValue(cref), GetBValue(cref)); 
}
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

Why are you creating a screenshot???

virtual bool irr::video::IVideoDriver::setRenderTarget ( video::ITexture * texture,
bool clearBackBuffer = true,
bool clearZBuffer = true,
SColor color = video::SColor(0, 0, 0, 0)
)

Just reuse the same texture, that way it won't keep creating a new texture in memory. Then you call
virtual void* irr::video::ITexture::lock ( bool readOnly = false )
So you can access the individual pixel of the textures with the void* returned.

When you are done, use
virtual void irr::video::ITexture::unlock ( )
to tell Irrlicht the texture is accessible again.

Then you can use setrendertarget again to put the screen buffer back again.

Then you use virtual void irr::video::IVideoDriver::draw2DImage ( const video::ITexture * texture,
const core::position2d< s32 > & destPos
)

To draw back the texture on the screen buffer.

You don't need a screenshot, this is terribly wasteful, and no, I won't write you a shader, I've got other things to do and this should have all went into beginner's help.
terier
Posts: 34
Joined: Sun Oct 05, 2008 4:46 pm

Post by terier »

thank you very much, Acki
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

terier wrote:thank you very much, Acki
you're welcome !!! ;)

but there seems to be an error with the code I posted before...
I now changed it and made it a bit more usable for your needs:

Code: Select all

irr::video::SColor getPixelColor(irr::core::position2d<s32> pos){
  static HWND hwnd = GetDesktopWindow();
  static HDC ddc = GetDC(hwnd);
  static HDC mdc = CreateCompatibleDC(ddc);
  RECT sz;
  GetWindowRect(hwnd, &sz);
  HBITMAP hbmp = CreateCompatibleBitmap(ddc, sz.right, sz.bottom);
  SelectObject(mdc, hbmp);
  BitBlt(mdc, 0, 0, sz.right, sz.bottom, ddc, 0, 0, SRCCOPY);
  COLORREF cref;
  cref = GetPixel(mdc, pos.X, pos.Y);
  DeleteObject(hbmp);
  return irr::video::SColor(255, GetRValue(cref), GetGValue(cref), GetBValue(cref));
}
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Acki wrote:but there seems to be an error with the code I posted before...
yeah, found the error in the first code (stupid me released a context that must be deleted) !!! :lol:

now here is the clean and corrected code:

Code: Select all

video::SColor getPixel(core::position2d<s32> pos){
  static HWND hwnd = GetDesktopWindow();
  HDC ddc = GetDC(hwnd);
  HDC mdc = CreateCompatibleDC(ddc);
  RECT sz;
  GetWindowRect(hwnd, &sz);
  HBITMAP hbmp = CreateCompatibleBitmap(ddc, sz.right, sz.bottom);
  SelectObject(mdc, hbmp);
  BitBlt(mdc, 0, 0, sz.right, sz.bottom, ddc, 0, 0, SRCCOPY);
  COLORREF cref;
  cref = GetPixel(mdc, pos.X, pos.Y);
  DeleteObject(hbmp);
  DeleteDC(mdc);
  ReleaseDC(hwnd, ddc);
  return video::SColor(255, GetRValue(cref), GetGValue(cref), GetBValue(cref));
}
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Why would that code be any better than rendering to texture and using that data? At least it would be portable as well.
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

hybrid wrote:Why would that code be any better than rendering to texture and using that data?
Speed !?!?! :shock:
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

No, the irrlicht implementation I suggest keep reusing the same texture and the texture draw to the screen is lighting fast. You'll maybe gain 1-2 fps on a 100, no guarantee, and you lose all portability for it AND mix exterior rendering libs with irrlicht.
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

well, I'm too lazy for this, but maybe you write the same function but using RTT, so we can make a benchmark comparison... ;)
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Make sure to use readOnly = true if you don't want to re-upload the entire texture again every frame.

I'd be interested to see a performance comparison with Acki's method too. Does it work with all drivers?
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Post Reply