Drawing pixel by pixel

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
crispus
In need of some credit
In need of some credit
Posts: 2
Joined: Sun Jul 15, 2018 8:54 am

Drawing pixel by pixel

Post by crispus » Sun Jul 15, 2018 9:30 am

Hi guys,

A bit of a background:
I have a small microcontroller with a display and I have to make a GUI. Testing and deploying the result on the MCU is difficult (slow-going) and I want to be able to do it on my PC.
The way the code is written on the MCU, all I have is a callback which sets a color to a (x,y).

I tried this for each pixel:

Code: Select all

brush.SetColour(r,g,b);
dc.SetBrush(brush);
dc.DrawRectangle(x * PixelSize, y * PixelSize, PixelSize, PixelSize);
but it is painfully slow.

Also, I tried to buffer the pixels in a "graphics memory" and paint it periodically:

Code: Select all

void BasicDrawPane::render(wxDC&  dc) {

    auto start = std::chrono::steady_clock::now();

    dc.SetPen(*wxTRANSPARENT_PEN);
    dc.DrawRectangle(0, 0, width, height);
    for (int i = 0; i < LCD_XSIZE; i++) {
        for (int j = 0; j < LCD_YSIZE; j++) {
            if(gpuMEM[i][j] & DirtyBit) {
                this->brush.SetColour(make_rgb_triplet(gpuMEM[i][j]));
                dc.SetBrush(brush);
                dc.DrawRectangle(i * PixelSize, j * PixelSize, PixelSize, PixelSize);
            }
        }
    }

    MilliSeconds totalTime = std::chrono::duration_cast<MilliSeconds>(std::chrono::steady_clock::now() - start);
    printf("Total time in ms: %lld\n", totalTime.count());
}
It is better, but still takes more than 1 second to paint the whole buffer (400 x 240)

What I would like to have is:

Code: Select all

int tft_drawPixel(int x, int y, COLOR_T color) {
    //gpuMEM[x][y] = static_cast<uint32_t>(color) | DirtyBit;
    wxColor wxCol(get_R(color), get_G(color), get_B(color));
    someWxObject.SetPixel(x, y, wxCol);
    elapsed = 0;
    return 0;
}
Or even better:

Code: Select all

someWxObject.DrawRectangle(wxCol, x * PixelSize, y * PixelSize, PixelSize, PixelSize);
Thank you.

User avatar
doublemax
Moderator
Moderator
Posts: 14277
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Drawing pixel by pixel

Post by doublemax » Sun Jul 15, 2018 9:52 am

Ignore the pixelsize, generate a wxImage at original resolution, use wxImage::SetRGB() to set indivudual pixels. For drawing, convert it to wxBitmap and use wxDC::SetUserscale() before drawing to scale it to the desired size.

Alternatively, use a wxBitmap instead of wxImage and use raw bitmap access to set individual pixels:
http://docs.wxwidgets.org/trunk/classwx_pixel_data.html

This makes the final conversion from wxImage to wxBitmap unnecessary and could be a little faster.
Use the source, Luke!

crispus
In need of some credit
In need of some credit
Posts: 2
Joined: Sun Jul 15, 2018 8:54 am

Re: Drawing pixel by pixel

Post by crispus » Sun Jul 15, 2018 10:25 am

You saved my day. More than 200x faster.
Thank you.

Post Reply