Mathematische Funktion gesucht, ich bin wohl gerade irgendwie zu blöd...

benneq

Fleet Admiral
Registriert
Juli 2010
Beiträge
12.620
Moin!

Also eigentlich sieht es auf dem Papier ganz einfach aus:

Code:
1     1     1     1     1

1    0.75  0.75  0.75  0.75

1    0.75  0.5   0.5   0.5

1    0.75  0.5   0.25  0.25

1    0.75  0.5   0.25   0

Das Muster sieht sooo einfach aus. Aber ich komm nicht drauf, wie man das anstellt. :D Wahrscheinlich bin ich einfach zu müde. Ich hab gerade schon beim copy&pasten Fehler produziert. Schafft das mal!

Um es zu präzisieren. Es geht hier um Canvas. Die Werte die da stehen, sind die Alpha-Werte für Punkte (also Transparenz^(-1)). Ich möchte einen Haufen Geraden zeichnen, die genau diesen Transparenzverlauf aufweisen. Die Geraden in Canvas gibt man folgendermaßen an:
(x0,y0 , x1,y1) also Startpunkt und Endpunkt. Hinzu kommt noch die Funktion 'addColorStop(double offset, String color)'. Überlicherweise arbeitet man mit:
addColorStop(0, 1.Farbe);
addColorStop(1, 2.Farbe);
und dann hat die gezeichnete Gerade einen Farbverlauf vom Anfang mit 1.Farbe zum Ende mit 2.Farbe. Ich gebe meine Farbe mit Alpha-Wert an wodurch ich eigentlich einen Verlauf hinbekommen sollte... sollte ... sollte...


Bitte Hilfe :)
Danke


EDIT:
Falls jemand Lust hat die 2te Hälfte des Problems gleich mitzulösen:
Ein Verlauf von Schwarz nach Weiß (oben nach unten) linear. Aber das dürfte halb so schwer werden, wenn da s Muster von oben erstmal irgendwie umsetzbar ist ^^
 
Zuletzt bearbeitet:
Welche Programmiersprache?

Btw, ich würde das mit mehreren Füllmethoden oder Linien in einer For-Schleife machen. Also zB:
for (float i = 0; i <= 4; i++) {
Fülle(x1 + i, y1 + i, x2, y2, Alpha - i*0.25)
}
Die Füllmethode ist zwar etwas ineffizient, aber bei einfachen Elementen ist das ausreichend.
 
Zuletzt bearbeitet:
Ich zeichne eh Linie für Linie. Also die Schleife ist schon da. Das ganze Canvas wird genau 1x gezeichnet und für das was ich dann eigentlich vorhabe passe ich die Farbe des Layers hinter dem Canvas an. ^^

Sprache ist an sich Java, d.h. GWT, aber ich hab kein Problem damit auch andere Sprachen zu lesen, solang es nichts Funktionales ist ;)

EDIT: deine Funktion ist aber ein wenig nichts-aussagend... Was sind x1,y1 und x2,y2 ? Horizontal zeichnen geht nicht, vertikal auch nicht. man muss das irgendwie diagonal lösen , stimmts?
 
Wie soll man das mit dem Gradient da oben verstehen? Das ist doch auch nur eine einfache Schleife. Soll da drüber dann der Rahmen gezeichnet werden?
 
Hm... ich glaub, in meinem Kopf hat sich eben eine Lösung zusammen gesetzt :D

Nehmen wir an, dass das Bild 3x3 Pixel groß ist (also jeweils Pixel 0-2):
Dann zeichnet man folgende Diagonalen (Punkt 0,0 ist oben links in der Ecke):

(0,0) -> (2,2)
(1,0) -> (3,2)
(2,0) -> (4,2)
(0,1) -> (2,3)
(0,2) -> (2,4)
Damit sollten die Alpha-Werte stimmen, wenn man die Transparenz immer von Anfang (1) bis Ende (0) laufen lässt. Die Linien gehen zwar über das Bild hinhaus, aber das wird ja eh abgeschnitten ;)
Jetzt müsste man nur noch die Schwarz-Weiß-Werte irgendwie mit da rein rechnen ^^...


EDIT: Ich versuchs nochmal in ASCII-Art :D
Code:
          (0,0)
            X----------
            |\   \   \|    <-- für diese 3 Linien ist hier Opacity 1
            | \   \   \
            |  \   \  |\
opacity 1-> |\  \   \ | \
            | \  \   \   \
            |  \  \   \   \
opacity 1-> |\  \  \  |\   \
            | \  \  \ | \   \   <-- und hier opacity 0
            ---\--\---X
                \  \   (2,2)
                 \  \  <- opacity 0
                  \  
                   \
                    \ <- opacity 0

Das Rechteckt ist das eigentliche Bild und die Schrägstriche sind die zu zeichnenden Linien
 
Zuletzt bearbeitet:
Mach's dir einfacher und verwende vorgefertigte Bitmaps, die du hinterher maximal nur noch miteinander verrechnen musst.
Das geht schneller und einfacher, als die den ultimativen (;)) Zeichenalgorithmus zu basteln.
 
Eine Bitmap ist aber nicht beliebig skalierbar :/
Ergänzung ()

Habs geschafft!

Nach vielem Überlegen ist der Code erstaunlich kurz geworden :D

Code:
for(int x=0; x<width; x++) {
	CanvasGradient grad = c.createLinearGradient(x, 0, x, height-1);
	grad.addColorStop(0, "rgba(0, 0, 0, 1)");
	int gray = (int) Math.round((255d/height)*x);
	grad.addColorStop((1d/height)*x, "rgba("+gray+", "+gray+", "+gray+", "+(1-(double) x/(height-1))+")");
	grad.addColorStop(1, "rgba(255, 255, 255, "+(1-(double) x/(height-1))+")");
	c.setFillStyle(grad);
	c.fillRect(x, 0, 1, height-1);
}
Also was macht das Ding nun?
  • Es durchläuft eine Schleife für die x-Koordinaten, von links nach rechts, beginnend bei 0, Ende bei (Breite-1)
  • In jedem Durchlauf erzeuge ich eine vertikale Linie (das macht die letzte Zeile: fillRect()) an der aktuellen x-Position
  • Jede Linie bekommt einen Farbverlauf (linearGradient), der von oben nach unten verläuft
  • Der Farbverlauf zeichnet zum einen den Alpha-Wert mittels von oben (y-Position 0) bis zur Diagonalen (y=x) der Alpha Verlauf ist dabei: 1 bis (1 - (x/(height-1)). Für den Rest darunter bleibt der Alpha-Kanal konstant
  • Zum anderen wird der Übergang von schwarz(oben) nach weiß(unten) gezeichnet. Also einfach gesagt: addColorStop(0, #000) und addColorStop(1, #FFF). Was anderes mach ich auch nicht, nur dass ich an dem Punkt wo der Alpha-Wert sich nicht mehr ändert den korrekten grau-Wert eintragen muss. Da aber alle linear verläuft ist der Wert einfach: (255/height) * x

Im Anhang gibt's das Ergebnis! Das passiert, wenn man den Hintergrund knall-Rot färbt (#FF0000).
Ergänzung ()

Mir ist aufgefallen, dass folgende Lösung ein schöneres Ergebnis erzielt (und dabei noch wesentlich performanter ist):

Code:
CanvasGradient grad = c.createLinearGradient(0, 0, width-1, 0);
grad.addColorStop(0, "rgba(255,255,255,1)");
grad.addColorStop(1, "rgba(255,255,255,0)");
c.setFillStyle(grad);
c.fillRect(0, 0, width, height);
		
CanvasGradient grad2 = c.createLinearGradient(0, 0, 0, height-1);
grad2.addColorStop(0, "rgba(0,0,0,1)");
grad2.addColorStop(1, "rgba(0,0,0,0)");
c.setFillStyle(grad2);
c.fillRect(0, 0, width, height);

Erklärung ganz einfach:
  • Die obere Hälfte erstellt einen Farbverlauf von links nach rechts. Von weiß+sichtbar zu weiß+unsichtbar
  • Die untere Hälfte erstellt einen Farbverlauf von oben nach unten. Von schwarz+sichtbar zu schwarz+unsichtbar

Im emulierten Developer-Mode merkt man den Geschwindigkeitszuwachs extrem :)
 

Anhänge

  • Bildschirmfoto 2011-09-07 um 17.54.12.png
    Bildschirmfoto 2011-09-07 um 17.54.12.png
    31,6 KB · Aufrufe: 146
Zurück
Oben