MoinMoin,
ich versuche gerade Daten aus einem Array in eine Bitmap zu schreiben.
Dazu hab ich mir rausgesucht, wie so eine Bitmap aufgebaut ist, habe
versucht das umzusetzen, aber die Datei die ich erzeuge, lässt sich
nicht öffnen.
Als erstes habe ich versucht, einfach nur den Header in die zu
erzeugende Datei zu schreiben, diese wurde jedoch nur 15byte statt der
erwarteten 54byte groß.
Ich schreibe meine Werte mit fputc in die Datei, will aber eigentlich
uint32 in der Datei haben, und aus dem Header der BMP kommen auch noch
einige int32 und uint32.
Ich vermute nun, dass fputc nur chars schreibt (also 8bittige Werte?),
bräuchte aber wohl etwas, das mir je nach Größe der aktuell zu
schreibenden Variable einen int16, uint16, int32 oder uint32 schreibt.
Hier mal mein aktueller Code, in der Funktion Mandelbrot wird das Array
erstellt, welches die Bilddaten beinhaltet. BMP_AUsgeben soll dann die
.bmp-Datei erzeugen:
MfG Chaos
j. t. schrieb:> MoinMoin,> ich versuche gerade Daten aus einem Array in eine Bitmap zu schreiben.> Dazu hab ich mir rausgesucht, wie so eine Bitmap aufgebaut ist, habe> versucht das umzusetzen, aber die Datei die ich erzeuge, lässt sich> nicht öffnen.
Ah, mit "Bitmap" meinst du eine BMP-Datei. Eigentlich haben diese mit
Bitmaps gar nix zu tun. Da hat Microsoft mal wieder einen Begriff falsch
verstanden.
> Ich vermute nun, dass fputc nur chars schreibt (also 8bittige Werte?),> bräuchte aber wohl etwas, das mir je nach Größe der aktuell zu> schreibenden Variable einen int16, uint16, int32 oder uint32 schreibt.
Ja, richtig. Ein anderes Problem ist, daß du die Datei im Textmodus
öffnest.
Peter II schrieb:> wie kommt man nur auf fputc?
aus nem Tutorial "wie schreibe ich in eine Datei".... , danke für den
Link=)
Rolf Magnus schrieb:> Ja, richtig. Ein anderes Problem ist, daß du die Datei im Textmodus> öffnest.
wie öffne ich die Datei im "Bild"Modus?
j. t. schrieb:> Rolf Magnus schrieb:>> Ja, richtig. Ein anderes Problem ist, daß du die Datei im Textmodus>> öffnest.>> wie öffne ich die Datei im "Bild"Modus?
Nicht "Bild"-, sondern Binärmodus. Sieh Dir mal die Dokumentation von
fopen an, hier insbesondere die Bedeutung des zweiten Parameters.
Lies mal etwas zu fwrite. Und zu packed bei structs. Etwas entfernt
mandelbrotiges ist dann schon erkennbar.
Das Bild würde ich zum Testen erstmal mit Schachbrett/Streifen o.ä.
füllen. Momentan ist nämlich nicht ganz klar, ob die seltsame Optik des
Resultats beim Erzeugen oder Speichern liegt.
Und die Warnungen grundsätzlich voll aufdrehen (-Wall -Wextra etc.) und
abarbeiten.
Sowas "warning: comparison of unsigned expression >= 0 is always true"
ist z.B. ein Fehlerkandidat.
Thomas schrieb:> Momentan ist nämlich nicht ganz klar, ob die seltsame Optik des> Resultats beim Erzeugen oder Speichern liegt.
Die reine Mandelbroterzeugung an sich läuft. Die hab ich schon auf dem
STM32F429 Disco laufen lassen, aber war mit der Auflösung von 320*240
nicht wirklich zufrieden. In der Tat sieht das was du da zeigst, ein
wenig seltsam aus *gg. Aber der Rand ist definitiv schon recht
mandelbrotig, nur etwas geneigt und er ist halt auch ein paar mal zu oft
da.
Ich werd mir die links mal zu Gemüte führen, danke dafür
MfG Chaos
j. t. schrieb:> Thomas schrieb:>> Momentan ist nämlich nicht ganz klar, ob die seltsame Optik des>> Resultats beim Erzeugen oder Speichern liegt.>> Die reine Mandelbroterzeugung an sich läuft. Die hab ich schon auf dem> STM32F429 Disco laufen lassen, aber war mit der Auflösung von 320*240> nicht wirklich zufrieden. In der Tat sieht das was du da zeigst, ein> wenig seltsam aus *gg. Aber der Rand ist definitiv schon recht> mandelbrotig, nur etwas geneigt und er ist halt auch ein paar mal zu oft> da.
Heisser Tip:
Seine ersten Gehversuche macht man nicht mit Daten, die man in einer
Hex-Anzeige der Datei nicht vernünftig deuten kann.
Seine ersten Versuche macht man mit zb dem bereits genannten
Schachbrett. Denn mit einem Hex-Editor erkennt man dort dann den
Dateiaufbau wieder und kann ihn mit einem 'baugleichen' Bild, welches
ein Malprogramm erzeugt hat, vergleichen um zu sehen, wo die
Unterschiede liegen, wnn man sich das File auf Byte-Ebene ansieht.
"Die Bilddaten werden Zeile für Zeile gespeichert. Wenn biHeight positiv
ist, beginnen die Bilddaten mit der letzten und enden mit der ersten
Bildzeile, ansonsten ist es umgekehrt. Bei BI_BITFIELDS und bei BI_RGB
ist die Länge jeder Zeile ist ein Vielfaches von 4 Bytes und wird, falls
erforderlich, mit Nullbytes aufgefüllt."
Deine 1366 passen dazu nicht. MIt 1368 geht es besser.
Das komische Muster in der Mitte ist meine Initialisierung des Bildes
vor dem Mandelbrotaufruf.
Zu der Geschichte mit dem Abarbeiten der Warnungen: Was möchte mir diese
Warnung eigentlich sagen?:
warning: useless storage class specifier in empty declaration [enabled
by default]|
wenn ich das ganze mit:
typedef struct foostruct
{
}foo;
mache, dann kommt die Warnung nicht.
Die Warnung mit dem Vergleich eines uint mit null ist diesem Fall zu
ignorieren, da ich ja auch noch vergleiche, ob kleiner als 256 ist.
Ich habe das ganze nun mit fwrite versucht.
Es wird nun kompiliert und auch eine 3075kb große Datei erzeugt, aber
ich kann sie nicht öffnen....
P.S.
Ich hatte versucht die falsche Datei zu öffnen. Es lässt sich doch
öffnen, jedoch ist da noch irgendwas durcheinander geraten...
Bei fwrite dachte ich eher an sowas:
fwrite(&BMPFileHeader, sizeof BMPFileHeader, 1, MandelbrotBild1);
Damit das funktioniert, muss das struct packed sein.
>fwritePt = &Bild[xPos][yPos];>fwrite(fwritePt, sizeof(Bild[xPos][yPos]), 1, MandelbrotBild1);
Hier musst Du immer 3 Byte (R, G und B) schreiben. Das 4. Byte des
uint32_t darf nicht in die Datei. Und das "Zahl der Pixel in einer Zeile
muss durch 4 teilbar sein oder mit 0 aufgefüllt werden"-Problem scheint
auch immer noch zu existieren.
Thomas schrieb:> Hier musst Du immer 3 Byte (R, G und B) schreiben. Das 4. Byte des> uint32_t darf nicht in die Datei. Und das "Zahl der Pixel in einer Zeile> muss durch 4 teilbar sein oder mit 0 aufgefüllt werden"-Problem scheint> auch immer noch zu existieren.
Ich könnte doch auch auf 32bit-Farbmodus schalten? Dann wäre das Problem
nur drei von vier Byte aus nem uint32 zu schreiben schonmal umgangen.
Dann wäre noch zu klären ob der Alphakanal auf auf 0x00 oder 0xff stehen
muss, damit das Bild nicht transparent ist.
Thomas schrieb:> Damit das funktioniert, muss das struct packed sein.
Was heißt dass, das struct muss packed sein?
Thomas schrieb:> fwrite(&BMPFileHeader, sizeof BMPFileHeader, 1, MandelbrotBild1);
dabei ergäbe sich ja das Problem, das die Elemente des Struct ja nicht
alle die selbe Größe haben. Oder schreibt er dann einfach alle Elemente
wie sind nacheinander weg?
Thomas schrieb:> Hier musst Du immer 3 Byte (R, G und B) schreiben. Das 4. Byte des> uint32_t darf nicht in die Datei. Und das "Zahl der Pixel in einer Zeile> muss durch 4 teilbar sein oder mit 0 aufgefüllt werden"-Problem scheint> auch immer noch zu existieren.
Ich schätze mal, das kommt von von dem Byteversatz den er durch das
Schreiben von 4 Bytes für R.G.B zustande bringt.
Aber die 4 Byte Grenze pro Scanline muss er natürlich trotzdem
einhalten.
j.t. machs dir doch nicht so schwer
und gut ists.
Der void* in der Funktionsdeklaration von fwrite bedeutet nur, dass du
da jede beliebige Adresse reingeben kannst. Das fwrite also nicht
irgendwas spezielles haben will, zb einen int* oder einen long*. Jede
Adresse ist ok, egal welcher Basis-Datentyp.
Die Felder schreibt man auch nicht einzeln aufs File. Genau dazu hat man
sich ja eine struct dafür gebaut. fwrite kann alles auf ein File
schreiben. Es muss nur wissen, wo es anfängt und wie lange es ist. Gib
ihm also die Startdresse der BMPFileHeader Struct-Variablen, sag ihm wie
gross die struct ist (in Bytes, mit einem siezeof) und fwrite schreibt
die ganze Struktur, so wie sie ist, aufs File (packing ausschalten,
damit der Compiler nicht zwischen Strukturmember Füllbytes einfügt,
falls das auf deiner Maschine die Performance steiegern würde).
j. t. schrieb:> Thomas schrieb:>> fwrite(&BMPFileHeader, sizeof BMPFileHeader, 1, MandelbrotBild1);>> dabei ergäbe sich ja das Problem, das die Elemente des Struct ja nicht> alle die selbe Größe haben. Oder schreibt er dann einfach alle Elemente> wie sind nacheinander weg?
Der fwrite weiss nichts von 'Elementen'. Der hat eine Speicheradresse
und eine Angabe wieviele Bytes er beginnend mit dieser Speicheradresse
ins File buttern soll.
wenn ich statt BMPFileHeader.bfType = 19778; //ASCII Zeichenkette "BM"
BMPFileHeader.bfType = 'BM' schreibe, dann ist das Format nicht lesbar
beim öffnen. Genauso wenn ich
fwrite(&BMPFileHeader, sizeof(BMPFileHeader), 1,MandelbrotBild1);
statt
fwrite(&BMPFileHeader.bfType, sizeof(BMPFileHeader.bfType),
1,MandelbrotBild1);
fwrite(&BMPFileHeader.bfSize, sizeof(BMPFileHeader.bfSize),
1,MandelbrotBild1);
fwrite(&BMPFileHeader.bfReserved, sizeof(BMPFileHeader.bfReserved),
1,MandelbrotBild1);
fwrite(&BMPFileHeader.bfOffBits,sizeof(BMPFileHeader.bfOffBits),
1,MandelbrotBild1);
schreibe....
Ansonsten macht er mir nun ein richtiges Apfelmännchen =)
z.Zt siehts so aus:
j. t. schrieb:> wenn ich statt BMPFileHeader.bfType = 19778; //ASCII Zeichenkette "BM">> BMPFileHeader.bfType = 'BM' schreibe, dann ist das Format nicht lesbar> beim öffnen.
Mea Culpa.
Bytereihenfolge
BMPFileHeader.bfType = 'MB'
> Genauso wenn ich>> fwrite(&BMPFileHeader, sizeof(BMPFileHeader), 1,MandelbrotBild1);>> statt
Und genau jetzt schlägt dann die Stunde eines Hex-Editors, mit dem man
auf Byte-Ebene in das File reinschaut und nachsieht, welche Bytes
verkehrt rum sind, bzw. wo ein Byte zu viel oder zu wenig ist.
Denn was hier, bei diesem Beispiel mit den läppischen 2 Strukturen noch
überschaubar ist, artet bei größeren und komplexeren Datenstrukturen
dann nämlich zu einem Albtraum aus. Allerdings ist das Beispiel auch gut
geeignet, weil man hier tatsächlich dann auch mal 'unter die Tuchent'
blicken muss, wie der Compiler die Dinge im Speicher anordnet. Das fällt
also in die Kategorie: lerne dein spezifisches Werkzeug kennen.
Die 32bit lösen nebenbei das Problem, dass die Bytes in jeder Zeile
durch 4 teilbar sein müssen (ich habe vorhin fälschlicherweise von
Pixeln gesprochen).
>Genauso wenn ich>fwrite(&BMPFileHeader, sizeof(BMPFileHeader), 1,MandelbrotBild1);>statt> fwrite(&BMPFileHeader.bfType, sizeof(BMPFileHeader.bfType), ...> schreibe....
Das "packed" wurde nun schon mehrfach erwähnt. Mehr können wir nicht
tun...
mhh man sollte auch mal fertig lesen...
You may only specify this attribute on the definition of an enum, struct
or union, not on a typedef that does not also define the enumerated
type, structure or union.
Heißt das, ich soll das typedef weglassen? Oder soll ich gleich bei der
Deklaration mein BMPFileHeader mitdefinieren?
Auch wenn ich das typedef weglasse geht es nicht....
Der Unterschied im HexEditor zwischen dem lesbaren Bild und dem
nichtlesbaren sind lediglich 4 Nullen. Das funktionierende geht mit:
424D000210000000 los, und das nicht funktionierende mit:
424D000000021000. Also schiebt er wohl irgendwie ein uint32 der 0 ist
ein wenn ich die Version wähle, das er das struct in einem Aufwasch
schreibt.
Die alten C-Experten bestehen mit religiösem Eifer auf Variante 2. Ich
bin schreibfaul und werde sowieso nie am Linux-Kernel oder anderen
großen C-Projekten (igitt) mitwirken und mag Variante 1.
Also wenn mich nicht alles täuscht, müsste ich hier nun Variante 1
umgesetzt haben.... aber es geht nicht. Lass ich das ganze struct
schreiben, ist die Datei nicht lesbar, lass ich alle einzeln schreiben,
geht es.
Hier nochmal der ganze Code. Evtl kannst du den ja nochmal kompilieren
und schauen was bei dir passiert. Oder mir sagen, ob ich irgendwo noch
nen doofen Fehler versteckt hab.
Die anderen Mandelbrot-Parameter haben mich zuerst etwas verwirrt ;)
bfSize und biSizeImage sehen noch falsch aus (darin stehen Bytes, nicht
Pixel), sind hier aber wohl nicht das Problem.
Der Anhang (dein Code bei mir lauffähig gemacht) liefert mit und ohne
das USE_PACKED eine byteweise identische BMP-Datei, so wie es zu
erwarten sein sollte.
Jetzt müssen wir wohl auf die Experten warten. Welchen GCC und welches
OS benutzt Du?
Ich benutze win8.1 und den mingw32-gcc-4.7.1.
An bfSize und biSizeImage gehört jeweils noch ein mal4, dann stimmen die
auch. Aber ansonsten macht er jetzt ja richtige Bilder, wenn man halt
von den vier Nullen im Hexfile absieht, wenn ich die verschieden Wege
nehme, den Header zu schreiben.
Ich werd mich nun aber erstmal hinlegen, ich wünsch ne gute Nacht =)
MfG Chaos
j. t. schrieb:> Zu der Geschichte mit dem Abarbeiten der Warnungen: Was möchte mir diese> Warnung eigentlich sagen?:> warning: useless storage class specifier in empty declaration [enabled> by default]|
Dazu wäre die Zeile interessant, auf die sich diese Warnung bezieht.
Das taucht beim deklarieren der structs auf. Bei:
typedef struct bla
{
};
mit typedef struct
{
}bla;
tauchts nicht auf, und inzwischen hab ich auch verstanden wieso, aber
was die Fehlermeldung nun exakt bedeutet ist mir dennoch nicht 100%ig
klar.
Das was am Ende rauskommt, ist vom Ergebnis her zumindest das selbe,
wenn man von der Fehlermeldung absieht
j. t. schrieb:> typedef struct bla> {>> };
Tja, was nutzt ein typedef, wenn da keine Name vergeben wird:
Der syntx ist (vereinfacht):
1
typedef<type><name>;
Dein <type> ist hier 'struct bla { ... }', und die <name> ist leer.
Deswegen meckert der Compiler, dass das alles nix nutzt.
> typedef struct> {>> }bla;
Hier ist <type> 'struct { ... }' und die <name> ist 'bla'.
Das ist also eine gültige und sinnvolle typedef.
> Das was am Ende rauskommt, ist vom Ergebnis her zumindest das selbe,> wenn man von der Fehlermeldung absieht
Nein. Im ersten fall hast du ein struct definiert, aber kein typedef
name dazu. Deswegen meckert der Compiler auch.
Nochmal zurück zum Schreiben des Headers. Ich hab immer noch das
Problem, das ich die Elemente des/der Headers einzeln in die Datei
schreiben muss.
Thomas hat eine Lösung mit defines und ifdefs vorgeschlagen, um zwischen
beiden Varianten umzuschalten, wenn ich seine Version in der das
Headerstruct als ganzes in die Datei geschrieben wird kompiliere, lässt
sich die Datei nicht öffnen, das Hex geht folgendermaßen los:
1) 424D0000B6A10000000000003600000028000000880000004C00000001002000
2) 424D05BFB6A10000000000003600000028000000880000004C00000001002000
3) 424DB6A10000000000003600000028000000880000004C000000010020000000
wobei
1) Thomas Version, per defines in den "Struct in einem Aufwasch"-Modus
gesetzt. Wie man sieht kommen nach 2 richtigen Byte 2 falsche 0Byte,
danach gehts richtig weiter.
2) Meine Version, per auskommentieren in den "Struct in einem
Aufwasch"-Modus gesetzt. Hier werden fälschlich ein Byte 05 und ein Byte
BF an der selben Stelle wie bei 1) eingesetzt. Wo kommen die her?
3) Meine Version, per auskommentieren in den "Alle Structelemente
einzeln ins BMP schreiben"-Modus gesetzt. Hierbei entsteht ein
Bitmapfile, das sich öffnen und betrachten lässt. Einziger Unterschied
sind die beiden erwähnten Bytes. Eine Zeit lang hatte ich auch in meiner
"Struct aufeinmal Version" die Nullbytes statt der 05BF aber ich weiß
nicht mehr, was ich da anders gemacht hatte. Wenn ich in den beiden
fehlerhaften Versionen jeweils die falschen Bytes rauschlösche, bekomme
wie zu erwarten das selbe Bild wie bei der richtigen Version.
Der Unterschied ziwschen den Versionen liegt eigentlich nur darin was
fwrite() übergeben wird.
einmal per:
zusätzlich ist der Unterschied zwischen meinen und Thomas Version, das
er die Auswahl ob einzeln oder in einem Aufwasch geschrieben wird, per
ifdefs trifft.
P.S.
.bmp-Dateien lassen sich wohl nicht anhängen, daher nur ne png von der
funktionierenden Version. Wie gesagt, der Unterschied sind ja lediglich
2Byte
von Deinem Compiler hier nicht berücksichtigt wird.
Die unterschiedlichen Werte in Byte 2 und 3 kommen daher, dass die
Strukturen auf dem Stack liegen und dementsprechend nicht initialisiert
werden. In den Lücken stehen also "zufällige" Daten.
Probier mal, dem struct einen Namen zu geben:
Hans schrieb:> Sieht so aus, als ob das _attribute_ ((_packed_)) von Deinem> Compiler hier nicht berücksichtigt wird.
Welcher Compiler ist das denn?
Sollte es beispielsweise was von Microsoft sein, dann ist stattdessen
#pragma pack(1)
zu verwenden
Rufus Τ. Firefly schrieb:> Welcher Compiler ist das denn?>> Sollte es beispielsweise was von Microsoft sein, dann ist stattdessen> #pragma pack(1)> zu verwenden
besser wäre die Klammerung mit:
1
#pragma pack(push,1)
2
...
3
#pragma pack(pop)
weiter oben stand aber etwas von:
> win8.1 und den mingw32-gcc-4.7.1
genau win 8.1 mingw32-gcc4.7.1., das ganze übrigens in Code::Blocks. Ich
glaub das baut wiederum auf winzigweich visual studio auf?!?
Hans schrieb:> Probier mal, dem struct einen Namen zu geben:typedef struct> _attribute_ ((_packed_)) BMPFileHeaderStruct_s> {> uint16_t bfType;//> uint32_t bfSize;//> uint32_t bfReserved;//> uint32_t bfOffBits;// = 54; //Offsetbytes> }BMPFileHeaderStruct;
Das werd ich direkt mal testen.
Hans schrieb:> Die unterschiedlichen Werte in Byte 2 und 3 kommen daher, dass die> Strukturen auf dem Stack liegen und dementsprechend nicht initialisiert> werden. In den Lücken stehen also "zufällige" Daten.
Aber ich fülle die Strukturen doch komplett aus, bevor ich sie in die
Datei schreibe? Da dürfte doch nichts zufälliges stehen?
Nebenbei eine Frage evtl etwas offtopic.
Ich zähle in einer Variablen n die Anzahl der Iterationen für jedes
Pixel, und je nach Iterationszahl wird eine Farbe zwischen 0-1536
zugewiesen.
Da der Anstieg der Iterationszahl aber recht exponentiell in einige
Richtungen zu gehen scheint, ergibt sich immer das Bild, das entweder
die Farben ewig lange rot bleiben, um dann am Rand aber halt erst recht
dicht dran, recht detailiert zu werden. Wenn ich nun einfach einen
Multiplikator einfüge, habe ich schon von Anfang an eine (wenn auch
recht sprunghafte) Farbändderungen, und zum Rand bleiben keine Farben
mehr übrig.
Ich brauche nun also eine Funktion, die die Iterationszahl auf 1
normiert a la nMax/n und auf meinen Farbraum abbildet. Also irgendwas in
der Richtungen
nMax/n * 1536(Farbmax).
Dabei besteht aber immernoch das problem der Exponentialität. Also muss
sich irgendwie noch was logarithmisches in meine Funktion einschleichen,
damit ich sowohl weit weg von den Rändern, als auch dicht dran schöne
Farbänderungen habe. Aber irgendwie steh ich da grad aufm Schlauch
j. t. schrieb:> Hans schrieb:>> Probier mal, dem struct einen Namen zu geben:typedef struct>> attribute ((packed)) BMPFileHeaderStruct_s>> {>> uint16_t bfType;//>> uint32_t bfSize;//>> uint32_t bfReserved;//>> uint32_t bfOffBits;// = 54; //Offsetbytes>> }BMPFileHeaderStruct;>> Das werd ich direkt mal testen.
Mh auch das klappt nicht....
Habs mal bei mir probiert. Sieht nach diesem Compilerbug aus:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991
Du musst unter Project -> Build Options -> Compiler Settings -> Other
Settings folgendes einfügen:
Hans schrieb:> Du musst unter Project -> Build Options -> Compiler Settings -> Other> Settings folgendes einfügen:-mno-ms-bitfields
Das hat das Problem gelöst! Danke dafür =)
Für die andere Frage lieber n neuen Thread öffnen?(von 20:14)
j. t. schrieb:> MoinMoin,> ich versuche gerade Daten aus einem Array in eine Bitmap zu schreiben.> Dazu hab ich mir rausgesucht, wie so eine Bitmap aufgebaut ist, habe
Man muß sich das Leben ja net unnötig schwer machen Wie wär's mit einem
simpleren Format wie z.B. PPM? Das Format ist Text und ohne jedes
Tralala, siehe
http://de.wikipedia.org/wiki/Portable_Anymap#Pixmap
Das wird dann bequem in (fast) jedes x-beliebige Rasterformat gewandelt,
das man idR nicht händisch beackern will: PNG, GIF, JPG, PDF, TIFF, BMP,
...
Als Tool dazu verwende ich gerne convert von ImageMagick
http://imagemagick.com/script/convert.php
als Programm, als C-Bibliothek, als C++-Bibliothek, als PHP, als Tcl,
weiß der Teufel... damit lassen sich Einzelbilder auch schmerzfrei zu
Animationan zusammenbasteln, hier z.B. für Julia-Mangen für z²+c, deren
Parameter c sich auf einem Halbkreis durch die Mandelbrotmenge bewegt:
http://commons.wikimedia.org/wiki/File:Julia-Set_z2%2Bc_ani.gif> #include <stdint-gcc.h>
Wo hast du den Header denn ausgebuddelt?! Der wird von GCC intern
verwendet; in dein Programm gehört #include <stdint.h>
Danke für die Links, die werd ich mir mal anschauen.
Johann L. schrieb:> Wo hast du den Header denn ausgebuddelt?! Der wird von GCC intern> verwendet; in dein Programm gehört #include <stdint.h>
Den hab ich irgendwo in den Optionen von Codeblocks entdeckt....
Ich hatte mich gewundert, das er die ganzen uintX_t nicht kennt und
wusste spontan nicht mehr, wo die drin stehen *gg
Johann L. schrieb:> als Programm, als C-Bibliothek, als C++-Bibliothek, als PHP, als Tcl,> weiß der Teufel... damit lassen sich Einzelbilder auch schmerzfrei zu> Animationan zusammenbasteln, hier z.B. für Julia-Mangen für z²+c, deren> Parameter c sich auf einem Halbkreis durch die Mandelbrotmenge bewegt:
das wäre der nächste angedachte Schritt gewesen =)
Ein weiterer mysteriöser "Fehler" taucht auf. Ich hab inzwischen ein
wenig weiterprogrammiert, und lasse nun mehrere Bilder in einem
Durchlauf berechnen.
Dazu lasse ich mit einer while-Schleife die Bilderzeugung x mal
durclaufen. Das klappt soweit auch wunderbar.
Nach dem Motto:
while (n < 10)
{
MachNBild();
n++;
}
Es werden mir 10 bmps erzeugt. Und jedes einzelne davon ist direkt
nachdem es errechnet wurde verfügbar(Ich stelle gerade fest, das sie
sich doch erst öffnen lassen, nachdem das Programm zu Ende gelaufen ist,
das ist doch schonmal ein Hinweis).
Wenn ich nun aber:
while (1)
{
MachNBild();
}
erstellt mir zwar jede Menge Dateien, bis ich das Programm abbreche,
jedoch sind das keine bmps mehr, sondern endungslose Dateien. Diese
lassen sich natürlich auch nicht öffnen.
Wodran könnte das liegen?
das öffnen der Datei, das Schreiben und das Schließen laufen alle in
Unterfunktionen ab, sollten doch eigentlich garnicht davon beeinflusst
sein, ob sie nun mit einer unendlichen whileschleife aufgerufen werden,
oder ob sie nur eine bestimmte Anzahl oft aufgerufen werden?
Im Anhang nochmal der aktuelle Code.
MfG Chaos
P.S.
Falls in dem Code noch #include <stdint-gcc.h> stehen sollte, das ist
inzwischen auf #include <stdint.h> geändert. Seit dem sind es immerhin
keine Endungslosen Dateien, lassen sich aber dennoch nicht öffnen.
noch etwas, wenn ich mehr als 36 Bilder "auf einmal" berechnen lassen
will, stürzt das Programm nach dem 36ten Bild ab. Dies geschieht
unabhängig von der gewählten Auflösung, also denke ich nicht, das ihm
der Speicher ausgeht.
Die dann erzeugten Bilddateien sind ebenfalls nicht zu öffnen...
direkt nochmal den Hexeditor benutzen.
P.S.
Laut hexeditor ist kein Unterschied zwischen den Beiden. Und das obwohl
die nicht zu öffnende ein bischen kleiner ist. Aber das liegt wohl
daran, dass das Programm mitten drin abstürzt, und bis zum Ende des
kürzeren keine Unterschiede vorliegen?
Guck' mal deinen fclose()-Aufruf an. Der ist verkehrt. Wahrscheinlich
stürzt dein Programm deswegen ab (weil ihm die Filehandles ausgehen).
Deswegen auch immer den Return-Wert von fopen() abprüfen!
Eigentlich sollte dein Compiler dafür mindestens eine Warnung
ausspucken (die Du natürlich ernst nehmen und abstellen solltest).
Tut er das nicht, solltest Du dringend rausfinden, wie Du ihn dazu
bringst. Compiler sind nämlich - per Definition - immer schlauer als der
Programmierer ;).
j. t. schrieb:> noch etwas, wenn ich mehr als 36 Bilder "auf einmal" berechnen lassen
Was soll das heißen, "auf einmal"?
> will, stürzt das Programm nach dem 36ten Bild ab.
Überprüf mal ob von fwrite so viele Einheiten geschrieben wurden (der
return-Wert) wie erwartet.
Außerdem schreibst du fleißig in das von fopen gelieferte FILE* auch
wenn dieser NULL ist! Und wieviele Dateien darfst du maximal
gleichzeitig offen haben?
Noch ein paar Anmerkungen zum Programm selbst:
C99 unterstützt von Hause aus komplexe Zahlen. Du brauchst also nicht
händisch mit Real- und Imaginärteil rumfrickeln sondern einfach
Eine BMP Datei beginnt nicht mit einem 16-Bit Wert wie uint16 sondern
mit einem Array char bm[2] mit bm[0] = 'B' und bm[1] = 'M'! Ansonsten
bekommst du Probleme mit Endianess. Allerdings gelten die
Endianess-Probleme auch für alle anderen Felder, d.h. du bist offenbar
aif eine Endian=Little Maschine, ansonsten käm für die BMPs nur Müll
raus.
Anstatt der umständlichen
1
x=0;while(x<baba){lala;x++;}
ist besser lesbar
1
for(x=0;x<baba;x++){lala;}
2
// oder
3
for(intx=0;x<baba;x++){lala;}
Das Äußere von M bekommst du ansprechender wenn du nicht |z| > 2
testest sondern z.B. |z| > 100.
|z| > 2 ist zwar eine hinreuchendende Bedingung dafür, dass der Startpunkt der
Iteration nicht in M liegt, aber je größer der Schwellwert, desto mehr gleichen
sich die Zwiebelschalen außerhalb von M den Äquipotentiallinien einer elektrisch
geladenen Mandelbrotmenge an
Hier ein Bild wo ganz offenbar |z| > 2 verwendet wurde:
http://commons.wikimedia.org/wiki/File:Mandelbrot_High_Resolution.png
und hier eins mit |z| > k >> 2:
http://commons.wikimedia.org/wiki/File:Mandelbrot_set_with_coloured_environment.png
Der Mehraufwand an Rechenzeit ist unerheblich: Wenn |z| > 2 dann ist es
bereits nach 3 weiteren Iterationen > 256.
Johann L. schrieb:> Was soll das heißen, "auf einmal"?
Das soll heißen, das mit einmal kompilieren, einfach mehrmals
nacheinander mit neuem Zoomfaktor die Berechnung des Mandelbrots
vorgenommen wird. Ursprünglich hab ich für jedes einzelne Bild im
Quelltext den Wert angepasst, und für jedes Bild dann neu kompiliert.
Nun werden die Werte halt in einer Schleife mehrmals berechnet. Also auf
einmal im Sinne von "mit einem Start der exe" nicht, das die
gleichzeitig und parallel berechnet werden.
Johann L. schrieb:> Überprüf mal ob von fwrite so viele Einheiten geschrieben wurden (der> return-Wert) wie erwartet.
Ich hab doch immer nur eine Einheit von fwrite offen?
Ich rufen ein einer Schleife auf
for (n = 0; n < 10; n++)
{
Bildmachen();
]
Bildmachen()
{
fopen(bla)
...
fclose(bla)
}
Johann L. schrieb:> Außerdem schreibst du fleißig in das von fopen gelieferte FILE* auch> wenn dieser NULL ist! Und wieviele Dateien darfst du maximal> gleichzeitig offen haben?
Das heißt?
Johann L. schrieb:> C99 unterstützt von Hause aus komplexe Zahlen. Du brauchst also nicht> händisch mit Real- und Imaginärteil rumfrickeln sondern einfach
Das werd ich mir mal anschauen, danke dafür
Johann L. schrieb:> Das Äußere von M bekommst du ansprechender wenn du nicht |z| > 2> testest sondern z.B. |z| > 100.>> |z| > 2 ist zwar eine hinreuchendende Bedingung dafür, dass der Startpunkt der> Iteration nicht in M liegt, aber je größer der Schwellwert, desto mehr> gleichen> sich die Zwiebelschalen außerhalb von M den Äquipotentiallinien einer> elektrisch> geladenen Mandelbrotmenge an
Der Unterschied bei den Abbruchbedingungen macht den Kohl hier nicht
sehr fett. Da wie du ganz richtig sagst, falls |z| > 2 schon nach nur 3
Schritten > 256 ist, bekomme ich ja grundsätzlich bei einem höheren Wert
(bspw 256) ja lediglich nur 3 Iterationsschritte mehr. Viel wichtiger
für die Darstellung ist, sauber mitzuzählen, wieviele Iterationen bis
zum erreichen der Abbruchbedingung notwendig waren, und danach die Farbe
zuzuordnen. (Irgendein mathematischer Satz besagt, wenn solch eine
Iterationsfolge 2 überschreitet, konvergiert sie ziemlich sicher und
ziemlich schnell gegen unendlich) Anbei mal 2 Bilder des gleichen
Ausschnittes, einmal mit Abbruchbedingung |z| >= 2 und einmal mit 256.
Weiter oben sind auch noch 2 Beispiele, die zeigen welch starke
Veränderung sich ergibt, wenn man an der Farbzuordnung rumspielt.
Markus F. schrieb:> Eigentlich sollte dein Compiler dafür mindestens eine Warnung> ausspucken (die Du natürlich ernst nehmen und abstellen solltest).
Spuckt er auch....:
warning: passing argument 1 of 'fclose' from incompatible pointer type
[enabled by default]
Aber ich verstehe nicht so ganz, was da schief läuft.
Ich öffne mit
Mandelbrotbild = fopen(Dateiname, wb)
und schließe mit
fclose(Dateiname).
Als ich das ohne Pointer gelöst hatte, und den Namen direkt angegeben
hatte, hat das auch ohne Warnung geklappt..
Danke euch erstmal für die Antworten,
MfG Chaos
j. t. schrieb:> Markus F. schrieb:>> Eigentlich sollte dein Compiler dafür mindestens eine Warnung>> ausspucken (die Du natürlich ernst nehmen und abstellen solltest).>> Spuckt er auch....:> warning: passing argument 1 of 'fclose' from incompatible pointer type> [enabled by default]> Aber ich verstehe nicht so ganz, was da schief läuft.> Ich öffne mit> Mandelbrotbild = fopen(Dateiname, wb)> und schließe mit> fclose(Dateiname).
... und das ist sehr verkehrt. Muß heißen:
1
Mandelbrotbild=fopen(Dateiname,wb);
2
if(Mandelbrotbild)
3
{
4
...
5
fclose(Mandelbrotbild);/* fclose() erwartet einen FILE pointer, keinen Dateinamen */
AAAchsoooo. Ich bin davon ausgegangen, das man natürlich exakt das
schließen muss, was man vorher geöffnet hat.
Nun funktioniert es!!!!! =) Ich kann jetzt beliebig viele Bilder
erzeugen. Selbst wenn ich es auf while (1) setze, erzeugt mir Bilder
ohne Ende, und ich kann sie sogar öffnen, während er die nächsten
berechnet. Ganz so wie ich es mir vorgestellt hab.
Ganz herzlichen Dank für deine Hilfe,
MfG Chaos
j. t. schrieb:> Ich bin davon ausgegangen,
Hört sich vielleicht jetzt blöd an: das ist beim Programmieren so
ungefähr die Totsünde #1!
Egal, ob man einfache Apfelmännchen oder ein komplexes ERP-System
programmiert, Annahmen rächen sich immer. Im besten Fall sofort (so
wie bei dir), im schlechten erst beim Nutzer und im schlechtesten nur
sporadisch.
Man darf schlicht von nichts ausgehen, sondern muß wissen. Wenn man
nicht weiß, muß man nachgucken.
Besser, man akzeptiert das so früh wie möglich.
j. t. schrieb:> Johann L. schrieb:>> Das Äußere von M bekommst du ansprechender wenn du nicht>> |z| > 2 testest sondern z.B. |z| > 100.>>>> |z| > 2 ist zwar eine hinreichende Bedingung dafür, dass der>> Startpunkt der Iteration nicht in M liegt, aber je größer>> der Schwellwert, desto mehr gleichen sich die Zwiebelschalen>> außerhalb von M den Äquipotentiallinien einer elektrisch>> geladenen Mandelbrotmenge an.>> Der Unterschied bei den Abbruchbedingungen macht den Kohl hier nicht> sehr fett. Da wie du ganz richtig sagst, falls |z| > 2 schon nach nur 3> Schritten > 256 ist, bekomme ich ja grundsätzlich bei einem höheren Wert> (bspw 256) ja lediglich nur 3 Iterationsschritte mehr.
Nicht ganz; denn die Iteration ist nicht z→z² sondern z→z²+c.
> Anbei mal 2 Bilder des gleichen Ausschnittes, einmal mit> Abbruchbedingung |z| >= 2 und einmal mit 256.
Ok, bei der roten Farbsoße wird man natürlich niemals nicht irgendeinen
Unterschied sehen...
Du verstehst scheinbar nicht, das es nicht darum geht, denn Betrag von Z
möglichst groß werden zu lassen, sondern zu zählen, wie oft die
Iteration durchläuft, bis der Betrag von Z die Abbruchbedingung, nämlich
größer als 2 zu sein, erreicht.
Eigentlich müsste man die Iteration unendlich oft durchlaufen lassen,
damit sicher entschieden wird, ob der Punkt zur Mandelbrotmenge gehört
oder nicht, denn das ist schließlich die Definition der Mandelbrotmenge.
Alle Punkte deren Iteration nicht gegen unendlich strebt, gehören zu
ihr.
(wobei die Iterationsvorschrift: Zn = Zn-1² + c. Und c ist die
Koordinate des betrachteten Pixels)
Sobald der Iterationswert größer als 2 wird, strebt er mit sehr hoher
Wahrscheinlichkeit gegen unendlich. (ich prüfe hier nur, ob das Quadrat
des Betrages größer als 4 ist, um mir das Wurzelziehen zu sparen was
aufs selbe hinauskommt).
Die Zahl der Iterationsschritte bis hierher bestimmt die Färbung des
Punktes.
Sollte der Punkt nicht gegen unendlich streben, müsstest du ja in der
Theorie unendlich oft iterieren. Da hierfür dem Durchschnittsanwender
die Zeit fehlt, geht man den Kompromiss ein, nach einer bestimmten
Anzahl von Iterationen abzubrechen und diesen Punkt dann als zur
Mandelbrotmenge zugehörig anzunehmen.
Was also viel größeren Einfluss auf die Genauigkeit hat, ist die Anzahl
der Iterationen bis zum Abbruch. Und dann noch die Zuordnung, bei
welchem Iterationsschritt welche Farbe gewählt wird.
Viel interessanter ist auch der Randbreich, statt der ganzen Menge. (Die
Zahl der Iterationenn bis zum Abbruch bleibt lange gering, bis man sich
der eigentlich Mandelbrotmenge nähert).
Anbei mal der gleiche Ausschnitt in unterschiedlichen drei
unterschiedlichen Farbzuordnungen.
Die Farben sind einfach:
farbe1 r=255, g=0, b=0
farbe2 r=255, g=1, b=0
farbe256 r=255, g=255, b=0
farbe257 r=254, g=255, b=0
farbe512 r=0, g= 255, b=0
farbe513 r=0, g= 255, b=1
farbe768 r=0, g= 255, b=255
farbe769 r=0, g= 254, b=255
farbe1024 r=0, g= 0, b=255
farbe1025 r=1, g= 0, b=255
farbe1280 r=255, g=0, b=255
farbe1281 r=255, g=0, b=254
FarbeLinearMal2 ist die Anzahl der Iterationsschritte*2=Farbe
FarbeLog ist der Logarithmus der Anzahl Iterationsschritte so
multipliziert, das er beim Maximum der Iterationsschritte das Maximum
der Farbtabelle trifft.
FarbeLogmal2, das selbe, nur mit 2 multipliziert.
P.S.
Ich könnte ich auch Bilder in 27320*15360 zeigen, aber das Datenvolumen
wollte ich euch nicht antun)
Johann L. schrieb:> Ok, bei der roten Farbsoße wird man natürlich niemals nicht irgendeinen> Unterschied sehen...
Aber es sind genug Details vorhanden, die in beiden Bildern gleich sind,
womit hinreichend bewiesen ist, vor allem mit den Bildern in denen die
Farbzuordnung unterschiedlch ist, das die Höhe von Z (|Z|) bei der
abgebrochen wird, kaum Einfluss auf das Ergebnis hat.
Wie mache ich, dass der Tippex streifen auf dem Bildschirm sich
mitbewegt, wenn ich scrole? :-D
Wobei das nicht davon abhängt, ob man mit unendlich |Z| meint, oder die
Zahl der Iterationsschritte.
j. t. schrieb:> Wobei das nicht davon abhängt, ob man mit unendlich |Z| meint, oder die> Zahl der Iterationsschritte.
Hier sollte das "nicht" in Anführungszeichen geschrieben werden ...
Wobei die Unendlichkeit nur bei der Anzahl der Iterationsschritte ein
Kriterium ist, bei der Betrachtung von |z| reicht 2, was doch
geringfügig kleiner ist als Unendlich.
Rufus Τ. Firefly schrieb:> bei der Betrachtung von |z| reicht 2, was doch> geringfügig kleiner ist als Unendlich.
Was ich Johann L zu erklären versuchte *gg
j. t. schrieb:> Johann L. schrieb:>> Ok, bei der roten Farbsoße wird man natürlich niemals nicht irgendeinen>> Unterschied sehen...>> Aber es sind genug Details vorhanden, die in beiden Bildern gleich sind,
Anbei zwei Bilder, links mit 2 und rechts mit 100 als Abbruchkriterium
für |z|.
> womit hinreichend bewiesen ist,
Soviel zu "bewiesen" und "beweisen".
j. t. schrieb:> Du verstehst scheinbar nicht, das es nicht darum geht,> denn Betrag von Z möglichst groß werden zu lassen, sondern zu> zählen, wie oft die Iteration durchläuft, bis der Betrag von> Z die Abbruchbedingung, nämlich größer als 2 zu sein, erreicht.
Du verstehst nicht, daß es (hier) nicht darum geht, M einzufärben,
sondern das Komplement von M. Und da hängt der Verlauf der
Farbgrenzen sehr wohl mit der Schranke für |z| zusammen! Abermals die
beiden Bildchen anschauen.
> Eigentlich müsste man die Iteration unendlich oft durchlaufen> lassen, damit sicher entschieden wird, ob der Punkt zur> Mandelbrotmenge gehört oder nicht, denn das ist schließlich> die Definition der Mandelbrotmenge.
Naja, das ergibt sich aus der Definition und ist praktisch für Leute,
die bunte Bildchen machen wollen.
> Sobald der Iterationswert größer als 2 wird, strebt er mit> sehr hoher Wahrscheinlichkeit gegen unendlich.
Dann konvergiert er immer gegen Unendlich.
Und damit du siehtst daß die Bilder nicht getürkt sind, hier noch das
Programm
Johann L. schrieb:> Anbei zwei Bilder, links mit 2 und rechts mit 100 als Abbruchkriterium> für |z|.
Wobei auch da die Unterschiede zwar wahrnehmbar, aber auch nicht gerade
eklatant sind.
Johann L. schrieb:> Du verstehst nicht, daß es (hier) nicht darum geht, M einzufärben,> sondern das Komplement von M. Und da hängt der Verlauf der> Farbgrenzen sehr wohl mit der Schranke für |z| zusammen! Abermals die> beiden Bildchen anschauen.
Doch das verstehe ich sehr wohl, was dir auffallen müsste, wenn du meine
Bilder ansiehst, da in denen das Apfelmännchen schwarz und der Rand
gefärbt ist(also nur der Nichtmandelbrotteil oder halt das Komplement).
Und da der interessante Bereich von C zwischen -1 und 2 im Realteil und
-1 und 1 im Imaginärteil liegt, verschiebt das Z bzw |Z| auch nur um
diesen Bereich. Evtl bringst du die Schranke von Z mit der Anzahl der
Iterationen durcheinander? Deinen Code verstehe ich auf die schnelle
ehrlich gesagt nicht. Zumindest hat bei mir, bei welcher Farbzuordnung
auch immer, die Höhe von z nur einen sehr geringen Einfluss auf das
Ergebnis, sehr wohl aber die Höhe der Iterationen, ab der abgebrochen
wird.
Johann L. schrieb:>> Eigentlich müsste man die Iteration unendlich oft durchlaufen>> lassen, damit sicher entschieden wird, ob der Punkt zur>> Mandelbrotmenge gehört oder nicht, denn das ist schließlich>> die Definition der Mandelbrotmenge.>> Naja, das ergibt sich aus der Definition und ist praktisch für Leute,> die bunte Bildchen machen wollen.
Und was willst du damit jetzt sagen? Ich "nenne" die Definition, und du
sagst, das ergibt sich aus der Definition? Was genau ergibt sich aus der
Definition? Das es praktisch für Leute ist, die bunte Bildchen machen
wollen?
Die sollten eben noch mir ran, aber irgendwie wollte er keine Bilder
hochladen. Diesmal ein Ausschnitt, auf dem deutlich mehr Strukturen zu
sehen sind, an denen man Unterschiede wahrnehmen sollte, würde Z einen
so großen Einfluss haben.
j. t. schrieb:> Johann L. schrieb:>> Anbei zwei Bilder, links mit 2 und rechts mit 100 als Abbruchkriterium>> für |z|.>> Wobei auch da die Unterschiede zwar wahrnehmbar, aber auch nicht gerade> eklatant sind.
Von eklatant hab ich auch nix geschrieben.
Je größer die Schranke für |z| ist, desto besser passen sich die Linien
außerhalb von M den Äquipotentiallinien an; das hab ich oben geschrieben
und ich versteh nicht, was für ein Problem du damit hast. Dass diese
Linien je nach Farbwahl nicht zu erkennen sind ist doch eine
Trivialität.
> Evtl bringst du die Schranke von Z mit der Anzahl der Iterationen> durcheinander?
Keine Angst, ich bring da nix durcheinander:
Die Anzahl der Linien, bzw. wie gut man (das Äußere von) M approximiert,
hängt ab von der Iterationsschranke -- mal abgesehen von Einschränkungen
durch Rechengenauigkeit, die je nach Wahl des Ausschnitts zum tragen
kommen. Je größer die Iterationsschranke, desto mehr Linien bzw.
Farbbänder bekommt man: pro Iterationsschritt mehr ein Farbband mehr.
Auf die Form der Linien bzw. Farbbänder hat das keinen Einfluß.
Die Schranke für |z| hat hingegen Einfluß auf dir Form der Banden. Es
gibt zwar auch einen kleinen Einfluß auf die Anzahl der Iterationen bis
zum Abbruchkriterium durch die Iterationsschranke, aber diese ist
vernachlässigbar da er nur mit log|z| zu Buche schlägt.
> Johann L. schrieb:>> Naja, das ergibt sich aus der Definition und ist praktisch für Leute,>> die bunte Bildchen machen wollen.>> Und was willst du damit jetzt sagen? Ich "nenne" die Definition,> und du sagst, das ergibt sich aus der Definition? Was genau ergibt> sich aus der Definition? Das es praktisch für Leute ist,> die bunte Bildchen machen wollen?
Es gibt natürlich mehrere Möglichkeiten um M zu definieren. Obwohl
diese Definitionen die gleiche Menge liefern ist der mathematische
Gehalt durchaus unterschiedlich.
Hast du dich z.B. schon mal gefragt warum man die verwendete Iteration
mit Startwert 0 beginnt und nicht mit irgendeinem anderen Wert? Warum
nicht mit 1 oder -1 oder i oder Pi? Und warum verwendet man z -> z²+c
als Iterationsvorschrift und nicht z->z²+cz oder z->sin(z)+c? Und wo
kommt die Schranke 2 her? Warum verwendet man ausgerechnet 2 und nicht
1.5?
Klar, mit 1.5 als Schranke für |z| bekommt man eine andere Menge; aber
warum zum Teufel fahren alle ab auf einen Wert >= 2 und keiner macht
tolle Bilder für |z| >= 1.5 oder schreibt ganze Bücher darüber?
Johann L. schrieb:> Je größer die Schranke für |z| ist, desto besser passen sich die Linien> außerhalb von M den Äquipotentiallinien an; das hab ich oben geschrieben> und ich versteh nicht, was für ein Problem du damit hast.
Das Problem das ich damit "hab" (eigentlich tangiert mich das ganze
recht peripher), das es in deinen ersten Ausführungen so klang, als wäre
die |Z| das Hauptkriterium, von dem das Aussehen des Mandelbrotes
abhängt, und das ist nunmal definitiv nicht der Fall.
So hängt das sichtbarwerden der "Äquipotentiallinien" hauptsächlich von
der Farbzuordnung ab. Denn wenn du jedem Iterationsschritt eine nur ganz
leicht unterschiedliche Farbe zuordnest, gehen sie natürlich in meinen
roten Farbmasch unter.
Johann L. schrieb:> Die Anzahl der Linien, bzw. wie gut man (das Äußere von) M approximiert,> hängt ab von der Iterationsschranke -- mal abgesehen von Einschränkungen> durch Rechengenauigkeit, die je nach Wahl des Ausschnitts zum tragen> kommen. Je größer die Iterationsschranke, desto mehr Linien bzw.> Farbbänder bekommt man: pro Iterationsschritt mehr ein Farbband mehr.> Auf die Form der Linien bzw. Farbbänder hat das keinen Einfluß.>> Die Schranke für |z| hat hingegen Einfluß auf dir Form der Banden. Es> gibt zwar auch einen kleinen Einfluß auf die Anzahl der Iterationen bis> zum Abbruchkriterium durch die Iterationsschranke, aber diese ist> vernachlässigbar da er nur mit log|z| zu Buche schlägt.
FACK
Darauf kann ich mich ohne Bauchschmerzen einlassen =) Anbei nochmal
2Bilder des gleichen Ausschnittes, die das von dir gesagt deutlich
zeigen.
(Die Farbzuordnung ist bei beiden die selbe, aber
gestreckt(Iterationsschrittzahl * 30(mit der weiter oben genannten
Farbtabelle)))
Mit der linearen Farbzuordnung (Farbe = Iterationsschrittzahl) kommt
übrigens der rote Mischmasch vom Anfang raus.
MfG Chaos