Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ProgressBar could use less memory, operate more efficiently #10

Open
jepler opened this issue Jul 21, 2020 · 7 comments
Open

ProgressBar could use less memory, operate more efficiently #10

jepler opened this issue Jul 21, 2020 · 7 comments
Labels
enhancement New feature or request

Comments

@jepler
Copy link
Member

jepler commented Jul 21, 2020

The ProgressBar is a 1×1 tilegrid configured to display a W×H bitmap. Instead, it could be a W×1 tile grid, displaying 1×H slices from a 3×H bitmap.

Three tall elements are needed: One which is entirely the outline color; one which is the outline color at the top and bottom and transparent/black in the middle, and one that is the outline color at the top and bottom and the bar color in the middle.

This should reduce memory consumption (from W×H to W+3×H times some constant) and speed updates, since a progress change P pixels wide would only have to update P tilegrid entries instead of P×H bitmap entries. (however, the amount of data actually sent over SPI/I2C to the display would not change)

@FoamyGuy
Copy link
Contributor

I had started work changing the progress bar implementation over to vectorio the other day but ran into trouble.

I think with the absolute latest builds of the system the required fixes inside vectorio are in and I made a few more fixes in my working branch of the library.

I've created #11 with those changes. I did end up seeing a decent memory reduction with that approach.

What do you think about vectorio.Polygons vs. the wider tilemap with slices? I don't think I grok enough of the larger picture to know which is likely to be more efficient.

@evaherrada evaherrada added the enhancement New feature or request label Jul 23, 2020
@jepler
Copy link
Member Author

jepler commented Jul 23, 2020

I think vectorio has a good shot at being more efficient, but if compatibility with 5.x is desired then there might have to be two sets of code...

@FoamyGuy
Copy link
Contributor

Ah, I definitely overlooked the compatibility issue. I think it would be good to offer backward compatibility at least for a while.

@makermelissa
Copy link

Same with Blinka until there's a vectorio module added.

@tannewt
Copy link
Member

tannewt commented Jul 23, 2020

I think a TileGrid with multiple tiles will be more efficient than a bitmap if the height of the bar is more than 8 because TileGrid allocates a byte for each tile it shows.

vectorio or displayio.Shape will be much more efficient because they just save bounds, not each pixel.

@FoamyGuy
Copy link
Contributor

Is there any further documentation or an example of how to use displayio.Shape? From the docs here: https://circuitpython.readthedocs.io/en/latest/shared-bindings/displayio/#displayio.Shape I'm not sure how to create one and get it showing on the screen.

@tannewt
Copy link
Member

tannewt commented Jul 24, 2020

I have a test somewhere but I can probably describe it.

You can use it in place of a Bitmap. Instead of storing each pixel, it stores a start and stop x value for every y. x values in the range are 1 and the rest are zero. In other words, for every row, you can store one range of "on" pixels.

This makes it easy to store a solid shape. With mirror_x and mirror_y you can define a half or quarter of the shape instead and have it mirror the pixel ranges (creating two stretches of pixels per row and therefore outlines of symmetric shapes).

set_boundary is used to set that x range for a given row. (and wow, the docs of set_boundary aren't right) I meant to add the index ability that would be ok as long as you set a pixel to 1 if it's adjacent to a 1.

A rectangle would be something like:

s = displayio.Shape(w, h, mirror_x=True, mirror_y=True)
for y in range(h // 2):
  s.set_boundary(y, 0, (w + 1) // 2)

You can then also alter the start of the first few rows to round the corners too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants