/// <summary> /// Lädt die SLP-Daten. /// </summary> /// <param name="buffer">Ein Puffer mit den SLP-Daten. Die Leseposition wird entsprechend der Datenlänge erhöht.</param> /// <remarks></remarks> private void loadData(RAMBuffer buffer) { // Header #region SLP-Header _headers.Version = buffer.ReadString(4); _headers.FrameCount = buffer.ReadUInteger(); _headers.Comment = buffer.ReadString(24); #endregion SLP-Header // Frame-Informationen: Header #region Frame-Header for(int i = 0; i < _headers.FrameCount; i++) { // Neues Frame-Header-Objekt erstellen FrameInformationHeader aktFIH = new FrameInformationHeader(); // Der Zeichenindex in der SLP-Datei, an dem die Kommandotabelle des Frames beginnt aktFIH.FrameCommandsOffset = buffer.ReadUInteger(); // Der Zeichenindex in der SLP-Datei, an dem die Umrissdaten (RowEdge) des Frames gespeichert sind aktFIH.FrameOutlineOffset = buffer.ReadUInteger(); // Der Zeichenindex in der SLP-Datei, an dem die Farbpalette des Frames definiert ist; Genaueres ist nicht bekannt aktFIH.PaletteOffset = buffer.ReadUInteger(); // Die Frame-Eigenschaften; die Bedeutung dieses Werts ist unbekannt aktFIH.Properties = buffer.ReadUInteger(); // Die Abmessungen des Frames aktFIH.Width = buffer.ReadUInteger(); aktFIH.Height = buffer.ReadUInteger(); // Die Anker (Mittelpunkt) des Frames aktFIH.AnchorX = buffer.ReadInteger(); aktFIH.AnchorY = buffer.ReadInteger(); // Frame-Header in die zentrale Liste schreiben _frameInformationHeaders.Add(aktFIH); } #endregion Frame-Header // Frameinformationen: Daten #region Frame-Daten (RowEdge und Kommandotabelle) // Gefundene Einstellungen merken bool useTransp = false; bool useOutline1 = false; bool useOutline2 = false; bool usePlayerColor = false; bool useShadow = false; // Frames einzeln durchgehen for(int i = 0; i < _headers.FrameCount; i++) { // Spielernummer einer ggf. ausgegebenen Einheit const byte Spielernummer = 0; // Spieler 1 => Blau // Frame-Header-Daten abrufen FrameInformationHeader aktFIH = _frameInformationHeaders[i]; // Neues Frame-Daten-Objekt erstellen FrameInformationData aktFID = new FrameInformationData(); // RowEdge (leere Fläche [=> Transparenz, ohne Kommandos], von den Bildrändern ausgehend) #region RowEdge-Daten // Arrays initialisieren: Das RowEdge-Array und das BinaryRowEdge-Array, um bei unveränderten Frames dieses nicht neu berechnen zu müssen und direkt schreiben zu können aktFID.RowEdge = new ushort[aktFIH.Height, 2]; aktFID.BinaryRowEdge = new BinaryRowedge[aktFIH.Height]; for(int j = 0; j < aktFIH.Height; j++) { // Werte einlesen ushort left = buffer.ReadUShort(); // Links ushort right = buffer.ReadUShort(); // Rechts // Evtl. falsche Werte korrigieren { // Links if(left > aktFIH.Width) { left = (ushort)aktFIH.Width; } // Rechts if(right > aktFIH.Width) { right = (ushort)aktFIH.Width; } } // Werte speichern aktFID.RowEdge[j, 0] = left; aktFID.RowEdge[j, 1] = right; // Binäres RowEdge mitschreiben aktFID.BinaryRowEdge[j] = new BinaryRowedge(left, right); } #endregion RowEdge-Daten // Kommandotabellen-Offsets abrufen #region Kommandotabellen-Offsets aktFID.CommandTableOffsets = new uint[aktFIH.Height]; for(int j = 0; j < aktFIH.Height; j++) { aktFID.CommandTableOffsets[j] = buffer.ReadUInteger(); } #endregion Kommandotabellen-Offsets // Kommandotabelle zeilenweise auslesen und umgewandelte Kommandotabelle erzeugen #region Kommandotabelle // Gleichzeitig wird die binaryCommands-Variable miterzeugt, um unveränderte Frames ggf. ohne Umweg über eine Neuerstellung der Kommandos wieder in die *.slp schreiben zu können aktFID.CommandTable = new int[aktFIH.Height, aktFIH.Width]; aktFID.BinaryCommandTable = new List<BinaryCommand>(); for(int j = 0; j < aktFIH.Height; j++) { // Gibt die aktuelle X-Position innerhalb des generierten Bildes (in Pixeln) an int aktPtr = 0; // Linker RowEdge-Bereich ist leer => transparent, also -1 for(int k = 0; k < aktFID.RowEdge[j, 0]; k++) { aktFID.CommandTable[j, aktPtr + k] = -1; } // Linker RowEdge-Bereich ist komplett in das Bild geschrieben worden aktPtr += aktFID.RowEdge[j, 0]; // Wird false, wenn ein Zeilenumbruch erreicht wurde bool Weiter = true; // Kommando für Kommando lesen while(Weiter) { // Das aktuelle Kommandobyte byte aktKommandoByte = buffer.ReadByte(); // Das aktuelle Kommando (die ersten vier Bits des Kommandobytes) Wird berechnet, um das oft mit der Datenlänge korrelierte Kommandobyte bestimmen zu können (es müssen nur die Werte 0 bis 15 abgefragt werden, statt eigentlich 0 bis 255; weiterhin geben immer die ersten 2 oder 4 Bits das Kommando an, die anderen 4 oder 6 meist nur die jeweilige Länge) byte aktKommando = (byte)(aktKommandoByte & 0x0F); // Das Kommando auswerten switch(aktKommando) { // Farbblock (klein) case 0x00: case 0x04: case 0x08: case 0x0C: { // Länge ermitteln int len = aktKommandoByte >> 2; // Daten einlesen byte[] dat = buffer.ReadByteArray(len); // Daten in die Kommandotabelle schreiben for(int k = 0; k < len; k++) { aktFID.CommandTable[j, aktPtr + k] = dat[k]; } // Es wurden len Pixel eingelesen aktPtr += len; // Binary-Wert erstellen cmdColor(ref aktFID, dat); break; } // Transparenz (klein) case 0x01: case 0x05: case 0x09: case 0x0D: { // Länge ermitteln int len = aktKommandoByte >> 2; // Transparenz in die Kommandotabelle schreiben for(int k = 0; k < len; k++) { aktFID.CommandTable[j, aktPtr + k] = -1; } // Es wurden len Pixel eingelesen aktPtr += len; // Binary-Wert erstellen cmdTransp(ref aktFID, len); // Transparenz wurde gefunden useTransp = true; break; } // Großer Farbblock case 0x02: { // Hilfs-Kommandobyte auslesen byte byte2 = buffer.ReadByte(); // Länge ermitteln int len = ((aktKommandoByte & 0xF0) << 4) + byte2; // Daten einlesen byte[] dat = buffer.ReadByteArray(len); // Daten in die Kommandotabelle schreiben for(int k = 0; k < len; k++) { aktFID.CommandTable[j, aktPtr + k] = dat[k]; } // Es wurden len Pixel eingelesen aktPtr += len; // Binary-Wert erstellen cmdColor(ref aktFID, dat); break; } // Großer Transparenzblock case 0x03: { // Hilfs-Kommandobyte auslesen byte byte2 = buffer.ReadByte(); // Länge ermitteln int len = ((aktKommandoByte & 0xF0) << 4) + byte2; // Transparenz in die Kommandotabelle schreiben for(int k = 0; k < len; k++) { aktFID.CommandTable[j, aktPtr + k] = -1; } // Es wurden len Pixel eingelesen aktPtr += len; // Binary-Wert erstellen cmdTransp(ref aktFID, len); // Transparenz wurde gefunden useTransp = true; break; } // Spielerfarbenblock case 0x06: { // Die oberen 4 Bits bestimmen byte next4Bits = (byte)(aktKommandoByte & 0xF0); // Die Länge der Daten int len = 0; // Die oberen 4 Bits sind 0, wenn die Länge im nächsten Byte angegeben ist; ansonsten werden diese um 4 nach rechts verschoben und sind somit als Längenangabe verwendbar if(next4Bits == 0) { len = buffer.ReadByte(); } else { len = next4Bits >> 4; } // Daten auslesen byte[] dat = buffer.ReadByteArray(len); // Daten durchgehen for(int k = 0; k < len; k++) { // Das aktuelle Byte byte aktVal = dat[k]; // Farbindex berechnen: Die Spielerfarben liegen zwischen 16 und 13. Beim SLP-Schreiben wurde von allen Werten 16 subtrahiert => aktVal liegt zwischen 0 und 7. Zwischen den Spielerfarben auf der Palette liegen immer 16 Einheiten. Angegeben wird die Spielerfarbe durch: 16 + (Spielernummer - 1) * 16, wobei die Spielernummer zwischen 1 und 8 liegt. aktVal = (byte)(aktVal + 16 + 16 * Spielernummer); // Wert in das Bild schreiben aktFID.CommandTable[j, aktPtr + k] = aktVal; // Wert zurück in Array schreiben, um das Schreiben der Binary-Daten zu erleichtern dat[k] += 16; } // Es wurden len Pixel eingelesen aktPtr += len; // Binary-Wert erstellen cmdPlayerColor(ref aktFID, dat); // Spielerfarben wurden gefunden usePlayerColor = true; break; } // Einfarbiger Block case 0x07: { // Die oberen 4 Bits bestimmen byte next4Bits = (byte)(aktKommandoByte & 0xF0); // Die Länge der Daten int len = 0; // Die oberen 4 Bits sind 0, wenn die Länge im nächsten Byte angegeben ist; ansonsten werden diese um 4 nach rechts verschoben und sind somit als Längenangabe verwendbar if(next4Bits == 0) { len = buffer.ReadByte(); } else { len = next4Bits >> 4; } // Das nächste Byte gibt die Farbe an byte farbe = buffer.ReadByte(); // Hilfsvariable für das Binary-Schreiben byte[] dat = new byte[len]; // Betroffene Pixel durchgehen for(int k = 0; k < len; k++) { // Farbe in das Bild schreiben aktFID.CommandTable[j, aktPtr + k] = farbe; // Farbe in das Array übernehmen dat[k] = farbe; } // Es wurden len Pixel eingelesen aktPtr += len; // Binary-Wert erstellen cmdColor(ref aktFID, dat); break; } // Einfarbiger Spielerfarben-Block case 0x0A: { // Die oberen 4 Bits bestimmen byte next4Bits = (byte)(aktKommandoByte & 0xF0); // Die Länge der Daten int len = 0; // Die oberen 4 Bits sind 0, wenn die Länge im nächsten Byte angegeben ist; ansonsten werden diese um 4 nach rechts verschoben und sind somit als Längenangabe verwendbar if(next4Bits == 0) { len = buffer.ReadByte(); } else { len = next4Bits >> 4; } // Das nächste Byte gibt die Grundfarbe an byte farbe = buffer.ReadByte(); // Hilfsvariable für das Binary-Schreiben byte[] dat = new byte[len]; // Daten durchgehen for(int k = 0; k < len; k++) { // Das aktuelle Byte byte aktVal = farbe; // Farbindex berechnen: Die Spielerfarben liegen zwischen 16 und 13. Beim SLP-Schreiben wurde von allen Werten 16 subtrahiert => aktVal liegt zwischen 0 und 7. Zwischen den Spielerfarben auf der Palette liegen immer 16 Einheiten. Angegeben wird die Spielerfarbe durch: 16 + (Spielernummer - 1) * 16, wobei die Spielernummer zwischen 1 und 8 liegt. aktVal = (byte)(aktVal + 16 + 16 * Spielernummer); // Wert in das Bild schreiben aktFID.CommandTable[j, aktPtr + k] = aktVal; // Wert zurück in Array schreiben, um das Schreiben der Binary-Daten zu erleichtern dat[k] = (byte)(farbe + 16); } // Es wurden len Pixel eingelesen aktPtr += len; // Binary-Wert erstellen cmdPlayerColor(ref aktFID, dat); // Spielerfarben wurden gefunden usePlayerColor = true; break; } // Schattenblock case 0x0B: { // Die oberen 4 Bits bestimmen byte next4Bits = (byte)(aktKommandoByte & 0xF0); // Die Länge der Daten int len = 0; // Die oberen 4 Bits sind 0, wenn die Länge im nächsten Byte angegeben ist; ansonsten werden diese um 4 nach rechts verschoben und sind somit als Längenangabe verwendbar if(next4Bits == 0) { len = buffer.ReadByte(); } else { len = next4Bits >> 4; } // Schattenpixel einzeln durchgehen for(int k = 0; k < len; k++) { // Schatten in Bild schreiben aktFID.CommandTable[j, aktPtr + k] = -4; } // Es wurden len Pixel eingelesen aktPtr += len; // Binary-Wert erstellen cmdShadow(ref aktFID, len); // Schatten wurde gefunden useShadow = true; break; } // Outline-Kommandos: Hängen von Kommandobyte ab ("E" am Ende bei allen gemeinsam) case 0x0E: { switch(aktKommandoByte) { // Outline1-Pixel case 0x4E: { // Outline auf Bild schreiben aktFID.CommandTable[j, aktPtr] = -2; // Es wurde ein Pixel eingelesen aktPtr += 1; // Binary-Wert erstellen cmdOutline1(ref aktFID, 1); // Outline1 wurde gefunden useOutline1 = true; break; } // Outline2-Pixel case 0x6E: { // Outline auf Bild schreiben aktFID.CommandTable[j, aktPtr] = -3; // Es wurde ein Pixel eingelesen aktPtr += 1; // Binary-Wert erstellen cmdOutline2(ref aktFID, 1); // Outline2 wurde gefunden useOutline2 = true; break; } // Outline1-Block case 0x5E: { // Blocklänge abrufen int len = buffer.ReadByte(); // Outlinepixel in der angegebenen Anzahl auf das Bild schreiben for(int k = 0; k < len; k++) { aktFID.CommandTable[j, aktPtr + k] = -2; } // Es wurden len Pixel eingelesen aktPtr += len; // Binary-Wert erstellen cmdOutline1(ref aktFID, len); // Outline1 wurde gefunden useOutline1 = true; break; } // Outline2-Block case 0x7E: { // Blocklänge abrufen int len = buffer.ReadByte(); // Outlinepixel in der angegebenen Anzahl auf das Bild schreiben for(int k = 0; k < len; k++) { aktFID.CommandTable[j, aktPtr + k] = -3; } // Es wurden len Pixel eingelesen aktPtr += len; // Binary-Wert erstellen cmdOutline2(ref aktFID, len); // Outline2 wurde gefunden useOutline2 = true; break; } } break; } // Zeilenende case 0x0F: { // Kein weiterer while-Schleifen-Durchlauf => nächste Zeile (for-Schleife) Weiter = false; // Binary-Wert erstellen cmdEOL(ref aktFID); break; } } // Ende switch: Kommando auswerten } // Ende while: Kommando für Kommando // Rechtes RowEdge einfügen (leere Bereiche) Leere Bereiche sind transparent, also erstmal -1 als Palettenindex schreiben for(int k = 0; k < aktFID.RowEdge[j, 1]; k++) { aktFID.CommandTable[j, aktPtr + k] = -1; } aktPtr += aktFID.RowEdge[j, 1]; } // Ende for: Zeile für Zeile #endregion Kommandotabelle // Framedaten zur zentralen Liste hinzufügen _frameInformationData.Add(aktFID); } // Ende for: Frame für Frame // Einstellungen speichern _settings = (useTransp ? Settings.UseTransparency : 0) | (useOutline1 ? Settings.UseOutline1 : 0) | (useOutline2 ? Settings.UseOutline2 : 0) | (usePlayerColor ? Settings.UsePlayerColor : 0) | (useShadow ? Settings.UseShadow : 0); #endregion Frame-Daten (RowEdge und Kommandotabelle) }
/// <summary> /// Ersetzt einen vorhandenen Frame oder fügt einen neuen am Ende hinzu. /// </summary> /// <param name="frameID">Die ID des Frames (bei Ersetzung) oder -1 für einen neuen Frame.</param> /// <param name="frameBitmap">Die Bilddaten, die in Kommando-Daten umgewandelt werden sollen (mit 50500er-Palette versehen).</param> /// <param name="pal">Die zu verwendende Farbpalette.</param> /// <param name="ankerX">Die X-Koordinate des Mittelpunkts der Grafik.</param> /// <param name="ankerY">Die Y-Koordinate des Mittelpunkts der Grafik.</param> /// <param name="settings">Die Einstellungen als Wert der Settings-Enumeration.</param> public void addReplaceFrame(int frameID, BitmapLoader frameBitmap, ColorTable pal, int ankerX, int ankerY, Settings settings) { #region Grundlegenes und Initialisierungen // Größen ermitteln int height = frameBitmap.Height; int width = frameBitmap.Width; // Framedaten FrameInformationData aktFID; FrameInformationHeader aktFIH; // Neuer Frame? if(frameID < 0 || frameID >= _frameInformationData.Count) { // Neue Framedaten erstellen aktFID = new FrameInformationData(); _frameInformationData.Add(aktFID); aktFIH = new FrameInformationHeader(); _frameInformationHeaders.Add(aktFIH); // Neue Frame-ID ermitteln frameID = _frameInformationData.Count - 1; } else { // Frame laden aktFID = _frameInformationData[frameID]; aktFIH = _frameInformationHeaders[frameID]; } // Anker speichern aktFIH.AnchorX = ankerX; aktFIH.AnchorY = ankerY; // Speichern der Abmessungen aktFIH.Width = (uint)width; aktFIH.Height = (uint)height; // RowEdge initialisieren aktFID.BinaryRowEdge = new BinaryRowedge[height]; for(int i = 0; i < height; i++) { aktFID.BinaryRowEdge[i] = new BinaryRowedge(); } // Kommando-Offset-Array initalisieren aktFID.CommandTableOffsets = new uint[height]; // Kommando-Array initialisieren aktFID.BinaryCommandTable = new List<BinaryCommand>(); #endregion Grundlegenes und Initialisierungen // Bild in umgesetzte Kommandodaten umwandeln #region Umwandlung in umgesetzte Kommandodaten (Masken + Farbenindizes) int[,] xCommandTable; // [Y, X] => Hilfsvariable für effizienteren Zugriff, enthält alle Palettenverweise des Bilds bzw. die negativen Masken-Pixel aktFID.CommandTable = new int[height, width]; { // Bildindizes (Daten) in die umgesetzte Kommandotabelle schreiben for(int i = 0; i < height; i++) { for(int j = 0; j < width; j++) { aktFID.CommandTable[i, j] = frameBitmap[j, i]; } } // Aus Effizienzgründen die umgewandelte Kommandotabelle in ein nahezu Objekt-freies int-Array kopieren (Direktzugriff ohne Umwege über unnötige OOP) xCommandTable = (int[,])aktFID.CommandTable.Clone(); // Berechnen der Masken #region Maskenberechnung { // Unsichtbar wird immer 255er-Weiß int _transMaskIndex = 255; // Transparenz if((settings & Settings.UseTransparency) == Settings.UseTransparency) { // Jedem transparenten 255er-Pixel den Index -1 verpassen for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { if(xCommandTable[y, x] == _transMaskIndex) xCommandTable[y, x] = -1; } } } // Sämtliche Transparenz hat nun den Wert -1 _transMaskIndex = -1; // Umriss 1 (Outline 1): Der Umriss des Objekts in der Grafik (wenn das Objekt hinter einem anderen steht, werden diese Umrisse in der Spielerfarbe dargestellt) Es müssen alle vier Richtungen durchgerechnet werden if((settings & Settings.UseOutline1) == Settings.UseOutline1) { // Waagerecht for(int y = 0; y < height; y++) { // Nach rechts for(int x = 0; x < width - 1; x++) { // Befindet sich beim nächsten Pixel keine Transparenz und auch kein Umriss 1? => Umriss if(xCommandTable[y, x] == _transMaskIndex && xCommandTable[y, x + 1] != _transMaskIndex && xCommandTable[y, x + 1] != -2) { xCommandTable[y, x] = -2; } } // Nach links for(int x = width - 1; x > 0; x--) { // Befindet sich beim nächsten Pixel keine Transparenz und auch kein Umriss 1? => Umriss if(xCommandTable[y, x] == _transMaskIndex && xCommandTable[y, x - 1] != _transMaskIndex && xCommandTable[y, x - 1] != -2) { xCommandTable[y, x] = -2; } } } // Senkrecht for(int x = 0; x < width; x++) { // Nach unten for(int y = 0; y < height - 1; y++) { // Befindet sich beim nächsten Pixel keine Transparenz und auch kein Umriss 1? => Umriss if(xCommandTable[y, x] == _transMaskIndex && xCommandTable[y + 1, x] != _transMaskIndex && xCommandTable[y + 1, x] != -2) { xCommandTable[y, x] = -2; } } // Nach oben for(int y = height - 1; y > 0; y--) { // Befindet sich beim nächsten Pixel keine Transparenz und auch kein Umriss 1? => Umriss if(xCommandTable[y, x] == _transMaskIndex && xCommandTable[y - 1, x] != _transMaskIndex && xCommandTable[y - 1, x] != -2) { xCommandTable[y, x] = -2; } } } } // Umriss 2 (Outline 2): Zweiter Umriss, umschließt Umriss 1 if((settings & Settings.UseOutline2) == Settings.UseOutline2) { // Zuerst Outline 1 für das Outline 2-Array neu berechnen (falls dies noch nicht passiert ist) if((settings & Settings.UseOutline1) != Settings.UseOutline1) { // Waagerecht for(int y = 0; y < height; y++) { // Nach rechts for(int x = 0; x < width - 1; x++) { // Befindet sich beim nächsten Pixel keine Transparenz und auch kein Umriss 1? => Umriss if(xCommandTable[y, x] == _transMaskIndex && xCommandTable[y, x + 1] != _transMaskIndex && xCommandTable[y, x + 1] != -2) { xCommandTable[y, x] = -2; } } // Nach links for(int x = width - 1; x > 0; x--) { // Befindet sich beim nächsten Pixel keine Transparenz und auch kein Umriss 1? => Umriss if(xCommandTable[y, x] == _transMaskIndex && xCommandTable[y, x - 1] != _transMaskIndex && xCommandTable[y, x - 1] != -2) { xCommandTable[y, x] = -2; } } } // Senkrecht for(int x = 0; x < width; x++) { // Nach unten for(int y = 0; y < height - 1; y++) { // Befindet sich beim nächsten Pixel keine Transparenz und auch kein Umriss 1? => Umriss if(xCommandTable[y, x] == _transMaskIndex && xCommandTable[y + 1, x] != _transMaskIndex && xCommandTable[y + 1, x] != -2) { xCommandTable[y, x] = -2; } } // Nach oben for(int y = height - 1; y > 0; y--) { // Befindet sich beim nächsten Pixel keine Transparenz und auch kein Umriss 1? => Umriss if(xCommandTable[y, x] == _transMaskIndex && xCommandTable[y - 1, x] != _transMaskIndex && xCommandTable[y - 1, x] != -2) { xCommandTable[y, x] = -2; } } } } // Outline 2 auf Outline 1 basierend erstellen (Umriss 1 wird wie eine gewöhnliche Farbe behandelt) { // Waagerecht for(int y = 0; y < height; y++) { // Nach rechts for(int x = 0; x < width - 1; x++) { // Befindet sich beim nächsten Pixel keine Transparenz? => Umriss if(xCommandTable[y, x] == _transMaskIndex && xCommandTable[y, x + 1] != _transMaskIndex && (x + 1 != width - 1)) { xCommandTable[y, x] = -3; } } // Nach links for(int x = width - 1; x > 0; x--) { // Befindet sich beim nächsten Pixel keine Transparenz? => Umriss if(xCommandTable[y, x] == _transMaskIndex && xCommandTable[y, x - 1] != _transMaskIndex && (x + 1 != width - 1)) { xCommandTable[y, x] = -3; } } } // Senkrecht for(int x = 0; x < width; x++) { // Nach unten for(int y = 0; y < height - 1; y++) { // Befindet sich beim nächsten Pixel keine Transparenz? => Umriss if(xCommandTable[y, x] == _transMaskIndex && xCommandTable[y + 1, x] != _transMaskIndex) { xCommandTable[y, x] = -3; } } // Nach oben for(int y = height - 1; y > 0; y--) { // Befindet sich beim nächsten Pixel keine Transparenz? => Umriss if(xCommandTable[y, x] == _transMaskIndex && xCommandTable[y - 1, x] != _transMaskIndex) { xCommandTable[y, x] = -3; } } } } } // Schatten (Farbindex 131) if((settings & Settings.UseShadow) == Settings.UseShadow) { // Jeden Schattenpixel mit -4 markieren for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { if(xCommandTable[y, x] == 131) xCommandTable[y, x] = -4; } } } } // Ende Maskenberechnung #endregion Maskenberechnung // Kommandotabelle zwischenspeichern aktFID.CommandTable = (int[,])xCommandTable.Clone(); } // Ende Umwandlung in umgesetzte Kommandodaten #endregion Umwandlung in umgesetzte Kommandodaten (Masken + Farbenindizes) // Generieren der RowEdge-Daten (Außenränder, Bestimmung waagerecht) #region Generierung der RowEdge-Daten for(int y = 0; y < height; y++) { // Von links nach rechts int left = 0; for(int x = 0; x < width; x++) { if(xCommandTable[y, x] != -1) break; else left++; } // Von rechts nach links int right = 0; for(int x = width - 1; x >= 0; x--) { if(xCommandTable[y, x] != -1) break; else right++; } // Liegt eine leere Zeile vor? if(left == width) { // Leere Zeile right = 0; } // Werte speichern aktFID.BinaryRowEdge[y] = new BinaryRowedge(left, right); } #endregion Generierung der RowEdge-Daten // Ziel-Kommando-Tabelle erstellen CreateBinaryCommandTable(aktFID, width, height, settings); // Frame-Daten-Variablen speichern _frameInformationHeaders[frameID] = aktFIH; _frameInformationData[frameID] = aktFID; // Sicherheitshalber Frame-Anzahl im Header aktualisieren _headers.FrameCount = (uint)_frameInformationHeaders.Count; // Fertig: RowEdge-Daten und Kommandotabelle vollständig erstellt. }