Page 1 of 1

Drawing pixel by pixel

Posted: Sun Jul 15, 2018 9:30 am
by crispus
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.

Re: Drawing pixel by pixel

Posted: Sun Jul 15, 2018 9:52 am
by doublemax
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.

Re: Drawing pixel by pixel

Posted: Sun Jul 15, 2018 10:25 am
by crispus
You saved my day. More than 200x faster.
Thank you.