Schrift
[thread]5133[/thread]

Jeden Pixel färben ??? (Seite 2)

Leser: 6


<< |< 1 2 3 >| >> 21 Einträge, 3 Seiten
Dubu
 2005-11-26 15:34
#45058 #45058
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Matze hat schon recht, manchmal moechte man lieber auf die Pixel direkt zugreifen koennen[1]. Mit esskars Loesung wuerde man bei einem kleinen Fenster von 300x300 Pixeln einen Canvas mit 90_000(!) Objekten verwalten muessen, was wohl die meisten Rechner ueberfordert. Tk scheint aber nur diesen objektorientierten Ansatz zu bieten und keinen direkten Zugriff auf die Pixel eines Fensters.

Eine Moeglichkeit mit Tk waere vielleicht, auf einer internen Pixmap zu arbeiten und diese immer wieder in ein Tk::Image-Objekt zu kopieren. Aus Effizienzgruenden koennte man einen Canvas in mehrere Image-Objekte aufteilen, damit nicht bei jeder Aenderung ein grosses Objekt kopiert werden muss.

Alternativ koennte man auch z.B. mit der SDL-Grafiklibrary arbeiten. Ich habe zwar keine Erfahrung damit, aber Spiele wie Frozen Bubble zeigen, dass man damit grafisch ansprechend mit Perl programmieren kann. (Mit Frozen Bubble kann man schoen Leute widerlegen, die der Meinung sind, Perl eigne sich nicht fuer grafiklastige Spiele.)

[1] Zu Zeiten eines C64 und auch noch beim Atari ST/TT konnte man fuer schnelle Pixelgrafiken direkt auf den Bildspeicher zugreifen und dort hineinschreiben. Ach, was habe ich da alles an einfachen Simulationen (Game of Life, Kristallwachstum, Stroemungsverhalten) auf den 640x400 monochrom programmiert ...
Bei Singletasking-Rechnern ist das alles kein Problem, aber wenn man mit Multitasking-Systemen und verschiedenen Fenstern arbeitet, muss man sich schon um Redraws kuemmern, was ein direktes Arbeiten im Bildschirmspeicher praktisch unmoeglich wird - man muss Buffering oder Double-Buffering nehmen und mit memcpy (wer erinnert sich noch an bitblt-Operationen?) auf den Bildschirm kopieren.
lichtkind
 2005-11-26 17:00
#45059 #45059
User since
2004-03-22
5679 Artikel
ModeratorIn + EditorIn
[Homepage]
user image
alternativ könnte man auch WxPerl nehmen da kannst nahc herzenslust auch pixelweise in einem Wx::Image malen und das dann auf ein pane,l button oder was auch immer kleben, und wenn du das render und refresh verhalten selber machen willst brauchst nur den DrawDC auf eignes Objekt verweisen lassen.\n\n

<!--EDIT|lichtkind|1133025812-->
Wiki:Tutorien in der Wiki, mein zeug:
kephra, baumhaus, garten, gezwitscher

Es beginnt immer mit einer Entscheidung.
ptk
 2005-11-26 18:46
#45060 #45060
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
Ich würde in diesem Fall auch mit Tk::Photo arbeiten, mit der Methode put. Aber ein Rennpferd dürfte das nicht sein. Unter Umständen ist es schneller, auf eine externe Bibliothek (GD, Imager, Image::Magick) auszuweichen.
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
use Tk;
$top = new MainWindow;
$p = $top->Photo(-width => 400, -height => 300);
$c = $top->Canvas(-width => 400, -height => 300)->pack(-fill => "both", -expand => 1);
$img = $c->createImage(0,0,-image=>$p,-anchor=>"nw");
for my $x (-$p->width/2 .. $p->width/2) {
my($tx) = int($x+$p->width/2);
my $y = sin($x/10)*$p->height/2;
my($ty) = int($y+$p->height/2);
$p->put("#ff0000", -to => $tx,$ty+1,$tx+1,$ty);
}
MainLoop;
Matze
 2005-11-27 12:04
#45061 #45061
User since
2005-08-29
222 Artikel
BenutzerIn
[Homepage] [default_avatar]
@lichtkind: Ich habe leider noch kein WX/Perl auf meinem Rechner.
Bald richte ich mir einen neuen Rechner mit Unix/Linux ein, da kommt dann alles mögliche von Perl drauf.

@ptk: Das ist das was ich gesucht habe.
Ich denke, wenn ich es schaffe mir ein effektives Modul zum zeichnen der Graphiken schreibe könnte es recht gut klappen.

Nur, beim Canvas hab ich letztens festgestellt, das es immer einen 'Rand' um die Zeichenfläche legt.
Ich habs schon mit -relief, -bd usw. probiert weg zu bekommen, aber der 'Rand' geht einfach nicht weg:

Das Script:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use strict;
use Tk;

my $mw = MainWindow     -> new();

my ($screenx,$screeny) = ($mw -> screenwidth(),
                         $mw -> screenheight());

$mw                     -> FullScreen(1);
$mw                     -> geometry("${screenx}x$screeny");

my $canvas = $mw        -> Canvas       (-background    => "#000000",
                                        -bd            => 0,

-relief        => "flat")->
                                   pack(-fill          => "both",
                                        -expand        => 1);

$mw                     -> bind ('<Key-q>',"exit");

MainLoop;
\n\n

<!--EDIT|esskar|1133099664-->
Mit freundlichen Grüßen: Matze
Dubu
 2005-11-27 13:20
#45062 #45062
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Es fehlt noch -highlightthickness => 0 beim Canvas.

Und bitte, bitte, formatiere deinen Code lesbar und benutze [code]-Tags hier im Forum!
Matze
 2005-11-27 14:06
#45063 #45063
User since
2005-08-29
222 Artikel
BenutzerIn
[Homepage] [default_avatar]
Danke dubu!
Jetzt funktioniert es!!!

Das mit dem code, ich hatte vorher tabstops im Skript, aber die übersieht das Forum, und man kann leider nicht
Code: (dl )
und <span style='font-family:courier'></span> zusammen benutzen.
Aber das nächste mal versuche ich es besser.

Weißt du wie man x und y position im Canvas herausfinden kann, egal wo im Skript ?

MfG. Matze
Mit freundlichen Grüßen: Matze
jemand
 2005-11-27 19:57
#45064 #45064
User since
2004-05-14
231 Artikel
BenutzerIn
[default_avatar]
Hi,
so nun möchte ich Dubu mal recht geben. Es geht wunderbar mit SDL:
Code: (dl )
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
30
31
#!/usr/bin/perl
#Tut bei Mausbewegung einzelne Pixel färben

use strict;
use warnings;
use SDL;
use SDL::App;
use SDL::Color;

my $app = new SDL::App (
-title => 'einzelne Pixel faerbender Test',
-width => 640,
-height => 480,
-depth => 32,
);

my %actions = (
SDL_QUIT() => sub { exit(0); },
SDL_MOUSEMOTION() => \&keydown,
);

$app->loop(\%actions);

sub keydown {
my $farbe = SDL::Color->new(
-r => int(rand(255)),
-g => int(rand(255)),
-b => int(rand(255)),
);
$app->pixel(int(rand(640)), int(rand(480)), $farbe);
}


Wie's dabei allerdings mit der Transparenz aussieht weiß ich nicht. Vielleicht wird die ja in neueren Versionen der SDL-Perl-Bindings unterstützt, aber wie gesagt ich habe keine Ahnung.
Bei mir stiegt die CPU-Auslastung nur um ca 5%
von dem her nicht wirklich viel, obwohl bei kräftiger Mausbewegung schon bestimmt 50 Pixel pro sec gezeichnet werden.

Edit:
Quote
Weißt du wie man x und y position im Canvas herausfinden kann, egal wo im Skript ?


Die x und y Position von was?\n\n

<!--EDIT|jemand|1133114413-->
print uc 'i',chr(29*4).q+'s +.++($_=q-m-),++$_;
print chr for 116,$_[0],97,$_[0],98;
print 'ug,',chr(), scalar reverse qq?!erutaef a s'ti?;
Matze
 2005-11-29 16:56
#45065 #45065
User since
2005-08-29
222 Artikel
BenutzerIn
[Homepage] [default_avatar]
@jemand: x und y Position des Maus-Cursors.

Ich habs jetzt mit put gemacht.
Und es geht auch recht schnell.

Ein Test Script:

Code: (dl )
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!/usr/bin/perl -w
#
# pf.pl
#

use strict;
use Tk;

my %all;
$all{mw} = MainWindow -> new();
$all{mw} -> bind("<Key-q>","exit");

$all{canvas} = $all{mw} ->
Canvas (-background => "#000000",
           -highlightthickness => 0,
           -relief => "flat",
           -bd => 0)->
   pack(-fill => "both",
          -expand => 1);

my ($screenx,$screeny) =
($all{mw} -> screenwidth(),
$all{mw} -> screenheight());

$all{photo} = $all{mw} ->
Photo (-width => $screenx,
         -height => $screeny);

$all{canvas} ->
createImage (0,0,
                  -image => $all{photo},
                  -anchor => "nw");

$all{mw} -> FullScreen(1);
$all{mw} -> geometry  ("${screenx}x$screeny");

for (0..$screenx) {

 my $y = $_;
 $y = $screeny / 2 if $y >= $screeny / 2;

 point($_,$y);

 for (0..10000) {}
 $all{mw} -> update;
}
for (0..$screenx) {

 my $y = $_;
 $y = $screeny / 2 if $y >= $screeny / 2;

 my $x = $screenx - $_;

 point($x,$y);

 for (0..10000) {}
 $all{mw} -> update;
}

MainLoop;

sub point {
 my ($x,$y,$color);

 if ($#_ >= 0) {
   $x = shift;
   if ($#_ >= 0) {
     $y = shift;
     if ($#_ >= 0) {
       $color = shift;
     }
     else {
       $color = "#ff0000";
     }
   }
   else {
     $y = 0;
     $color = "#ff0000";
   }
 }
 else {
   $x = 0;
   $y = 0;
   $color = "#ff0000";
 }

 $all{photo} ->
 put ("$color",
       -to => $x,$y);
}


Ich denke es ist diesmal besser formatiert.

MfG. Matze
Mit freundlichen Grüßen: Matze
ptk
 2005-11-29 23:34
#45066 #45066
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
Code: (dl )
$mw->pointerxy
für die absoluten Koordinaten, besser aber
Code: (dl )
$c->CanvasBind("<Motion>", ...)
verwenden und (glaube ich) Ev("x") und Ev("y") auslesen.
Matze
 2005-11-30 16:25
#45067 #45067
User since
2005-08-29
222 Artikel
BenutzerIn
[Homepage] [default_avatar]
Ich weiß leider nicht was genau <Motion> abfragt, ob der Maus-Cursor bewegt wird ?
Ev("x") bzw. Ev("y") habe ich auch benutzt, allerdings mit <ButtonPress-1>.

MfG. Matze\n\n

<!--EDIT|Matze|1133360843-->
Mit freundlichen Grüßen: Matze
<< |< 1 2 3 >| >> 21 Einträge, 3 Seiten



View all threads created 2005-11-24 22:53.