Grayscale overlay

116 views
Skip to first unread message

steve

unread,
Sep 18, 2017, 1:11:47 PM9/18/17
to wxPython-users
Hi,

I would like to get a grayscale screenshot (overlay) of the current window and do drawings on it. I mean, the current window and all widgets, etc on it should lose all their colors and I should do drawings on it. Do you know how to do this?

I use 


odc = wx.DCOverlay(wx.Overlay, dc)


but its not grayscale.

Tim Roberts

unread,
Sep 18, 2017, 1:43:15 PM9/18/17
to wxpytho...@googlegroups.com
steve wrote:
>
> I would like to get a grayscale screenshot (overlay) of the current
> window and do drawings on it. I mean, the current window and all
> widgets, etc on it should lose all their colors and I should do
> drawings on it. Do you know how to do this?

Well, an overlay is something that appears over the top of an existing
window, so the controls on the window still show through.   Is that
really what you're after?  It sounds like you want a separate window
contains a converted copy of your current window, so the existing
controls are not visible.

There is nothing in wx that will convert a color bitmap to a grayscale
bitmap, in part because the definition of "grayscale" is not completely
uniform.  You'll have to do that by hand, pixel by pixel, or using
another graphics library.  It's not hard.

Perhaps you should describe what you're trying to in a bit more detail.

--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

Robin Dunn

unread,
Sep 18, 2017, 3:43:56 PM9/18/17
to wxPython-users
wx.Image has a ConvertToGreyscale method.

Drawing in a layer on top of other widgets will be tricky however.  The overlay classes on OSX use a native implementation that can do that, however the other platforms use a generic overlay based on ClientDC so it can only support drawing on the window performing the overlay which is likely to be the parent of the widgets you want to draw over.

The only approach that comes to mind is to use wx.ScreenDC to blit a snapshot of the window into a bitmap, temporarily replace (or hide) the current contents of the window with one that displays that bitmap and supports drawing like you want. However that won't work on OSX (DC's are one-way there, in most cases you can't easily get their current contents) but you can use the overlay classes there. Also, IIRC the ScreenDC approach may or may not work on Linux, depending on a number of factors.

Robin

Steve Barnes

unread,
Sep 18, 2017, 4:25:56 PM9/18/17
to wxpytho...@googlegroups.com
Just get the screenshot, (in colour), convert to an image with
ConvertToImage() and then use Pillow or Numpy to convert to greyscale.

--
Steve (Gadget) Barnes
Any opinions in this message are my personal opinions and do not reflect
those of my employer.

---
This email has been checked for viruses by AVG.
http://www.avg.com

steve

unread,
Sep 18, 2017, 4:33:33 PM9/18/17
to wxPython-users
Sorry for causing misunderstanding,

I have a panel on my frame, and I do drawings on it (rectangles, shapes etc) with wxpython GDI (using methods like dc.DrawRectangle etc). Rectangles and shapes have colors. There are no widgets on the panel. Just shapes.

When I press a button on the toolbar, I want everything on that panel to turn into grayscale (all shapes will lose their colors), and a colored custom progress bar will appear in the middle of that grayscaled panel (and on top of shapes), and it will run (because a lengthy operation will be executed). When the execution is completed, the progress bar will disappear and the shapes on panel will regain its original colors.

I hope I could explain it.

Steve Barnes

unread,
Sep 19, 2017, 3:45:04 AM9/19/17
to wxpytho...@googlegroups.com
> Tim Roberts, ti...@probo.com <javascript:>
> Providenza & Boekelheide, Inc.

Simply hide the existing panel and replace it with one displaying a grey
scale version of the current bitmap or image for the duration.

Tim Roberts

unread,
Sep 19, 2017, 1:52:29 PM9/19/17
to wxpytho...@googlegroups.com
steve wrote:
>
> I have a panel on my frame, and I do drawings on it (rectangles,
> shapes etc) with wxpython GDI (using methods like dc.DrawRectangle
> etc). Rectangles and shapes have colors. There are no widgets on the
> panel. Just shapes.

That's very different from what you first described.


> When I press a button on the toolbar, I want everything on that panel
> to turn into grayscale (all shapes will lose their colors), and a
> colored custom progress bar will appear in the middle of that
> grayscaled panel (and on top of shapes), and it will run (because a
> lengthy operation will be executed). When the execution is completed,
> the progress bar will disappear and the shapes on panel will regain
> its original colors.

It seems to me that the easy way to do this is to have all of your color
selections go through a filter:

    m_Shape->SetBackgroundColor( ChooseColor( 255,128,64 ) );
...
    wxColour MyWindow::ChooseColor( int r, int g, int b )
    {
        if( m_NeedGrayscale )
        {
            // This is a cheap but acceptable RGB->grayscale conversion.
            int gray = (2 * r + 4 * g + b) / 7;
            return wxColour( gray, gray, gray );
        }
        else
            return wxColour( r, g, b );
    }

Now, to draw in grayscale, you just set the flag and call "Refresh();."

Tim Roberts

unread,
Sep 19, 2017, 1:54:45 PM9/19/17
to wxpytho...@googlegroups.com
Tim Roberts wrote:
> steve wrote:
>> I have a panel on my frame, and I do drawings on it (rectangles,
>> shapes etc) with wxpython GDI (using methods like dc.DrawRectangle
>> etc). Rectangles and shapes have colors. There are no widgets on the
>> panel. Just shapes.
> That's very different from what you first described.
>
>
>> When I press a button on the toolbar, I want everything on that panel
>> to turn into grayscale (all shapes will lose their colors), and a
>> colored custom progress bar will appear in the middle of that
>> grayscaled panel (and on top of shapes), and it will run (because a
>> lengthy operation will be executed). When the execution is completed,
>> the progress bar will disappear and the shapes on panel will regain
>> its original colors.
> It seems to me that the easy way to do this is to have all of your color
> selections go through a filter:

Holy cripes, I totally spaced that I was on the wxPython list.

    def ChooseColor( self, r, g, b ):
        if self.NeedGrayScale:
            gray = (2 * r + 4 * g + b) / 7
            return wx.Colour( gray, gray, gray )
        else:
            return wx.Colour( r, g, b )

    ....
        self.widget.SetBackgroundColor( self.ChooseColor( 255, 128, 64 ) )

Chris Barker - NOAA Federal

unread,
Sep 19, 2017, 8:25:37 PM9/19/17
to wxpytho...@googlegroups.com
>
> Holy cripes, I totally spaced that I was on the wxPython list.

Makes you appreciate Python, eh?

Another option:

Rather than greyscale, draw a semi-transparent white or black
rectangle over the whole thing -- that will make it look all muted.

Also - you should probably have your window double/buffered-- so you
can grab the buffet, make it an image, convert to grayscale, and the
put it back.

-CHB

>
> def ChooseColor( self, r, g, b ):
> if self.NeedGrayScale:
> gray = (2 * r + 4 * g + b) / 7
> return wx.Colour( gray, gray, gray )
> else:
> return wx.Colour( r, g, b )
>
> ....
> self.widget.SetBackgroundColor( self.ChooseColor( 255, 128, 64 ) )
>
> --
> Tim Roberts, ti...@probo.com
> Providenza & Boekelheide, Inc.
>
> --
> You received this message because you are subscribed to the Google Groups "wxPython-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-user...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

steve

unread,
Sep 20, 2017, 6:08:51 PM9/20/17
to wxPython-users
Great answer Chris, it doesn't exactly do what I want, bu still it is very handy. Thanks.
Reply all
Reply to author
Forward
0 new messages