Struggling with manipulating a bitmap

69 views
Skip to first unread message

Mike W

unread,
Sep 22, 2021, 11:05:57 AM9/22/21
to wx-users
I'm in the process of writing an application that uses wxWidgets.  It compiles and 
runs fine using msys2 and wx library 3.1.5. I am having problems, however when I try
to compile the code under Ubuntu/wx 3.1.5.  Although the app itself runs fine, the
display window just outputs a plain black window.

I using wxNativePixelData to draw on a bitmap that I then blit onto the display window
in the onpaint event.

The Display initialisation code looks like this:

class CDisplayWX: public CTV
{
public:
    ~CDisplayWX();
    void Initialise(void *Handle);
    void UpdateDisplay(wxDC *DC);
    void End(void);
    void ReSize(int Width, int Height);
    void Plot(unsigned int color);
    void NewLine();
    void Refresh();

private:
    wxBitmap *Bitmap=nullptr;
    wxMemoryDC *SrcDC=nullptr;
    wxNativePixelData *PixelData=nullptr;
    wxNativePixelData::Iterator *Pixel=nullptr;
};

and the code that draws onto the bitmap, and blits it to the window looks like

void CDisplayWX::Initialise(void *Handle)
{
    End();

    Bitmap = new wxBitmap(FrameMaxW, FrameMaxH, 24);
    SrcDC=new wxMemoryDC(*Bitmap);
    PixelData = new wxNativePixelData(*Bitmap);
    Pixel = new wxNativePixelData::Iterator(*PixelData);

    Pixel->MoveTo(*PixelData, 0, 0);
    ScanLineX = 0;
    ScanLineY = 0;
}

// If we have finished rendering - either quitting, or
// changed some setting, release all handles and memory used.

void CDisplayWX::End()
{
    if (Pixel) { delete Pixel; Pixel=nullptr; }
    if (PixelData) { delete PixelData; PixelData=nullptr; }
    if (SrcDC) {delete SrcDC; SrcDC=nullptr; }
    if (Bitmap) { delete Bitmap; Bitmap=nullptr; }
}

// UpdateDisplay - called from onPaint event to blit the bitmap
// onscreen.

void CDisplayWX::UpdateDisplay(wxDC *DC)
{
    DC->StretchBlit (0, 0, WindowWidth,  WindowHeight,
                            SrcDC, FrameX, FrameY, FrameW, FrameH);


    if (CreatedDC) delete DC;

    Pixel->MoveTo(*PixelData, 0, 0);
    ScanLineX = 0;
    ScanLineY = 0;

}

void CDisplayWX::Plot(unsigned int color)
{
    Pixel->Red()    = (color >> 16) & 255;
    Pixel->Green()  = (color >> 8) & 255;
    Pixel->Blue()   =  color & 255;

    (*Pixel)++;
    ScanLineX++;
    if (ScanLineX >= FrameMaxW) NewLine();
}

If I draw on the bitmap using SrcDC, I can see my drawing onscreen so i know
bit bitmap itself is OK and the blit operation is working, which leaves the
raw data bit...

Can anyone suggest what I'm doing wrong and why I'm such a numpty...

Mike

Vadim Zeitlin

unread,
Sep 22, 2021, 7:00:32 PM9/22/21
to wx-u...@googlegroups.com
On Wed, 22 Sep 2021 08:04:34 -0700 (PDT) Mike W wrote:

MW> I'm in the process of writing an application that uses wxWidgets. It
MW> compiles and runs fine using msys2 and wx library 3.1.5. I am having
MW> problems, however when I try to compile the code under Ubuntu/wx 3.1.5.
MW> Although the app itself runs fine, the display window just outputs a
MW> plain black window.
MW>
MW> I using wxNativePixelData to draw on a bitmap that I then blit onto the
MW> display window in the onpaint event.

It's rather difficult to find the problem in snippets of unfamiliar code
and I don't have time to do it, unfortunately, but perhaps I can still give
a helpful advice: please have a look at the code doing about the same thing
you describe in the image sample and compare what your code does with the
code there. It can also serve as a useful testbed for your pixel
manipulation code.

Good luck!
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

Eric Jensen

unread,
Sep 22, 2021, 7:42:04 PM9/22/21
to Mike W
Hello Mike,

Wednesday, September 22, 2021, 5:04:34 PM, you wrote:


MW> private:
MW> wxBitmap *Bitmap=nullptr;
MW> wxMemoryDC *SrcDC=nullptr;
MW> wxNativePixelData *PixelData=nullptr;
MW> wxNativePixelData::Iterator *Pixel=nullptr;
MW> };

MW> and the code that draws onto the bitmap, and blits it to the window looks
MW> like

MW> void CDisplayWX::Initialise(void *Handle)
MW> {
MW> End();

MW> Bitmap = new wxBitmap(FrameMaxW, FrameMaxH, 24);
MW> SrcDC=new wxMemoryDC(*Bitmap);
MW> PixelData = new wxNativePixelData(*Bitmap);
MW> Pixel = new wxNativePixelData::Iterator(*PixelData);

MW> Pixel->MoveTo(*PixelData, 0, 0);
MW> ScanLineX = 0;
MW> ScanLineY = 0;
MW> }

You can not have a bitmap assigned to a wxMemoryDC, use wxPixelData
access and use it in wxDC operations at the same time.

Usually wxMemoryDC and wxPixelData are local variables and only used
temporarily while modifiying the bitmap.

After modifying a bitmap using wxMemoryDC, you must un-select the
bitmap from the wxMemoryDC before you can use it anywhere else.

Same goes for wxPixelData access.

Eric





--

Mike W

unread,
Sep 23, 2021, 5:56:16 AM9/23/21
to wx-users
> You can not have a bitmap assigned to a wxMemoryDC, use wxPixelData
> access and use it in wxDC operations at the same time.

I figured this out at around 3am this morning...  The code is actually part of some CRT TV emulation I'm writing (The rest of the  class simulates video noise, bandwidth limitations, sync pulses and the like.  I only use the MemoryDC to blit the final bitmap into the display window once a frame (50 - 60 times a second), whereas the PixelData (Plot function) gets called around 5 million times a second.

> Usually wxMemoryDC and wxPixelData are local variables and only used
> temporarily while modifiying the bitmap.

I came up with a solution.  Every time I need to blit the bitmap to the display window I destroy the PixelData, and create a MemoryDC. I then blit the bitmap, followed by destroying the MemoryDC and recreating the PixelData.  I understand what you say about holding the PixelData only while modifying the data only, but it would seem (I haven't timed it) that recreating the PixelData 5 million times a second would be less than efficient.

Maybe I'm thinking about this all wrong and there's a more efficient way of doing thing.  For Windows I already have a D2d solution that does away with all the wx code and manipulates the window contents itself bit I also need to provide a portable solution too, which is what this code is for.

Mike
Reply all
Reply to author
Forward
0 new messages