Archived
1
0

+ ClientSize adaption

+ more statistics and timing
* improved FastPixel with working code for odd row images
This commit is contained in:
Markus Birth 2009-01-30 01:36:46 +01:00
parent 7028323a80
commit fa5ad89d6b
5 changed files with 94 additions and 71 deletions

View File

@ -5,13 +5,13 @@ using System.Drawing.Imaging;
class FastPixel {
private byte[] rgbValues;
private BitmapData bmpData;
private IntPtr bmpPtr;
private bool locked = false;
private bool _isAlpha = false;
private Bitmap _bitmap;
private int _width;
private int _height;
private int bytesPerPixel;
public int Width {
get { return this._width; }
@ -37,6 +37,7 @@ class FastPixel {
this._isAlpha = (this.Bitmap.PixelFormat == (this.Bitmap.PixelFormat | PixelFormat.Alpha));
this._width = bitmap.Width;
this._height = bitmap.Height;
this.bytesPerPixel = (this._isAlpha)?4:3;
}
public void Lock() {
@ -45,16 +46,21 @@ class FastPixel {
Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
this.bmpData = this.Bitmap.LockBits(rect, ImageLockMode.ReadWrite, this.Bitmap.PixelFormat);
this.bmpPtr = this.bmpData.Scan0;
this.rgbValues = new byte[(this.Width * this.Height) * this.bytesPerPixel];
int bytes;
if (this.IsAlphaBitmap) {
bytes = (this.Width * this.Height) * 4;
} else {
bytes = (this.Width * this.Height) * 3;
unsafe {
byte* ptr= (byte*)this.bmpData.Scan0;
int offset = this.bmpData.Stride - this.bmpData.Width * this.bytesPerPixel;
for(int y = 0; y < this.Height; y++, ptr += offset) {
for(int x = 0; x < this.Width; x++, ptr += this.bytesPerPixel) {
int index = ((y * this.Width + x) * this.bytesPerPixel);
this.rgbValues[index] = ptr[0];
this.rgbValues[index+1] = ptr[1];
this.rgbValues[index+2] = ptr[2];
if (this.bytesPerPixel == 4) this.rgbValues[index+3] = ptr[3];
}
}
}
this.rgbValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(this.bmpPtr, rgbValues, 0, this.rgbValues.Length);
this.locked = true;
}
@ -63,8 +69,21 @@ class FastPixel {
throw new Exception("Bitmap not locked.");
// Copy the RGB values back to the bitmap;
if (setPixels)
System.Runtime.InteropServices.Marshal.Copy(this.rgbValues, 0, this.bmpPtr, this.rgbValues.Length);
if (setPixels) {
unsafe {
byte* ptr= (byte*)this.bmpData.Scan0;
int offset = this.bmpData.Stride - this.bmpData.Width * this.bytesPerPixel;
for(int y = 0; y < this.Height; y++, ptr += offset) {
for(int x = 0; x < this.Width; x++, ptr += this.bytesPerPixel) {
int index = ((y * this.Width + x) * this.bytesPerPixel);
ptr[0] = this.rgbValues[index];
ptr[1] = this.rgbValues[index+1];
ptr[2] = this.rgbValues[index+2];
if (this.bytesPerPixel == 4) ptr[3] = this.rgbValues[index+3];
}
}
}
}
// Unlock the bits.;
this.Bitmap.UnlockBits(bmpData);
@ -75,19 +94,11 @@ class FastPixel {
if (!this.locked)
throw new Exception("Bitmap not locked.");
if (this.IsAlphaBitmap) {
for (int index = 0; index < this.rgbValues.Length; index += 4) {
for (int index = 0; index < this.rgbValues.Length; index += this.bytesPerPixel) {
this.rgbValues[index] = colour.B;
this.rgbValues[index + 1] = colour.G;
this.rgbValues[index + 2] = colour.R;
this.rgbValues[index + 3] = colour.A;
}
} else {
for (int index = 0; index < this.rgbValues.Length; index += 3) {
this.rgbValues[index] = colour.B;
this.rgbValues[index + 1] = colour.G;
this.rgbValues[index + 2] = colour.R;
}
if (this.bytesPerPixel == 4) this.rgbValues[index + 3] = colour.A;
}
}
@ -99,18 +110,11 @@ class FastPixel {
if (!this.locked)
throw new Exception("Bitmap not locked.");
if (this.IsAlphaBitmap) {
int index = ((y * this.Width + x) * 4);
int index = ((y * this.Width + x) * this.bytesPerPixel);
this.rgbValues[index] = colour.B;
this.rgbValues[index + 1] = colour.G;
this.rgbValues[index + 2] = colour.R;
this.rgbValues[index + 3] = colour.A;
} else {
int index = ((y * this.Width + x) * 3);
this.rgbValues[index] = colour.B;
this.rgbValues[index + 1] = colour.G;
this.rgbValues[index + 2] = colour.R;
}
if (this.bytesPerPixel == 4) this.rgbValues[index + 3] = colour.A;
}
public Color GetPixel(Point location) {
@ -121,19 +125,14 @@ class FastPixel {
if (!this.locked)
throw new Exception("Bitmap not locked.");
if (this.IsAlphaBitmap) {
int index = ((y * this.Width + x) * 4);
int index = ((y * this.Width + x) * this.bytesPerPixel);
int b = this.rgbValues[index];
int g = this.rgbValues[index + 1];
int r = this.rgbValues[index + 2];
if (this.bytesPerPixel == 4) {
int a = this.rgbValues[index + 3];
return Color.FromArgb(a, r, g, b);
} else {
int index = ((y * this.Width + x) * 3);
int b = this.rgbValues[index];
int g = this.rgbValues[index + 1];
int r = this.rgbValues[index + 2];
}
return Color.FromArgb(r, g, b);
}
}
}

View File

@ -10,7 +10,7 @@ namespace vampi {
public class Output_GUI : Output {
const int statsHeight = 45;
double scale = 1;
int scale = 1;
Form f = new Form();
FastPixel fp;
Graphics fg;
@ -18,11 +18,8 @@ namespace vampi {
Bitmap stats;
public Output_GUI() {
field = new Bitmap(Settings.size, Settings.size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
stats = new Bitmap(300, Output_GUI.statsHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
fp = new FastPixel(field);
fg = Graphics.FromHwnd(f.Handle);
fg.InterpolationMode = InterpolationMode.NearestNeighbor;
this.field = new Bitmap(Settings.size, Settings.size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
this.stats = new Bitmap(f.ClientSize.Width, Output_GUI.statsHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
@ -38,9 +35,16 @@ namespace vampi {
g.Clear(Settings.guiColorEmpty);
g.Dispose();
if (Math.Min(f.ClientSize.Width, f.ClientSize.Height-Output_GUI.statsHeight) < Settings.size) {
f.ClientSize = new Size(Settings.size, Settings.size+Output_GUI.statsHeight);
}
fp = new FastPixel(field);
fg = Graphics.FromHwnd(f.Handle);
fg.InterpolationMode = InterpolationMode.NearestNeighbor;
fg.Clear(Color.White); // clear window background
calculateScale();
f.Show();
calculateScale();
}
~Output_GUI() {
@ -54,11 +58,13 @@ namespace vampi {
}
public void calculateScale() {
scale = (double)(Math.Min(f.ClientSize.Height - Output_GUI.statsHeight, f.ClientSize.Width) / Settings.size);
scale = (int)Math.Floor((double)Math.Min(f.ClientSize.Height - Output_GUI.statsHeight, f.ClientSize.Width) / (double)Settings.size);
if (scale<1) scale = 1;
}
public void FormResize(object sender, EventArgs e) {
calculateScale();
stats = new Bitmap(f.ClientSize.Width, Output_GUI.statsHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
fg = Graphics.FromHwnd(f.Handle);
fg.InterpolationMode = InterpolationMode.NearestNeighbor;
fg.Clear(Color.White);
@ -66,7 +72,7 @@ namespace vampi {
public override void doOutput() {
this.drawGameMap();
if (Program.AnzSimDone % 2 == 0) this.drawStatistics();
this.drawStatistics();
Application.DoEvents();
}
@ -123,19 +129,22 @@ namespace vampi {
}
}
fp.Unlock(true);
fg.DrawImage(this.field, 0, Output_GUI.statsHeight, (int)(Settings.size * this.scale), (int)(Settings.size * this.scale));
fg.DrawImage(this.field, 0, Output_GUI.statsHeight, Settings.size * this.scale, Settings.size * this.scale);
f.Update();
}
public void drawStatistics() {
if (!f.Visible) this.requestAbort = true;
Graphics g = Graphics.FromImage(this.stats);
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
g.Clear(Color.White);
int lineSpc = 10;
int Ecount = Einwohner.Count; // sflaeche.countTypeOccurrences(Typliste.EINWOHNER);
int Vcount = Vampir.Count; // sflaeche.countTypeOccurrences(Typliste.VAMPIR);
g.DrawString(String.Format("Steps Done: {0:D5}", Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 0);
g.DrawString(String.Format("Step: {0:D5}", Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 0);
g.DrawString(String.Format("T{0:N} = {1:D}/sec", Program.lastCalcTime+Program.lastStatsTime, (int)Math.Floor(1000/(Program.lastCalcTime+Program.lastStatsTime))), Settings.guiFont, Settings.guiFontBrush, 100, 0);
g.DrawString(String.Format("C{0:N} D{1:N}", Program.lastCalcTime, Program.lastStatsTime), Settings.guiFont, Settings.guiFontBrush, 200, 0);
g.DrawString(String.Format(String.Format("Einwohner: {0:D} / Vampire: {1:D}", Ecount, Vcount), Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 1*lineSpc);
g.DrawString(String.Format(String.Format("Verhältnis Vampire/Einwohner = 1/{0:N5}", (double)Ecount / Vcount), Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 2*lineSpc);
g.DrawString(String.Format(String.Format("Bedeckung: {0:N5} %", (double)(Ecount + Vcount) / (Settings.size*Settings.size) * 100), Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 3*lineSpc);

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Diagnostics;
namespace vampi {
class Program {
@ -13,16 +14,27 @@ namespace vampi {
}
public static Random random = new Random();
public static Spielflaeche sflaeche = new Spielflaeche(Settings.size, Settings.coveragePercent, Settings.vampireRatio);
public static double lastCalcTime = 0;
public static double lastStatsTime = 0;
static void Main(string[] args) {
Output output = new Output_GUI();
Stopwatch sw = new Stopwatch();
for (anz_sim_done=0; anz_sim_done < anz_sim; anz_sim_done++) {
if (anz_sim_done % Settings.drawEveryNthStep == 0) {
sw.Reset();
sw.Start();
output.doOutput();
sw.Stop();
Program.lastStatsTime = sw.Elapsed.TotalMilliseconds;
}
if (output.requestAbort) break;
sw.Reset();
sw.Start();
sflaeche.simulateStep();
sw.Stop();
Program.lastCalcTime = sw.Elapsed.TotalMilliseconds;
}
}//Main
}//class

View File

@ -3,7 +3,7 @@ using System.Drawing;
namespace vampi {
public abstract class Settings {
public const int size = 43;
public const int size = 500;
public const int coveragePercent = 77;
public const int vampireRatio = 3;
public const int drawEveryNthStep = 1;
@ -13,10 +13,13 @@ namespace vampi {
public const ConsoleColor colorVampire = ConsoleColor.Red;
public const ConsoleColor colorEmpty = ConsoleColor.Gray;
public static Color[] guiColorHuman = {Color.FromArgb(0, 60, 0), Color.LimeGreen};
/* public static Color guiColorHuman = Color.LimeGreen;
public static Color guiColorHumanInfected = Color.DarkMagenta;
public static Color guiColorVampire = Color.Red;
*/ public static Color[] guiColorHuman = {Color.FromArgb(0, 60, 0), Color.LimeGreen};
public static Color[] guiColorHumanInfected = {Color.FromArgb(60, 0, 60), Color.DarkMagenta};
public static Color[] guiColorVampire = {Color.FromArgb(60, 0, 0), Color.Red};
public static Color guiColorEmpty = Color.Gray;
public static Color guiColorEmpty = Color.Silver;
public static Font guiFont = new Font("sans-serif", 8);
public static Brush guiFontBrush = Brushes.Black;

View File

@ -24,7 +24,7 @@
<OutputType>Exe</OutputType>
<AssemblyName>vampi</AssemblyName>
<RootNamespace>vampi</RootNamespace>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<ApplicationIcon>.</ApplicationIcon>
</PropertyGroup>
@ -39,7 +39,7 @@
<AssemblyName>vampi</AssemblyName>
<DebugSymbols>true</DebugSymbols>
<RootNamespace>vampi</RootNamespace>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<ApplicationIcon>.</ApplicationIcon>
</PropertyGroup>