Kleine c-routine um auf Pixelbasis Kreise und Striche zu zeichnen

OP #7950172
Lesenswert?
• ▲
▼

Hi zusammen,

ich suche eine kleine c-Datei in der wenige einfache routinen zum Kreise und Striche Zeichnen sind.

Basieren sollte alles auf einer set_pixel(x,y,color) - Funktion.

void draw_circle(uint8_t x,uint8_t y, uint8_t r, uint8_t color); void draw_line(uint8_t x1,uint8_t y1,uint8_t x2, uint8_t y2, uint8_t color);

Wären völlig ausreichend. Bild ist nur 32y64 Pixel.

Danke

#7950189
Lesenswert?
• ▲
▼

Martin S. schrieb:

ich suche eine kleine c-Datei in der wenige einfache routinen zum Kreise und Striche Zeichnen sind.

Eine kleine C-Datei wirst du nicht finden, aber eine grosse. Dort must du suchen nach Drawline und Drawcircle. Diese Funktionen musst du ein eine kleine C-Datei kopieren, und voilá, schon hast du sie.

Die erwähnte (grosse) Datei findest du in allen üblichen Ansammlungen ("Libs") von Funktionen zum Ansteuern von TFT-Displays.

Oder war deine Suchanfrage so zu verstehen dass wir das machen sollen?

Beitrag #7950207 wurde von einem Moderator gelöscht.
(Firma: Q3) #7950223
Lesenswert?
• ▲
▼

Sowas mache ich immer als "Fingerübung" in Programmierkursen. Will sagen, das kann man mit wenigen Zeilen auch selber schreiben. Hier eine Beschreibung der Algorithmen:

  1. Line, hat Koordinaten der Endpunkte XA,YA und XE,YE

a) Länge der Linie nach Pythagoras berechnen b) die Differenz DX aus XE-XA und DY aus YE-YA bestimmen c) die Schrittweite für X und Y bestimmen: XS = DX/Länge, YS = DY/Länge c) dann, beginnend mit XA,YA die Länge entlang bis zu XE,YE iterieren und jedesmal SX zu X und SY zu Y dazu addieren

  1. Kreis, hat Koordinaten des Mittelpunkes XM,YM und einen Radius R

a) Länge des Umfanges über 2 * Pi * R berechnen b) die Zahl 2 Pi durch die Länge teilen, das ist die Schrittweite c) von 0 nach 2 * PI in der ermittelten Schrittweite iterieren, dabei die Koordinaten der zu setzenden Pixel (X,Y) berechnen. POS ist der Momentanwert:

x = XM + sin(POS) * R, y = YM + cos(POS) * R


OP #7950226
Lesenswert?
• ▲
▼

Interessant wäre wie man die "Strichdicke" bei Kreisen realisieren könnte.

Erster Gedanke wäre ja einfach zwei ein-strich Dicke Kreise mit einem Pixel Radius weniger ineinander zu zeichnen, doch dann entstehen immer mal Löcher im Kreis, was ja auch logisch ist, aber wie das zu machen wäre, wäre interessant für mich ebenso wie das Füllen von Kreisen...

// /* Interne Hilfsroutine zum kreiszeichen, spiegelt die Segmente */ //

void circlepoints(unsigned int cx, unsigned int cy, unsigned int x, unsigned int y, unsigned char color) { if (x == 0) { lcdg_drawpixel(cx,cy+y, color); lcdg_drawpixel(cx,cy-y, color); lcdg_drawpixel(cx+y,cy, color); lcdg_drawpixel(cx-y,cy, color); } else if (x == y) { lcdg_drawpixel(cx+x,cy+y, color); lcdg_drawpixel(cx-x,cy+y, color); lcdg_drawpixel(cx+x,cy-y, color); lcdg_drawpixel(cx-x,cy-y, color); } else if (x<y) { lcdg_drawpixel(cx+x,cy+y, color); lcdg_drawpixel(cx-x,cy+y, color); lcdg_drawpixel(cx+x,cy-y, color); lcdg_drawpixel(cx-x,cy-y, color); lcdg_drawpixel(cx+y,cy+x, color); lcdg_drawpixel(cx-y,cy+x, color); lcdg_drawpixel(cx+y,cy-x, color); lcdg_drawpixel(cx-y,cy-x, color); } }

// /* Zeichnet einen Kreis um die angebene Position */ //

void lcdg_circle(unsigned char xCenter, unsigned char yCenter, unsigned char radius, unsigned char color) { unsigned int x= 0; unsigned int y= radius; signed int p= (5- radius*4)/4;

circlepoints(xCenter, yCenter, x, y, color); while (x<y) { x++; if (p<0) { p += 2 * x + 1; } else { y--; p += 2 * (x-y)+1; } circlepoints(xCenter, yCenter, x, y, color); } }

(Firma: Q3) #7950233
Lesenswert?
• ▲
▼

Martin S. schrieb:

Interessant wäre wie man die "Strichdicke" bei Kreisen realisieren könnte.

Wenn man für alle berechneten Werte Float oder Double nimmt, etstehen keine Lücken. Das ist sicher nicht perfekt für eine hoch optimierte Grafik-Lib, zum Grundverständnis reicht es allemal.

Die Liniendicke kann man, wenn vorhanden, über den Parameter "penwidth" vorher einstellen, ebenso die Farbe. Wenn nicht, muss man kleine gefüllte Kreise oder Quadrate verwenden und jedesmal "händisch" die Pixel in der passenden Farbe hinmalen.

#7950287
Lesenswert?
• ▲
▼

Frank E. schrieb:

x = XM + sin(POS) * R, y = YM + cos(POS) * R

Das ist als Fingerübung ok. Habe ich im 9ten Schuljahr auch so gemacht (wollte ein Zeichenprogramm auf deren Acorn erstellen, ja, Größenwahn). Aber das ist nicht Kanonen auf Spatzen, sondern Flugzeugträger zum Milchholen.

(Über die Jahre habe ich dann nach und nach gesehen, wie sowas in einfach und Integer)

#7951634
Lesenswert?
• ▲
▼

Hier mal ein Beispielprogram mit Pythagoras. Für Disks ausserhalb / grösser als das Bild, werden nicht besonders effizient sein. Dünne ringe auch nicht.

Hab gleich auch noch Gradienten eingebaut. Damit bekommt man auch gratis anti-aliasing, ist einfach ein radialer Gradient von ungefähr 1px Dicke zwischen den 2 Farben (wobei eine auch Transparent sein kann).

Für die Farben hab ich RGBA Premultiplied Alpha verwendet. Das heisst, R, G und B sind schon im vornherein mit dem Alpha Kanal Multipliziert, also <= Alpha. Das hilft gegen das Problem, dass man zwischen Weiss und Transparent, in der Mitte grau bekommt. Denn 0.5 R und 0.5 A premultiplied sind R / A = 0.5 / 0.5 = 1, 1 R straight.

1
gcc x.c -o x2 -lm && ./x2 | convert -size 256x256 -depth 8 rgba:- o.png
Angehängte Dateien:
#7951904
Lesenswert?
• ▲
▼

Falls notwendig:

1
--- x.c.orig
2
+++ x.c
3
@@ -5,2 +5,5 @@
4
 #include <stdio.h>
5
+#if _WIN32
6
+#include <fcntl.h>
7
+#endif
8

9
@@ -100,2 +103,5 @@ void premultiplied_to_straight(size_t n, RGBA data[n]){
10
 int main(){
11
+#if _WIN32
12
+  _setmode(_fileno(stdout), _O_BINARY);
13
+#endif
14
   RGBA data[256][256] = {0,0,0,0};
15
@@ -165,2 +171,6 @@ int main(){
16

17
+#if USE_NETPBM_PAM
18
+  printf("P7\nWIDTH %zu\nHEIGHT %zu\nDEPTH 4\nMAXVAL 255\n"
19
+         "TUPLTYPE RGB_ALPHA\nENDHDR\n", img.width, img.height);
20
+#endif
21
   fwrite(data, 1, sizeof(data), stdout);
#7951952
Lesenswert?
• ▲
▼

Martin S. schrieb:

aber wie das zu machen wäre, wäre interessant für mich ebenso wie das Füllen von Kreisen...

... im Anhang die von mir verwendeten Funktionen zum Zeichnen von Linien und Kreisen, basierend auf dem bereits oben genannten Algorithmus nach Bresenham aus Wikipedia. Erweitert hier eine Funktion zum Zeichnen von gefüllten Ellipsen und Kreisen.

Funktion fastxline und putpixel sind anzupassen.

Angehängte Dateien:

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.