Ich habe leider im Forum dazu nichts gefunden.
Ich schreibe gerade einen IFF Konverter. Bei dem sind eh nach Aktion die aufgeführt wird Button aktiv oder inaktiv. Das klappe sehr gut.
Mein Problem ist aber, es gibt auch einen Dark Mod. In dem Modus passen sich aber die inaktiven Button leider nicht an. Die bleiben auf ihre Grau. Das Problem ist halt das diese Grau für den Dark Mod zu hell ist.
Ich wäre schon glücklich wenn man die Hintergrundfarbe in eine neutralere Farbe bringen kann, die einigermaßen für bei Mod passt.
Nur habe ich dazu zu wenig Erfahrung wie man so was machen könnte, hat bitte wer für mich ein paar Tipps, oder Code Beispiel?
Sorry habe das mit der Auflösung ünersehen.
Erzeugt habe ich die Datei mit dem Picture Manager 5.5 am Amiga bei einer Auflösung von 1024 x 768 bei 24 Bit
Bei mir steht
X 44
Y 44.
Für was die gehören verstehe ich schon. Nur wie werden diese Werte beim erstellen der Grafik errechnet?
Was ich noch nicht verstehe ist wie der x und y Aspect errechnet wird.
Danke für dein Angebot, ich komme da sicher gerne mal zurück.
Das kann jetzt aber einige Zeit dauern.
Es gibt da noch einen Fehler im Code.
bitmapZaehlerBreite und bitmapZaehlerHoehe müssen auf 0 zurück gesetzt werden bevor die Daten eines neuen Body geladen werden.
Ich habe mir dann eine andres Testbild gemacht, was auch Dreiecke und Kreis hat. Da konnte ich dann sehen was noch schief läuft.
Das Problem ist, das ein MC 680x0 die Byte anderes speichert als ein x86. Da ist die Bit Reihenfolge eine anderes. Aber und da bin ich auch darüber gefallen. Man muss Wissen wenn die Bit Reihenfolge im Byte umdrehen muss und wann nicht. Weil man das aber so nicht unbedingt drehen muss, bin ich nicht auf die Idee gekommen das im Body zu machen.
Klar kann ich den Code hier veröffentlichen. Ein Ziel des ganzen ist ja auch eine Doku zu schaffen die es mal genau beschreibt.
Aber bitte bedenkt das ist der Code eines Anfängers und viele Teile sind jetzt etwas schlecht, weil da viele Versuche dahinter stehen und der Code oft verändert wurde.
Ich habe in dir mal Angehängt.
Vielen dank noch mal für deine Hilfe. Auch wenn es jetzt nicht ganz die Lösung war, war dein Ansatz schon wichtig um zu verstehen wie die Daten da lieben.
Sorry, bei der BMHD hast du Recht, das hatte ich falsch im Kopf.
Es ist noch nicht perfekt. Aber der Weg stimmt. Da hat er mir den richtigen Tipp gegeben.
@Th69
Wie liegen jetzt die Daten. Vereinfacht gesagt hatten wir beide zu einen Teil recht. Es stimmt auch so wie ich es gepostet habe. Nur wenn immer gesagt wird im Amiga sind die Daten 90 Grad gedreht sieht man sie halt auch mal schnell mit dem falsch Blickwinkel an.
Sie liegen Zeilenweiße.
Beispiel Grafik 800 x600
800 Bit mit R0, 800 Bit mit R1 .... 800 Bit mit R7, 800 Bit mir G0, 800 Bit mit G1 .... 800 Bit mit G7, 800 Bit mit B0, 800 Bit mit B1 .... 800 Bit mit B7
Ganz passte es aber noch nicht. Da muss ich mir meinen Code noch genauer ansehen. Denke da läuft ein Zähler nicht ganz richtig.
Ich muss gestehen für mich als Anfänger wird das immer verwirrender. Daher ist es für mich jetzt auch schwer den C Code zu verstehen.
Vielleicht sollte ich das mal ruhen lassen und meine Kenntnisse zuerst mal vertiefen.
Ist ja voll interessant. Man sagt immer, am Amiga braucht man bei einer IFF 24 Bit Grafik 24 Befehle ( Assembler ) um die Farbe eines Pixel zu ändern. Das würde das unterstreichen wie ich am Anfang gesagt habe das die Daten liegen. Ist aber nicht so.
Es wird aber noch besser. Wenn ich von dem Masken lesen, hört sich das für mich so an als wenn dann mehr Daten gespeichert sind. Weil ja der Maskenwert noch dazu kommt.
Aber jetzt pass mal auf. Bei einer Grafik von 800 x 600 24 Bit mit dem Maskenwert 1. Also eine IFF Grafik wie sie zum Beispiel auch XnView erzeugt. Da ist der Body 1 440 000 Byte Groß. Bei der selben Grafik ohne Maske so wie ich das verstehe müsste der kleiner sein. Er ist aber auch 1 440 000 Byte groß. Was ja auch passt 800 * 600 * 3 = 1 440 000.
Wobei ich bei den Beschreibungen auch so meine Zweifel habe. Denn die BMHD wird zwar immer richtig beschrieben. Was aber so gut wie keiner dazu schreibt ist das die ersten zwei Byte leer sind.
Wie auch immer, ich habe jetzt noch wenn gefragt der so einen Code, wenn auch für den Amiga, schon mal geschrieben hat. Vielleicht habe ich Glück und er gibt mir Antwort.
Sorry das habe ich jetzt überlesen.
Wenn ich den Code nehme wo man davon ausgeht das die Grafik im Speicher gedreht ist. Also so wie ich das am Anfang gesagt habe. Bekomme ich Streifen.
Ich glaube so falsch liegst du da gar nicht. Die KI hatte da eine ganz gute Idee und meint nimm zum Beispiel ein Bild mit Vierecken.
In den Bild gibt es ein grünes Viereck an der oben rechten Ecke. Wenn man sich aber das Bild da angezeigt wird ansieht. Passt es zwar in der Höhe, aber nicht in der Breite. Da wiederholt das Bild.
Ich mach einen zweiten Beitrag wo ich das Originalbild anhänge damit man den Vergleich besser sieht.
Ich mache mir gerade was zu essen. Dann werde ich mal die Bit drehen. Versuchen kann man es ja.
Ich habe jetzt das gleiche Bild auf 100 x 100 Pixel geändert. 16 x 16 war mir doch zu kleine.
Gibt aber auch nur Datenmüll.
Am Amiga und am PC von xnView wird es richtig angezeigt.
Ich habe mir jetzt mal die Einsprung Adressen angesehen, die scheinen zu passen.
HauptZähler: 798 Spaltenzähler: 798
rotByteIndex: 798
gruenByteIndex: 1598
blauByteIndex: 2398
Bitmapzähler Breite: 798
Bitmapzähler Höhe: 0
RotByte: 00, GruenByte: 00, BlauByte: 00, Index: 31F
---------------------------
HauptZähler: 799 Spaltenzähler: 799
rotByteIndex: 799
gruenByteIndex: 1599
blauByteIndex: 2399
Bitmapzähler Breite: 799
Bitmapzähler Höhe: 0
RotByte: 00, GruenByte: 00, BlauByte: 00, Index: 960
---------------------------
HauptZähler: 800 Spaltenzähler: 0
rotByteIndex: 2400
gruenByteIndex: 3200
blauByteIndex: 4000
Bitmapzähler Breite: 0
Bitmapzähler Höhe: 1
RotByte: 00, GruenByte: 00, BlauByte: 00, Index: 961
Zwei Variablen.
xxxxByteIndex zählt immer eine Zeile. Mit xxxByteArray errechne ich die neue Adresse wenn eine Zeile durchgelaufen ist.
Beispiel Bild mit 800 x 600 Pixel.
Startwert für: rotByteIndex = 0
gruenByteIndex = 800
blauByteIndex = 1600
rotByteIndex zählt von 0 bis 799
gruenByteIndex zählt von 800 bis 1599
blauByteIndex zählt von 1600 bis 2399.
Ist die Zeile durch wird ByteArray um die Bild Breite mal 3 erhöht und auf ByteIndex übergeben.
Die Werte für die zweite Zeile sind dann
rotByteIndex = 2400
gruneByteIndex = 3200
blauByteIndex = 4000
Ja, ein Profi würde es vielleicht anderes machen.
Klar kann ich das auch mit einen kleiner Bild machen. Muss ich am PC eines in der Größe anpassen und dann am Amiga in ein IFF konvertieren.
Ich habe den Code jetzt angepasst. Aber so ganz passt es wohl noch nicht.
Ich habe mal die ersten Werte von RotByte, GruenByte und BlauByte im Hex Editor verglichen. Die stimmen.
Nur das Bild wird noch nicht richtig angezeigt. Vielleicht habe ich als Anfänger da ja eine Fehler der mir nicht auffällt.
Ich habe mal ein Bild angehängt.
// Bitmap erstellen
Bitmap flag = new Bitmap(bildBreite, bildHoehe, PixelFormat.Format24bppRgb);
using (FileStream fs = new FileStream(fileIFF, FileMode.Open, FileAccess.Read))
{
BinaryReader br = new BinaryReader(fs);
// Zu Bodydaten springen
br.BaseStream.Seek(bodyIndex + 8, SeekOrigin.Begin);
int byteBody = (bildBreite * bildHoehe * 3);
byte[] bodyData = br.ReadBytes(byteBody);
// Überprüfen, ob bodyData korrekt gelesen wurde
if (bodyData == null || bodyData.Length == 0)
{
MessageBox.Show("Body-Daten konnten nicht gelesen werden.");
return;
}
// Sprung Adresse errechnen.
hauptzaehler = bildBreite * bildHoehe; // Hauptzähler berechnen
spaltenzaehler = 0; // Ist spaltenzaehler = bildBreite. ByteArray muss neu berechnet werden
rotByteArray = 0;
gruenByteArray = bildBreite;
blauByteArray = bildBreite * 2;
rotByteIndex = rotByteArray;
gruenByteIndex = gruenByteArray;
blauByteIndex = blauByteArray;
// Zähler zum zuweisen der Farben in Bitmap auf Null setzen
bitmapZaehlerBreite = 0;
bitmapZaehlerHoehe = 0;
hz = 0; // Zähler für hauptzähler auf Null setzen
Debug.WriteLine($"Breite: {bildBreite}");
Debug.WriteLine($"Höhe: {bildHoehe}");
Debug.WriteLine($"Hauptzähler: {hauptzaehler}");
Debug.WriteLine($"\nrotByteIndex: {rotByteIndex}");
Debug.WriteLine($"gruenByteIndex: {gruenByteIndex}");
Debug.WriteLine($"blauByteIndex: {blauByteIndex}");
while (hz < hauptzaehler)
{
Debug.WriteLine($"\nHauptZähler: {hz} Spaltenzähler: {spaltenzaehler}");
// Rot auslesen
RotByte = bodyData[rotByteIndex];
// Grün auslesen
GruenByte = bodyData[gruenByteIndex];
// Blau auslesn für 8 Pixel
BlauByte = bodyData[blauByteIndex];
// Zuweisung der von xxxByteIndex
if (spaltenzaehler < bildBreite - 1)
{
rotByteIndex++;
gruenByteIndex++;
blauByteIndex++;
spaltenzaehler++;
}
else
{
rotByteArray = rotByteArray + (bildBreite * 3);
gruenByteArray = gruenByteArray + (bildBreite * 3);
blauByteArray = blauByteArray + (bildBreite * 3);
rotByteIndex = rotByteArray;
gruenByteIndex = gruenByteArray;
blauByteIndex = blauByteArray;
spaltenzaehler = 0;
}
hz += 1;
Debug.WriteLine($"\nBitmapzähler Breite: {bitmapZaehlerBreite}");
Debug.WriteLine($"Bitmapzähler Höhe: {bitmapZaehlerHoehe}\n");
Debug.WriteLine($"RotByte: {RotByte:X2}, GruenByte: {GruenByte:X2}, BlauByte: {BlauByte:X2}, Index: {rotByteIndex:X}\n");
Debug.WriteLine("---------------------------\n");
flag.SetPixel(bitmapZaehlerBreite, bitmapZaehlerHoehe, Color.FromArgb(RotByte, GruenByte, BlauByte));
if (bitmapZaehlerBreite < bildBreite -1)
{
bitmapZaehlerBreite++;
}
else
{
bitmapZaehlerBreite = 0;
bitmapZaehlerHoehe++;
}
}
}
pictureBox1.Image = flag;
}
Ja, HAM6 und HAM8 ist ein eigener Typ, wird auch wieder anderes gespeichert.
So wohl HAM6 und HAM8 kann man auf der Workbench nicht nutzen. Bilder die in HAM6 oder HAM8 gespeichert sind öffnen immer den passenden Screen dazu. Am Amiga kann so viel Screen offenen als in den Speicher passt. Heute würden wir vielleicht Desktop sagen. Dabei kann jeder Screen eine eigene Auflösung haben und Farbtiefe und Farbpalette. Mit dem AAA Chip hätte dann so gar jedes Fenster eine eigne Farbpalette haben können.
CDXL Videos sind vereinfacht gesagt nichts andres als aufeinander folgende HAM Bilder. Wobei ein CDXL Video nur eine gewissen Anzahl von Bildern haben kann.
Das IFF Format selbst ist ein Container Format, das aus verschieden Blocken besteht. So lassen sich in IFF ILBM auch noch Blöcke hinzufügen. Das haben zum Beispiel manche Grafikprogramme gemacht. So könnte man in einer Grafik auch einen Block mit Kommentaren oder einen Block mit dem Autor einfügen. Diese Blöcke würden dann, zum Beispiel vom MulitView ( universal Anzeige Programm des Amigas ) überlesen und die Grafik dennoch korrekt angezeigt.
Man muss bei einer IFF Datei immer zuerst die ersten Block auslesen. Bei jeder IFF Datei hat man zuerst FORM stehen. Das sind die ersten 4 Byte. In den nächsten 4 Byte steht die gesamt Größe der Datei. Bei einer Grafik steht dann ILBM. Damit wird angegeben das es sich um eine ILBM Grafik handelt. RGB8 würde heißen das es sich im eine 24 Bit Grafik von Turbo Silber handelt.
Dann kommt BMHD, gefolgt von den Werten der Grafik. Dann Farbkarte und dann der Body.
Der Witz ist es, es kann auch zuerst die Farbkarte kommen und dann erst BMHD. Die müssen nicht in einer gewissen Reihenfolge stehen. Wichtig ist nur das der Body als letzter steht. Am kann also nicht davon ausgehen das die Block an einer gewissen Adresse stehen. Das heißt man muss die schon suchen in der Datei wo sie sind.
Aufpassen muss man da auch, weil es immer auch leere Byte gibt. Auch muss man beachten wo genau die Daten eines Blocks stehen. Wenn du meinen Code ansiehst wird du auch sehen das ich die ersten 8 Byte im Body überspringe. Weil ersten 4 Byte BODY stehe. Damit man weiß wo sich der befinden und dann kommen 4 Byte die die Größe des Bodys angeben.
In Hex Editor sieht das dann so aus.
FORM�ù(ILBMBMHD��� X������€��,, XBODY�ù�¤nàÃ9�?æ�8|Ľ¡�<¼Ö—ÿçæiÐ
Wie du siehst gibt es hier keine Farbkarte (CMAP Block). Der wird auch bei einer IFF 24 Bit nicht gebraucht. Es gibt aber auch Programme die den Block der Farbkarte bei einer 24 Bit Grafik mit anlegen. Der ist dann leer oder mit ein paar 0 Byte gefühlt.
Ein IFF Format das sicher jeder kennt ist AIFF. TIFF ist vereinfacht gesagt ein aufgeblasenes IFF Format. Wobei Microsoft das so verändert hat das niemand mit Lizenzen kommt.-)
Sorry, hat ein bisschen gedauert, weil ich mir ja eingebildet habe ich muss noch schnell einen Video Konverter machen der auf ffmpeg passiert. Der kann zwar noch nichts anderes als Videos von einen Format ins andere zu bringen. Aber er lauft super und ist auch schon in WPF gemacht. Und einen Bilder Konverter habe ich mir auch noch eingebildet. Der ist aber noch nicht fertig. Der Dient auch mehr dazu um später mal einen IFF Konverter zu machen. Zuerst mal mit IFF 24Bit, dann auch mal die andern IFF ILBM. Dann halt auch mal HAM6 und HAM8. Zweck des ganzen ist ein Verständnis für die Dateien Formate zu bekommen. Um vielleicht mal in der Lage zu sein auf Windows einen CDXL Konverter zumachen. Bis jetzt gibt es da nur einen guten auf Linux.
Wenn du CDXL nicht kennst kannst du dir das auf meinen Kanal ansehen. Das ist ein CDXL HAM8 auf meinen Amiga 4000, am Amiga 2000 geht das dann nur mit HAM6. Das können alle Amiga ab Werk. Dazu muss ich aber sagen ich kann Höher FPS und höher Einstellungen in Audio fahren. Bei Amiga haben einen MC 68060@50.
Amiga 4000 HAM 8 Video (youtube.com)
Klar kann ein Amiga 24 Bit Grafiken und auch 32 Bit darstellen. (Siehe Bild). So gar als Hintergrundbild. Das kann mein Amiga 2000 und auch Amiga 4000. Setzt aber eine Grafikkarte voraus. Meine Amiga sind auch Ausgerüstet. Die können auch in Internet. Wobei da kann man halt nur Amiga typisch Seiten anzeigen. Hat aber seine Vorteil wenn sie das können.
Ganz richtig ist das nicht. 64 Farben im Extra Halbrite Modus trifft auf die ersten Amiga zu. Also Amiga 1000, 500, 600, 2000 und 3000. Die Amiga 1200 und Amiga 4000 könnten in dem Modus dann 256 Farben. Wo bei die erste noch dem HAM6 Modus haben mit dem man 4096 Farben anzeigen kann. Der Amiga 1200 und Amiga 4000 können in HAM8 mit dem AGA Chip dann noch mehr anzeigen.
Tja, und den AAA Chip den hat Commodore leider mit ins Grab genommen. Der hätte schon im Amiga 4000 verbaut sein sollen. Das weiß man weil der Jumper dafür da ist. ( Nur Commodore hat auf Grund des PC Geschafftes zu wenig Geld für die Entwicklung ). Der hätte 16,8 Millionen Farben anzeigen könnten oder bei einer Auflösung von 1260 x 1024 256 Farben. Zumindest wird das immer so gesagt. Der hätte auch sehr schnell sein müssen, weil Commodore damals bekannt gab das man mit den Chip ein Fenster in dem ein Video läuft verschieben kann und das Video dabei weiter läuft.
Erzeugt habe ich übrigens die IFF 24 Bit Grafiken am Amiga mit dem Picture Manager 5.5. Am könnte sie zwar auch mit XnView auf dem PC erzeugen. Nur baut das immer dann eine Maske mit ein. Was das ganze noch schwerer macht.
Auf diesen Gedankengang bin ich durch diesen Betrag von mir in Amiga Englisch Board gekommen.
IFF 24 Bit richtig gelesen? - Englisches Amiga-Board (abime.net)
So wie ich das Verstehe sind die Daten dort so gespeichert wie ich das Beschrieben habe.
Aber ich kann das ja mal versuchen das so auszulesen wie du das beschreibst.
Ganz kapiere ich es aber noch nicht. Also da heißt bei einer Grafik von 800 x 600 würden zuerst 800 Byte für Rot kommen, dann 800 Byte für Grün und dann 800 für Blau.
PS: Egal wie viele versuche daneben gehen, ich lerne so immer was neues über C# dabei.
Zitat von Gerwald
Ne da habe ich wohl falsch geklickt, man sollte halt keine Beträge schreiben vor dem Ersten Kaffee. Könnte aber auch sein das der Beitrag zu lange ist.
Ich teile in daher auf mehrere auf.@Th69:
Eine IFF Datei, egal ob sie Text, Sound, Amin oder Grafik (ILBM) enthält teilt sich immer in mehre Blöcke auf. Bild Breite und Höhe stehen dann im BMHD Block.
Der ist so aufgebaut.BMHD-Blockstruktur laut Dokumentation:
Blocktyp (BMHD) bmhdIndex Byte 0-4
Unbenutzt (2 Bytes) bmhdIndex Byte 5-7
Bildbreite (2 Bytes) bmhdIndex Byte 8-9
Bildhöhe (2 Bytes) bmhdIndex Byte 10-11
X-Versatz (2 Bytes) bmhdIndex Byte 12-13
Y-Versatz (2 Bytes) bmhdIndex Byte 14-15
Anzahl der Bitplanes (1 Byte) bmhdIndex Byte 16
Maskierungstechnik (1 Byte) bmhdIndex Byte 17
Komprimierungstechnik (1 Byte) bmhdIndex Byte 18
Padbyte (1 Byte, ungenutzt bmhdIndex Byte 19
Transparentfarbe (2 Bytes) bmhdIndex Byte 20-21
X-Aspektverhältnis (1 Byte) bmhdIndex Byte 22
Y-Aspektverhältnis (1 Byte) bmhdIndex Byte 23
Bildschirmbreite (2 Bytes) bmhdIndex Byte 24-25
Bildschirmhöhe (2 Bytes) bmhdIndex Byte 26-27Der wird von meinen Code auch korrekt ausgelesen. Hier muss man nur aufpassen wegen höherwertigen und niederwertigen Byte. Da macht der Amiga anders als ein PC.
Die Grafikdaten stehen dann im Block Body. Wobei die ersten 8 Byte übersprungen werden müssen. In den ersten 4 Byte steht, BODY und in den nächsten 4 Byte ist die Größe des Body gespeichert. Aber nur die Größe es Body nicht die gesamt Größe der Datei, die ist an einer anderen Stelle gespeichert.
Das ist jetzt der Code mit dem ich das Auslese.
Die Debug.WriteLine Befehle habe ich nur dazu eingefügt damit ich sehe, ob die Schleifen richtig laufen und richtig gezählt wird.
// ********** IFF ILBM in Bitmap erstellen **********
private void bitmap_Erstellen(System.Object sender, EventArgs e)
{
if (intMaske != 0 || kompresion != 0)
{
MessageBox.Show("Zur Zeit konnen nur Bilder ohne Maske und Kompresion angezeigt werden!");
return;
}
// Bitmap erstellen
Bitmap flag = new Bitmap(bildBreite, bildHoehe, PixelFormat.Format24bppRgb);
using (FileStream fs = new FileStream(fileIFF, FileMode.Open, FileAccess.Read))
{
BinaryReader br = new BinaryReader(fs);
// Zu Bodydaten springen
br.BaseStream.Seek(bodyIndex + 8, SeekOrigin.Begin);
int byteBody = (bildBreite * bildHoehe * 3);
byte[] bodyData = br.ReadBytes(byteBody);
// Überprüfen, ob bodyData korrekt gelesen wurde
if (bodyData == null || bodyData.Length == 0)
{
MessageBox.Show("Body-Daten konnten nicht gelesen werden.");
return;
}
// Sprung Adresse errechnen.
hauptzaehler = ((bildBreite * bildHoehe * 3) / 24); // Hauptzähler berechnen
bytezaehler = (bildBreite * bildHoehe) / 8; // Einsprung berechnen für Farbwerte
rotByteArray = 0; // Einsprung Adresse die Farbe Rot in IFF Body
gruenByteArray = bildBreite * bildHoehe; // Einsprung Adresse die Farbe Grüne in IFF Body
blauByteArray = (bildBreite * bildHoehe) * 2; // Einsprung Adresse die Farbe Blau in IFF Body
// Zähler zum zuweisen der Farben in Bitmap auf Null setzen
bitmapZaehlerBreite = 0;
bitmapZaehlerHoehe = 0;
hz = 0; // Zähler für hauptzähler auf Null setzen
byte[] RotByte = new byte[8];
byte[] GruenByte = new byte[8];
byte[] BlauByte = new byte[8];
Debug.WriteLine($"Breite: {bildBreite}");
Debug.WriteLine($"Höhe: {bildHoehe}");
Debug.WriteLine($"Hauptzähler: {hauptzaehler}");
Debug.WriteLine($"\nrotByteIndex: {rotByteIndex}");
Debug.WriteLine($"gruenByteIndex: {gruenByteIndex}");
Debug.WriteLine($"blauByteIndex: {blauByteIndex}");
Debug.WriteLine($"bytezaehler: {bytezaehler}\n");
while (hz < hauptzaehler)
{
rotByteIndex = rotByteArray;
gruenByteIndex = gruenByteArray;
blauByteIndex = blauByteArray;
rotByteIndex += hz;
gruenByteIndex += hz;
blauByteIndex += hz;
// Arrays zurücksetzen
Array.Clear(RotByte, 0, RotByte.Length);
Array.Clear(GruenByte, 0, GruenByte.Length);
Array.Clear(BlauByte, 0, BlauByte.Length);
// Rot auslesen für 8 Pixel
for (int pixelPosRot = 0; pixelPosRot < 8; pixelPosRot++)
{
Debug.WriteLine($"pixelPosRot: {pixelPosRot}, rotByteIndex: {rotByteIndex}");
pixelRGB[pixelPosRot] = bodyData[rotByteIndex];
rotByteIndex += bytezaehler;
}
Debug.WriteLine($"\n");
// Grün auslesen für 8 Pixel
for (int pixelPosGruen = 8; pixelPosGruen < 16; pixelPosGruen++)
{
Debug.WriteLine($"pixelPosGruen: {pixelPosGruen}, grünByteIndex: {gruenByteIndex}");
pixelRGB[pixelPosGruen] = bodyData[gruenByteIndex];
gruenByteIndex += bytezaehler;
}
Debug.WriteLine($"\n");
// Blau auslesn für 8 Pixel
for (int pixelPosBlau = 16; pixelPosBlau < 24; pixelPosBlau++)
{
Debug.WriteLine($"pixelPosBlau: {pixelPosBlau}, blauByteIndex: {blauByteIndex}");
pixelRGB[pixelPosBlau] = bodyData[blauByteIndex];
blauByteIndex += bytezaehler;
}
Debug.WriteLine($"\n");
// pixelRGB den Byte in der Bitmap zu ornden.
for (int i = 0; i < 8; i++)
{
for (int bit = 0; bit < 8; bit++)
{
// RotByte
RotByte[bit] |= (byte)((pixelRGB[i] & (1 << (7 - bit))) != 0 ? (1 << (7 - i)) : 0);
// GruenByte
GruenByte[bit] |= (byte)((pixelRGB[i + 8] & (1 << (7 - bit))) != 0 ? (1 << (7 - i)) : 0);
// BlauByte
BlauByte[bit] |= (byte)((pixelRGB[i + 16] & (1 << (7 - bit))) != 0 ? (1 << (7 - i)) : 0);
}
}
hz += 1;
Debug.WriteLine($"\nHz: {hz}");
// Farben der Bitmap zuweisen
for (int z = 0; z < 8; z++)
{
Debug.WriteLine($"RotByte: {RotByte[z]} GrünByte: {GruenByte[z]} BlauByte: {BlauByte[z]}");
flag.SetPixel(bitmapZaehlerBreite, bitmapZaehlerHoehe, Color.FromArgb(RotByte[z], GruenByte[z], BlauByte[z]));
Debug.WriteLine($"\nBreite: {bitmapZaehlerBreite}");
Debug.WriteLine($"Hohe: {bitmapZaehlerHoehe}");
if (bitmapZaehlerBreite < bildBreite -1)
{
bitmapZaehlerBreite += 1;
}
else
{
bitmapZaehlerBreite = 0;
bitmapZaehlerHoehe++;
}
}
}
Ich muss leider Sagen das mein Ansatz den Body auszulesen falsch war.
Die Dokumentation dazu ist leider auch nicht die beste. Ich habe das zuerst so verstanden das im Body die Daten als RGB gespeichert sind. Also so wie auf einen PC. Das ist mir zwar auch komisch vorgekommen, weil ein Amiga Grafik nicht so speichert, aber man kann es halt so verstehen wie es beschreiben ist.
Dazu muss man halt sagen das man eine IFF 24 Bit halt nicht so einfach vergleichen kann. Den in der gibt es keine Farbkarte mehr wie das sonst der Fall ist.
Die Farbkarte würde man im CAMP Block finden. Der ist aber bei einer 24 Bit Grafik leer, weil er ganz einfach zu groß wäre.
Daher stehen die Farben direkt im BODY Block. Allerdings sind sie dann auch bei einer 24 BIT IFF gedreht wie ein Amiga das so macht, ( Das hat auch Apple mal so gemacht ). Wenn man sich die Ebenen der Grafik drei Dimensional vorstellt ist die dann um 90 Grad gedreht.
Sie stehen also so im Speicher.
Byte 0 Byte 1 Byte 2 ...
R0 01234567 01234567 01234567
R1 01234567 01234567 01234567
R2 01234567 01234567 01234567
R3 01234567 01234567 01234567
und so weiter.
Das heißt in der ersten Ebene stehen für alle Pixel der Wert von R0. Also das erste Bit für Rot. In der zweiten Ebene das zweite Bit für Rot und so weiter. Dann kommen die Werte für Grün und dann für Blau.
Wen meine Gedankengänge stimmen würde das heißen.
Bei einer Grafik von 800 x 600 Pixel, wäre die Grafik Daten im Body 1 440 000 Byte groß. ( Nur die Grafikdaten, die ganze Datei hätte dann 1 440 040 Byte)
Das müsste heißen die Blöcke für Rot, Grün und Blau sind immer 480 000 Byte groß. Jede Ebene wäre dann 60 000 Byte groß.
Für das erste Pixel müsste dann das erste Bit im Byte 0 stehen. Das zweit Bit dann im Byte an der Stelle 60 000, das dritte Bit für Rot an der stelle 120 000 und so weiter.
Die Werte für Grün sollten dann beim Byte an der Stelle 480 000 beginnen und für Blau bei 960 000.
Das heißt ich muss für die Farbe für ein Pixel 24 Byte auslesen. gebraucht wird aber für ein Pixel immer nur ein 1 Bit aus den 24 Byte. Weil man damit aber schon die Farbwerte von 8 Pixel liest. Habe ich das so gemacht das die einzelne Bit gleich 8 Pixel zu gewissen werden.
Nur leider bekomme ich halt nur Datenmüll. Komischerweise hat dieser Datenmüll viele Grün. Die Grafik besteht aber mehr aus Rot und Orange.
Also könnte es sein das meine Zuordnung der Bit falsch ist, oder meine Gedankengänge.
Ne da habe ich wohl falsch geklickt, man sollte halt keine Beträge schreiben vor dem Ersten Kaffee. Könnte aber auch sein das der Beitrag zu lange ist.
Ich teile in daher auf mehrere auf.
@Th69:
Eine IFF Datei, egal ob sie Text, Sound, Amin oder Grafik (ILBM) enthält teilt sich immer in meiner Blöcke auf. Bild Breite und Höhe stehen dann im BMHD Block.
Der ist so aufgebaut.
BMHD-Blockstruktur laut Dokumentation:
Blocktyp (BMHD) bmhdIndex Byte 0-4
Unbenutzt (2 Bytes) bmhdIndex Byte 5-7
Bildbreite (2 Bytes) bmhdIndex Byte 8-9
Bildhöhe (2 Bytes) bmhdIndex Byte 10-11
X-Versatz (2 Bytes) bmhdIndex Byte 12-13
Y-Versatz (2 Bytes) bmhdIndex Byte 14-15
Anzahl der Bitplanes (1 Byte) bmhdIndex Byte 16
Maskierungstechnik (1 Byte) bmhdIndex Byte 17
Komprimierungstechnik (1 Byte) bmhdIndex Byte 18
Padbyte (1 Byte, ungenutzt bmhdIndex Byte 19
Transparentfarbe (2 Bytes) bmhdIndex Byte 20-21
X-Aspektverhältnis (1 Byte) bmhdIndex Byte 22
Y-Aspektverhältnis (1 Byte) bmhdIndex Byte 23
Bildschirmbreite (2 Bytes) bmhdIndex Byte 24-25
Bildschirmhöhe (2 Bytes) bmhdIndex Byte 26-27
Der wird von meinen Code auch korrekt ausgelesen. Hier muss man nur aufpassen wegen höherwertigen und niederwertigen Byte. Da macht der Amiga anders als ein PC.
Die Grafikdaten stehen dann im Block Body. Wobei die ersten 8 Byte übersprungen werden müssen. In den ersten 4 Byte steht, BODY und in den nächsten 4 Byte ist die Größe des Body gespeichert. Aber nur die Größe es Body nicht die gesamt Größe der Datei, die ist an einer anderen Stelle gespeichert.
Uff ich sehe meine neuen Beitrag jetzt nicht. Ich hoffe ich habe da nix falsch angeklickt, sonst kann ich ihn noch mal schreiben. Oder muss der zuerst freigeschalten werden. Muss ich halt mal warten, wenn da nichts kommt muss ich es noch mal schreiben.
Aber ich hänge mal ein Bild an wie das dann aussieht.
Ich habe angefangen mit dem Programmieren angefangen.
Jetzt versuche ich gerade ein Programm zu machen das IFF ILBM 24 Bit anzeigen kann. Diese Bilder haben keinen Maske und keine Komprision. Die werden auch auf einen Amiga kortekt angezeigt.
Ich lese den Body der IFF Datei wird auch korrekt gelesen und übertrage die Daten in eine Bitmap.
Nur bei meinen Programm bekomme ich nur Datenmüll angezeigt.
Ein Möglichkeit wäre das die Daten nicht richtig in die Bitmap eingetragen werden. Mein Frage daher wie ist die Bitmap genau in C# aufgebaut?
So sieht der Code aus, der den Body ausliest. Vielleicht habe ich ja als Anfänger auch da einen Denkfehler
private void bitmap_Erstellen(System.Object sender, EventArgs e)
{
if (intMaske != 0 || kompresion != 0)
{
MessageBox.Show("Zur Zeit konnen nur Bilder ohne Maske und Kompresion angezeigt werden!");
return;
}
Bitmap flag = null;
// Bitmap erstellen
flag = new Bitmap(bildBreite, bildHoehe, PixelFormat.Format24bppRgb);
using (FileStream fs = new FileStream(fileIFF, FileMode.Open, FileAccess.Read))
{
BinaryReader br = new BinaryReader(fs);
// Zu Bodydaten springen
br.BaseStream.Seek(bodyIndex + 8, SeekOrigin.Begin);
int byteBody = (bildBreite * bildHoehe * 3);
byte[] bodyData = br.ReadBytes(byteBody);
int bodyDataSize = bodyData.Length;
// Überprüfen, ob bodyData korrekt gelesen wurde
if (bodyData == null || bodyData.Length == 0)
{
MessageBox.Show("Body-Daten konnten nicht gelesen werden.");
return;
}
/*
// Die ersten 8 Werte anzeigen
Debug.WriteLine("Erste 8 Werte:");
for (int i = 0; i < 8 && i < bodyData.Length; i++)
{
Debug.WriteLine($"Wert {i + 1}: {bodyData[i]} (Hex: {bodyData[i]:X2})");
}
*/
for (indexhoehe = 0; indexhoehe < bildHoehe; indexhoehe++)
{
for (indexbreite = 0; indexbreite < bildBreite; indexbreite++)
{
pixelIndex = (indexhoehe * bildBreite + indexbreite) * 3;
byte byteRot = bodyData[pixelIndex];
byte byteGruen = bodyData[pixelIndex + 1];
byte byteBlau = bodyData[pixelIndex + 2];
//byte byteAlpha = bodyData[pixelIndex + 3];
// Byte-Werte anzeigen
//Debug.WriteLine($"Pixel ({indexbreite}, {indexhoehe}): Rot = {byteRot} (Hex: {byteRot:X2}), Grün = {byteGruen} (Hex: {byteGruen:X2}), Blau = {byteBlau} (Hex: {byteBlau:X2})");
//
// Setze die Pixel in der Bitmap
Color color = Color.FromArgb(byteRot, byteGruen, byteBlau);
flag.SetPixel(indexbreite, indexhoehe, color);
int width = flag.Width;
int height = flag.Height;
int pixelSize = 3;
int flagSize = width * height * pixelSize;
label1.Text = ("Größe Body " + bodyDataSize.ToString() + " Größe Flag: " + flagSize);
}
}
}
pictureBox1.Image = flag; // In einer PictureBox anzeigen
}