views:

37

answers:

2

Hi everybody!

I want to create a filter over a specific area of the screen to perform filtering opertions.

Examples what a filtering opertion might be:
    - inverting (e.g. change black pixel to white pixels, red to cyan)
    - masking pixels (e.g. mask = ff0000; input c79001 -> c70000)
    - operations like photoshop's layer effects

Here is an example of what it should look like: http://img443.imageshack.us/img443/1462/overlayk.png

Does anyone know how to perform this under Windows OS. (my prefered language is C#)

Thanks!

A: 

Depending on how fast you need the "filter" to update, a quick and hacky way is just to get a screenshot using CopyFromScreen while your filter window is invisible, apply the filter to the image data, and then set the filter window to display the image data.

If you want to do it without having to hide the window first, you'll probably need to do something like http://www.codeproject.com/KB/system/snapshot.aspx where you capture individual windows.

An even trickier but potentially faster thing to do, and requiring nearly complete use of p/invoke win32 calls, would be to not have a window at all, get the required capture windows based on their coordinates, capture the images as above, and then draw directly to the screen DC.

Reinderien
I though about this approach. The problem is that when the pixels behind the filter change i need to update the filter. But I cannot detect if they have changed because the filter is in front. (Setting the filter invisible temporarily is not a option.)
youllknow
Right, so then consider the third option. Do repeated draws directly to the screen DC based on direct window captures.
Reinderien
Can you please explain what "direct window captures" are?
youllknow
First, call WindowFromPoint as appropriate to figure out what window is visible at certain coordinates. Then, do as in http://www.codeproject.com/KB/system/snapshot.aspx where you do a BitBlt directly from that window into your own bitmap.
Reinderien
But the window above would ever by my filter window!?
youllknow
Right. So, like I said, don't have a window. Draw directly to the screen DC.
Reinderien
Oh, I'm sorry, I misunderstood! It's clear now!
youllknow
Do you know how to draw directly to the screen DC?
youllknow
This is one example: http://cboard.cprogramming.com/windows-programming/111462-%5Bc%5D-gdi-how-erase-material-drawn-entire-screen-dc.html
Reinderien
A: 

To clarify: you want an area of the desktop, not just within the bounds of your window, to be under your control allowing you to apply a per-pixel filter. If that's the case, I think what you need is DirectDraw using the XNA libraries. WPF MAY get you what you need, but WinForms will most likely not. There are third party tools as well.

If you want this capability only within the bounds of your application's window, for instance in a drawing application, it gets far easier. Every class in the Windows.Forms namespace that inherits from Control exposes a CreateGraphics() method. This method returns an object representing a drawing surface covering the screen area of the control, and is the basis for just about anything you want to do on a window involving custom graphics (and internally, it's used to draw the controls in the first place).

Once you have the Graphics object, you can draw Images on it. A popular method of drawing custom graphics like animations or games is to do the actual drawing on a Bitmap object (derived from the abstract Image) and then when you're done, draw the Bitmap on the Graphics area. This is done to reduce flicker; if the graphics area is shown to the user while it is being drawn on, the user will only see the complete image for a split second before it is "wiped" and redrawn, and shapes drawn halfway through will be there one moment and gone the next as they wait to be drawn. Drawing to a bitmap, then showing the Bitmap on the screen when you're done, means the user sees a complete image at a time.

You can extend this using transparency features to create multi-layered images. Have a Bitmap for every layer you wish to manipulate. Work on them seperately, then draw each of them, in their proper order from back to front, onto a master Bitmap, and draw that Bitmap on the screen. This allows you those PhotoShop-type manipulations where a part of the image is one layer, and can be manipulated independently of all others.

As for per-pixel filtering, Bitmap objects expose GetPixel() and SetPixel() methods, which allow you to grab the color of a single pixel, perform a filter calculation, and re-draw it. This process will be totally unaccelerated, and so limited by your CPU speed, but allow very fine control of your image, or repetitive tasks like your filters.

KeithS
I want an area or the desktop, and not just within the bounds of your window. Any idea how to do this with DirectDraw?
youllknow
You'll need the XNA Game Studio plug-in for VS. It will allow access to the Microsoft.XNA.Framework namespaces. Under the Graphics subspace, you'll find GraphicsAdapter, which has methods allowing you to reference a portion of a screen for drawing, and to set up objects on which to apply textures (in this case you just want a face the size of the area you're referencing). You'll combine this with Windows API methods in the user32 and gdi32 DLLs that will allow you to grab areas of the screen so you can work with them in .NET code before redrawing them.
KeithS