Entwickler-Ecke
WPF / Silverlight - [Einsteiger] pixelweise zeichnen in wpf
miniC# - Mo 22.12.08 20:51
Titel: [Einsteiger] pixelweise zeichnen in wpf
hallo,
ich bins mal wieder, mit einer ziemlich grundlegenden frage. ich habe eine klasse, die einen perlin noise in form eines float arrays erzeugt. nun stellt sich mir die frage der darstellung der daten in einem wpf projekt. ich habe ein bissel gegraben und mein einziger fund war die BitmapSource.Create methode. da mein noise nun aber animiert ist und letztendlich auch in realtime auf usereingaben reagieren soll, erscheint mir es etwas *unelegant* framebyframe ein neues bitmap zu erzeugen.
was wäre denn ein möglichste performamente (schreibt man das so?) herangehensweise an eine komplett pixelbasierte eigene zeichenmethode ? quasi eine usercontrol, die pixel für pixel gezeichnet wird. muss ich mich da mit direct 2d auseinadersetzen ? grob gesucht habe ich da schon, jeodch erfolglos. ich bitte um nachsicht, meine c# erfahrung im allgemeinen ist immernoch sehr gering :)
gruß und vielen dank im vorraus,
euer miniC#
Christian S. - Mo 22.12.08 21:19
Hallo!
Ich denke, das WriteableBitmap wäre da eine gute Möglichkeit, vor allem seit dem SP1 für .NET 3.5. Damit kann man sowas ziemlich performant umsetzen. Einfach einmal ein WriteableBitmap erzeugen und einem Image als Source zuweisen. Jede Änderung an dem WriteableBitmap wird automatisch in dem Image angezeigt.
Ziemlich rasch geht es bei großen Änderungen vor allem, wenn man die WritePixels-Methode verwendet (deren Idee dasselbe ist wie bei LockBits / UnLockBits beim guten alten Bitmap ;-)).
Letztens für mich testweise geschrieben:
Delphi-Prism-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| constructor Window1; begin InitializeComponent();
fWriteableBitmap := new WriteableBitmap(1024, 256, 96, 96, PixelFormats.Bgr32, nil); image1.Source := fWriteableBitmap;
fRect := new Int32Rect(0, 0, Integer(fWriteableBitmap.Width), Integer(fWriteableBitmap.Height)); fRandom := new Random; end;
method Window1.image1_MouseMove(sender: System.Object; e: System.Windows.Input.MouseEventArgs); begin var buffer := new Byte[fWriteableBitmap.BackBufferStride * Integer(fWriteableBitmap.Height)];
for i : Integer := 0 to buffer.Length-1 step 4 do begin buffer[i] := Byte( fRandom.Next(0,255) ); buffer[i+1] := Byte( fRandom.Next(0,255) ); buffer[i+2] := Byte( fRandom.Next(0,255) ); end; fWriteableBitmap.WritePixels(fRect, buffer, fWriteableBitmap.BackBufferStride, 0); end; |
Hier wird ein WriteableBitmap bei jeder Mausbewegung komplett neu gefüllt, was ziemlich rasch funktioniert :-)
Grüße
Christian
miniC# - Di 23.12.08 00:19
hallo,
zunächst vielen dank für die raschen antworten. ich werde morgen die WriteableBitmap klasse testen, klingt einfach und gut :). hlsl ist sicher eine seher spannende sache (vorallem wenn man an bunten bildchen interessiert ist, so wie ich), jedoch far to much für mich im moment, bin schon einige mal darüber gestolpert in mdsn und habe es für ferne zukunft gebookmarkt ;).
jetzt werde ich mich wieder in den kampf mit geschenkpapier und und geschenkband begeben. *schere zwischen die zähne klemm* ARRR !!!
gruß,
miniC#
miniC# - Di 23.12.08 17:11
funktioniert klasse, danke für das beispiel.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| public partial class Window1 : Window { private WriteableBitmap render; private Image disp; private Random r;
public Window1() { InitializeComponent(); render = new WriteableBitmap(512, 512, 96, 96, PixelFormats.Rgb24, null); disp = new Image(); disp.Source = render; r = new Random(); this.Content = disp; }
private void Window_MouseMove(object sender, MouseEventArgs e) { byte[] buffer = new byte[render.BackBufferStride * (int)render.Height]; for (int i = 0; i < buffer.Length - 1; i += 4) { buffer[i] = (byte)(r.Next(0, 255)); buffer[i + 1] = (byte)(r.Next(0, 255)); buffer[i + 2] = (byte)(r.Next(0, 255)); }
render.WritePixels(new Int32Rect(0, 0, 512, 512), buffer, render.BackBufferStride, 0); } } |
Christian S. - Di 23.12.08 17:30
Du musst aber beachten, dass Du ein Pixelformat gewählt hast, wo nur 24 Bit (also 3 Byte) pro Pixel gespeichert werden. Damit ist die Schrittweite in Deiner Schleife um 1 zu groß.
Außerdem steht in den Dokus zur WriteableBitmap-Klasse:
WriteableBitmap Constructor - Remarks: |
The preferred values for pixelFormat are Bgr32 and Pbgra32. These formats are natively supported and do not require a format conversion. Other pixelFormat values require a format conversion for each frame update, which reduces performance. |
miniC# - Di 23.12.08 17:33
hab ich schon gemerkt ;) verwende nun brav bgr32 :).
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!