Triangle, circle ellipse and rounded rectangle #26
Replies: 9 comments 3 replies
-
Thank you for the code. Regarding the device driver there are many ST7735 variants, the driver works with the Adafruit display but may well need adapting for other hardware. Users of unsupported hardware need to undertake this themselves (as you have). I can only support hardware I possess. As for circle, triangle etc, I think these should be handled in C. Coincidentally I raised this point yesterday. A key aim of nano-gui is small size. Barring actual bug fixes, the only changes I'm prepared to make are to add new widgets as these don't add to the size of the core code. |
Beta Was this translation helpful? Give feedback.
-
I think a set of graphics primitives for framebuf is a good idea. It's possible that the maintainers will not want this done as part of the firmware because of the added size. So a Python solution would be good. In my view it has no real connection with nano-gui. The deliberately undocumented circle and fill_circle methods exist only to support widgets and polar graphs. As you point out circle doesn't work well with large widths; the algorithm is crude. In practice nano-gui only ever calls it with the default value 1, so I might save a few bytes by removing this option. What I suggest you do is create a FramebufGraphics class which provides these additional graphics methods. This could be a subclass of FrameBuffer and could be used with or without nano-gui. A small change to the device driver would be needed so that it could export its buffer def __init__(self, ...):
self.mode = framebuf.GS4_HMSB # or whatever
self.buf = bytearray(...) # Now a bound variable
def buffer(self):
return self.buf, self.width, self.height, self.mode Your color_setup.py would then do ssd = SSD(spi, pcs, pdc, prst, height) # Create a display instance
gfb = FramebufGraphics(*ssd.buffer()) # Your framebuf is mapped onto the same physical memory as nano-gui You could then call existing FrameBuffer methods (gfb.line(...)) and your added methods (gfb.ellipse(...)). An alternative implementation would be to use composition rather than inheritance with stub methods to access the existing FrameBuffer methods. I think a FramebufGraphics class would be a useful thing to develop and to offer to the community. If you do this, I'll modify the device drivers to enable access to the buffer. |
Beta Was this translation helpful? Give feedback.
-
I had a feeling when I posted that there was a better way. That is much simpler, using composition rather than inheritance as ssd is an instance.
Making these bound variables would be fine, but I'd caution against accessing buf. The only reason my original suggestion presented these variables was (as you spotted) to enable another FrameBuffer to be instantiated. Accessing buf to draw graphics brings in complexity because of the different modes. Further there is a risk of future new modes being added to the C code. These issues can be avoided by using the FrameBuffer graphics primitives. I would start on that basis using my unmodified driver and see how you get on. |
Beta Was this translation helpful? Give feedback.
-
Hi Peter, |
Beta Was this translation helpful? Give feedback.
-
The initializer is awful :-)
|
Beta Was this translation helpful? Give feedback.
-
Is there a better way of doing this? Another approach is a set of stub methods, but yours is more efficient. I'll try your code over the weekend. The code looks good. One minor query: given that a circle is a special case of an ellipse, a small simplification would be to have the .circle() method call .ellipse(). Is there a performance reason to avoid this? |
Beta Was this translation helpful? Give feedback.
-
Yes, that simplification is probably justified. Circle is only 7 % faster than an ellipse with a=b (=r). Perhaps I will conduct a test to see if the generator function in this case really exactly prduces the same pixels. |
Beta Was this translation helpful? Give feedback.
-
You can return values @micropython.viper
def foo(a:int, b:int) -> int:
return a + b Viper is a bit of a black art but it is phenomenally fast. Type annotations are vital. I assume you've seen the doc. Beyond that the best approach is to experiment and to look at other people's code. You'll have found some of my efforts in the display drivers. There is a lot of Viper in this from Robert Hammelrath. As with all optimisation it's best to put the effort into the code which is most performance-critical, but given what you're doing I guess that's most of it... |
Beta Was this translation helpful? Give feedback.
-
Damien is rarely active in the forum. The project's general policy is that if something can be done in Python it should be. This is to save firmware bytes which are an overhead on everybody. In my view given the levels of performance you're achieving, I agree with you that there's no real case for implementing it in C. I think it's best offered as an unofficial independent repo. For an official decision you'd need to contact @dpgeorge or @jimmo. |
Beta Was this translation helpful? Give feedback.
-
Hello Peter,
thank you first for this great nano-gui project.
Based on it I got my 160x128 st7735-based LCD running.
And it's really fast and takes only 11K of RAM with 4-bit color-mode. I'm impressed.
First I had to correct the _init() functions in st7735r.py and st7735r4b.py a bit.
Then I started to play around. I was disturbed by the circle() function in nanogui.py when applied with e.g. width=10 . It left dots uncolored. So I started to find out what your algorithm was and began to read about Bresenham algorithms.
In the end I programmed triangle, circle, ellipse and rounded rect basically with the same approach: Generator functions deliver (x,y)-pairs for the left and right boundary and hline()s are drawn between them.
This has the advantage that the outline of filled shapes agree with the corresponding lines of shapes drawn unfilled.
I put all this in one file. Hope you are interested. Would be nice to hear (read) your opinion.
Perhaps nano-gui can profit from it.
As I'm not familiar with github yet I cannot make a pull-request. I will instead drop this file here.
Another question: Would you prefer this being discussed on the micropython forum?
Cheers,
Raul
st7735r4b_mx2.py.zip
Beta Was this translation helpful? Give feedback.
All reactions