Exemplo n.º 1
0
		/// <summary>
		/// Exportiert den angegebenen Frame in eine Bitmap-Datei (50500er-Palette).
		/// </summary>
		/// <param name="frameID">Die ID des zu exportierenden Frame.</param>
		/// <param name="Pal">Die Farbtabelle.</param>
		/// <param name="filename">Die Bitmap-Datei, in die die Daten geschrieben werden sollen.</param>
		/// <param name="mask">Die zu exportierende Maske (oder reine Grafik) als Element der Masks-Enumeration.</param>
		public void exportFrame(int frameID, string filename, ColorTable Pal, Masks mask = Masks.Graphic)
		{
			// Framedaten abrufen
			FrameInformationHeader FIH = _frameInformationHeaders[(int)frameID];

			// Rückgabebild erstellen
			BitmapLoader bmp = new BitmapLoader((int)FIH.Width, (int)FIH.Height, Pal);

			// Welche Maske ist gewollt?
			if(mask == Masks.Graphic) // Es handelt sich um die reine Frame-Grafik
			{
				// Bild pixelweise durchgehen
				for(int i = 0; i < FIH.Width; i++)
				{
					for(int j = 0; j < FIH.Height; j++)
					{
						// Palettenindex abrufen
						int farbID = _frameInformationData[(int)frameID].CommandTable[j, i];

						// Sonderindizes in die jeweiligen Farben umsetzen; meist Rein-Weiß
						switch(farbID)
						{
							case -1:
								farbID = 255;
								break;

							case -2:
								farbID = 255;
								break;

							case -3:
								farbID = 255;
								break;

							case -4:
								farbID = _schatten;
								break;
						}

						// Pixel in das Bild schreiben
						bmp[i, j] = (byte)farbID;
					}
				}
			}
			else if(mask != Masks.PlayerColor) // Es handelt sich um eine Maske (außer der Spielerfarbe)
			{
				// Den Index und die Zielfarbe angeben
				int maskIndex = 0;
				int maskColor = 0;
				if(mask == Masks.Transparency)
				{
					maskIndex = -1;
					maskColor = 0;
				}
				else if(mask == Masks.Outline1)
				{
					maskIndex = -2;
					maskColor = 8;
				}
				else if(mask == Masks.Outline2)
				{
					maskIndex = -3;
					maskColor = 124;
				}
				else if(mask == Masks.Shadow)
				{
					maskIndex = -4;
					maskColor = 131;
				}

				// Bild pixelweise durchgehen
				for(int i = 0; i < FIH.Width; i++)
				{
					for(int j = 0; j < FIH.Height; j++)
					{
						// Palettenindex abrufen
						int farbID = _frameInformationData[(int)frameID].CommandTable[j, i];

						// Je nach Masken Farben setzen
						if(farbID == maskIndex)
						{
							// Masken-Farbe übernehmen
							farbID = maskColor;
						}
						else
						{
							// Keine Maske, also weiß
							farbID = 255;
						}

						// Pixel übernehmen
						bmp[i, j] = (byte)farbID;
					}
				}
			}
			else // Spielerfarbe
			{
				// Bild pixelweise durchgehen
				for(int i = 0; i < FIH.Width; i++)
				{
					for(int j = 0; j < FIH.Height; j++)
					{
						// Palettenindex abrufen
						int farbID = _frameInformationData[(int)frameID].CommandTable[j, i];

						// Liegt keine Spielerfarbe vor?
						if(farbID < 16 || farbID > 23)
						{
							// Pixel weiß einfärben
							farbID = 255;
						}

						// Pixel übernehmen
						bmp[i, j] = (byte)farbID;
					}
				}
			}

			// Fertig, Bild speichern
			bmp.saveToFile(filename);
		}
Exemplo n.º 2
0
		/// <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.
		}