Drawing a border on an image - c#

I'm currently trying to make a mask generator to generate polygons for images. Here's my code.
Bitmap bmp = new Bitmap(file);
int w = bmp.Width;
int h = bmp.Height;
List<Point> vertices = new List<Point>();
for (int y=0; y<h; y++)
{
bool rowbegin = false;
for (int x=0; x<w; x++)
{
Color c = bmp.GetPixel(x, y);
if (!rowbegin)
{
// Check for a non alpha color
if (c.A != Color.Transparent.A)
{
rowbegin = true;
// This is the first point in the row
vertices.Add(new Point(x, y));
}
} else {
// Check for an alpha color
if (c.A == Color.Transparent.A)
{
// The previous pixel is the last point in the row
vertices.Add(new Point(x-1, y));
rowbegin = false;
}
}
}
}
// Convert to an array of points
Point[] polygon = vertices.ToArray();
Graphics g = Graphics.FromImage(bmp);
g.DrawPolygon(Pens.LawnGreen, polygon);
g.Dispose();
But I'm getting wrong output.
The required.
What I want is also the gaps between the characters to be empty. Also why DrawPolygon is filling it?
Thanks.

Do you trying something like this:i hope my code help you:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(#"C:\Users\Ali\Desktop\1.png");
int w = bmp.Width;
int h = bmp.Height;
Lst_Data lastpointcolor = new Lst_Data() ;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
Color c = bmp.GetPixel(x, y);
if (c.A != Color.Transparent.A)
{
if (lastpointcolor.color.A == Color.Transparent.A)
{
bmp.SetPixel(lastpointcolor.point.X, lastpointcolor.point.Y, Color.Red);
}
}
lastpointcolor = new Lst_Data() { point = new Point(x, y), color = bmp.GetPixel(x, y) };
}
}
for (int y = h-1; y > 0; y--)
{
for (int x = w-1; x > 0; x--)
{
Color c = bmp.GetPixel(x, y);
if (c.A != Color.Transparent.A)
{
if (lastpointcolor.color.A == Color.Transparent.A)
{
bmp.SetPixel(lastpointcolor.point.X, lastpointcolor.point.Y, Color.Red);
}
}
lastpointcolor = new Lst_Data() { point = new Point(x, y), color = bmp.GetPixel(x, y) };
}
}
pictureBox1.Image = bmp;
}
}
public struct Lst_Data
{
public Point point;
public Color color;
}
}
Edited:
And Another idea i have for you:D
Make a mask for original image with the same size and do this:
Bitmap orginal = new Bitmap(#"C:\Users\Ali\Desktop\orginal.png");
Bitmap mask = new Bitmap(#"C:\Users\Ali\Desktop\mask.png");
for (int i = 0; i < orginal.Width; i++)
{
for (int j = 0; j < orginal.Height; j++)
{
if (orginal.GetPixel(i, j).A == Color.Transparent.A)
{
mask.SetPixel(i, j, Color.Transparent);
}
}
}
Bitmap bitmap = new Bitmap(mask, mask.Height, mask.Height);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.DrawImage(mask, 0, 0);
g.DrawImage(orginal,0,0);
}
pictureBox1.Image = bitmap;
Result:

Related

How to get color from specific area in an Image in C#

I am trying to get color from specific area in an Image.
Assume that , this is image , and I want to get color inside image.(the result should be red of the above image) This color may be different position in image. Because I don't know exact position of color where it starting, so I can't get exact result.
Until now, I cropped image giving manually position of x and y, and then cropped image and I got average color of cropped image. But I know , this is not exact color.
What I tried :
private RgbDto GetRGBvalueCroppedImage(Image croppedImage)
{
var avgRgb = new RgbDto();
var bm = new Bitmap(croppedImage);
BitmapData srcData = bm.LockBits(
new Rectangle(0, 0, bm.Width, bm.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
int stride = srcData.Stride;
IntPtr Scan0 = srcData.Scan0;
long[] totals = new long[] { 0, 0, 0 };
int width = bm.Width;
int height = bm.Height;
unsafe
{
byte* p = (byte*)(void*)Scan0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
for (int color = 0; color < 3; color++)
{
int idx = (y * stride) + x * 4 + color;
totals[color] += p[idx];
}
}
}
}
avgRgb.avgB = (int)totals[0] / (width * height);
avgRgb.avgG = (int)totals[1] / (width * height);
avgRgb.avgR = (int)totals[2] / (width * height);
return avgRgb;
}
How can I get exact position to crop? May be I can convert image to byte array, then I can find different color and take position of it and then crop. But I have no clue how do this.
You can use something this extension method to get dominant color in a region of an image in case they are not all the same
public static Color GetDominantColor(this Bitmap bitmap, int startX, int startY, int width, int height) {
var maxWidth = bitmap.Width;
var maxHeight = bitmap.Height;
//TODO: validate the region being requested
//Used for tally
int r = 0;
int g = 0;
int b = 0;
int totalPixels = 0;
for (int x = startX; x < (startX + width); x++) {
for (int y = startY; y < (startY + height); y++) {
Color c = bitmap.GetPixel(x, y);
r += Convert.ToInt32(c.R);
g += Convert.ToInt32(c.G);
b += Convert.ToInt32(c.B);
totalPixels++;
}
}
r /= totalPixels;
g /= totalPixels;
b /= totalPixels;
Color color = Color.FromArgb(255, (byte)r, (byte)g, (byte)b);
return color;
}
You can then use it like
Color pixelColor = myBitmap.GetDominantColor(xPixel, yPixel, 5, 5);
there is room for improvement, like using a Point and Size, or even a Rectangle
public static Color GetDominantColor(this Bitmap bitmap, Rectangle area) {
return bitmap.GetDominantColor(area.X, area.Y, area.Width, area.Height);
}
and following this link:
https://www.c-sharpcorner.com/UploadFile/0f68f2/color-detecting-in-an-image-in-C-Sharp/
If you want to get the image colors, you don't need to do any cropping at all. Just loop on image pixels and find the two different colors. (Assuming that you already know the image will have exactly 2 colors, as you said in comments). I've written a small function that will do that. However, I didn't test it in an IDE, so expect some small mistakes:
private static Color[] GetColors(Image image)
{
var bmp = new Bitmap(image);
var colors = new Color[2];
colors[0] = bmp.GetPixel(0, 0);
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
Color c = bmp.GetPixel(i, j);
if (c == colors[0]) continue;
colors[1] = c;
return colors;
}
}
return colors;
}

How to Draw a Outline (Edge ) of Irregular Shape using c#

enter image description here
Please give me a solution about that I have ti find out many site's but i did not get any solution.
thankyou
private void Form1_Load(object sender, EventArgs e)
{
Bitmap bitmap = new Bitmap(#"D:\shapes_Images\4.png");
pictureBox1.Image = bitmap;
image = bitmap ;
}
Bitmap image;
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
//Create a path and add lines.
List<Point> outlinePoints = new List<Point>();
BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] originalBytes = new byte[image.Width * image.Height * 4];
Marshal.Copy(bitmapData.Scan0, originalBytes, 0, originalBytes.Length);
//find non-transparent pixels visible from the top of the image
for (int x = 0; x < bitmapData.Width; x++)
{
for (int y = 0; y < bitmapData.Height; y++)
{
byte alpha = originalBytes[y * bitmapData.Stride + 4 * x + 3];
if (alpha != 0)
{
Point p = new Point(x, y);
if (!ContainsPoint(outlinePoints, p))
outlinePoints.Add(p);
break;
}
}
}
//helper variable for storing position of the last pixel visible from both sides
//or last inserted pixel
int? lastInsertedPosition = null;
//find non-transparent pixels visible from the right side of the image
for (int y = 0; y < bitmapData.Height; y++)
{
for (int x = bitmapData.Width - 1; x >= 0; x--)
{
byte alpha = originalBytes[y * bitmapData.Stride + 4 * x + 3];
if (alpha != 0)
{
Point p = new Point(x, y);
if (!ContainsPoint(outlinePoints, p))
{
if (lastInsertedPosition.HasValue)
{
outlinePoints.Insert(lastInsertedPosition.Value + 1, p);
lastInsertedPosition += 1;
}
else
{
outlinePoints.Add(p);
}
}
else
{
//save last common pixel from visible from more than one sides
lastInsertedPosition = outlinePoints.IndexOf(p);
}
break;
}
}
}
lastInsertedPosition = null;
//find non-transparent pixels visible from the bottom of the image
for (int x = bitmapData.Width - 1; x >= 0; x--)
{
for (int y = bitmapData.Height - 1; y >= 0; y--)
{
byte alpha = originalBytes[y * bitmapData.Stride + 4 * x + 3];
if (alpha != 0)
{
Point p = new Point(x, y);
if (!ContainsPoint(outlinePoints, p))
{
if (lastInsertedPosition.HasValue)
{
outlinePoints.Insert(lastInsertedPosition.Value + 1, p);
lastInsertedPosition += 1;
}
else
{
outlinePoints.Add(p);
}
}
else
{
//save last common pixel from visible from more than one sides
lastInsertedPosition = outlinePoints.IndexOf(p);
}
break;
}
}
}
lastInsertedPosition = null;
//find non-transparent pixels visible from the left side of the image
for (int y = bitmapData.Height - 1; y >= 0; y--)
{
for (int x = 0; x < bitmapData.Width; x++)
{
byte alpha = originalBytes[y * bitmapData.Stride + 4 * x + 3];
if (alpha != 0)
{
Point p = new Point(x, y);
if (!ContainsPoint(outlinePoints, p))
{
if (lastInsertedPosition.HasValue)
{
outlinePoints.Insert(lastInsertedPosition.Value + 1, p);
lastInsertedPosition += 1;
}
else
{
outlinePoints.Add(p);
}
}
else
{
//save last common pixel from visible from more than one sides
lastInsertedPosition = outlinePoints.IndexOf(p);
}
break;
}
}
}
// Added to close the loop
outlinePoints.Add(outlinePoints[0]);
image.UnlockBits(bitmapData);
GraphicsPath myPath = new GraphicsPath();
myPath.AddLines(outlinePoints.ToArray());
// return outlinePoints.ToArray();
PathGradientBrush pthGrBrush = new PathGradientBrush(outlinePoints.ToArray());
//foreach (Point p in outlinePoints.ToArray())
//{
// //Point p1 = p;
//}
Color[] colors = { Color.Red , Color.Green };
pthGrBrush.SurroundColors = colors;
pthGrBrush.CenterColor = Color.Red;
Blend blend = new Blend();
// blend.Factors = new float[] { 1, 0 };
blend.Positions = new float[] { 0, 0.25f };
pthGrBrush.Blend = blend;
// LinearGradientBrush linGrBrush = new LinearGradientBrush(new Point(0, 10),new Point(200, 10),Color.FromArgb(255, 255, 0, 0),Color.FromArgb(255, 0, 0, 255));
e.Graphics.FillPath(pthGrBrush, myPath);
// Pen myPen = new Pen(Color.Black, 6);
// e.Graphics.DrawPath(pthGrBrush, myPath);
}

C# Create Grid For Painting Pixels and Rendering Text

I'm trying to find the best path to go about creating a pixel "grid" that would allow basic paint functions such as coloring the pixels by clicking and moving the mouse, selecting an area for copying, pasting, or moving, or using other graphics functions in order to render text or shapes to the pixels. I've looked at a few samples, such as this example which overrides the panel control and has a similar look to what I'm trying to achieve, but the painting is slow and it seems like it wouldn't perform well for drawing with the mouse. Is there a control, or one that I could override, that would allow for the functionality that I'm looking for?
Here's a sample of what the above example looks like:
Sample pixel grid
And the code I adapted from the above example:
public class Pixel
{
public Rectangle Bounds { get; set; }
public bool IsOn { get; set; }
public bool IsSelected { get; set; }
}
public class PixelGridControl : Panel
{
public int Columns = 99;
public int Rows = 63;
private readonly Pixel[,] pixels;
public PixelGridControl()
{
this.DoubleBuffered = true;
this.ResizeRedraw = true;
// initialize pixel grid:
pixels = new Pixel[Columns, Rows];
for (int y = 0; y < Rows; ++y)
{
for (int x = 0; x < Columns; ++x)
{
pixels[x, y] = new Pixel();
}
}
}
// adjust each column and row to fit entire client area:
protected override void OnResize(EventArgs e)
{
int top = 0;
for (int y = 0; y < Rows; ++y)
{
int left = 0;
int height = (this.ClientSize.Height - top) / (Rows - y);
for (int x = 0; x < Columns; ++x)
{
int width = (this.ClientSize.Width - left) / (Columns - x);
pixels[x, y].Bounds = new Rectangle(left, top, width, height);
left += width;
}
top += height;
}
base.OnResize(e);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
for (int y = 0; y < Rows; ++y)
{
for (int x = 0; x < Columns; ++x)
{
if (pixels[x, y].IsOn)
{
e.Graphics.FillRectangle(Brushes.Gold, pixels[x, y].Bounds);
}
else
{
ControlPaint.DrawButton(e.Graphics, pixels[x, y].Bounds,
ButtonState.Normal);
}
}
}
base.OnPaint(e);
}
// determine which button the user pressed:
protected override void OnMouseDown(MouseEventArgs e)
{
for (int y = 0; y < Rows; ++y)
{
for (int x = 0; x < Columns; ++x)
{
if (pixels[x, y].Bounds.Contains(e.Location))
{
pixels[x, y].IsOn = true;
this.Invalidate();
MessageBox.Show(
string.Format("You pressed on button ({0}, {1})",
x.ToString(), y.ToString())
);
}
}
}
base.OnMouseDown(e);
}
}
Here is an minimal example that uses a bitmap as the pixel storage and displays the enlarged pixels in a panel for editing.
You can use it by setting it up to edit the pixels in an Picturebox pBox_Target.Image, maybe like this:
public Form1()
{
InitializeComponent();
..
..
pixelEditor1.APBox = pBox_Target;
pixelEditor1.TgtBitmap = (Bitmap)pixelEditor1.APBox.Image;
..
}
The editor exposes the pixel size and the color to draw with among a minimum of properties..
all in all it is slightly over 100 lines - of course it is meant to be expanded!
Here it is at work:
class PixelEditor : Panel
{
public Color DrawColor { get; set; }
public Color GridColor { get; set; }
int pixelSize = 8;
public int PixelSize
{
get { return pixelSize; }
set
{
pixelSize = value;
Invalidate();
}
}
public Bitmap TgtBitmap { get; set; }
public Point TgtMousePos { get; set; }
Point lastPoint = Point.Empty;
PictureBox aPBox = null;
public PictureBox APBox {
get { return aPBox; }
set
{
if (value == null) return;
aPBox = value;
aPBox.MouseClick -=APBox_MouseClick;
aPBox.MouseClick +=APBox_MouseClick;
}
}
private void APBox_MouseClick(object sender, MouseEventArgs e)
{
TgtMousePos = e.Location;
Invalidate();
}
public PixelEditor()
{
DoubleBuffered = true;
BackColor = Color.White;
GridColor = Color.DimGray;
DrawColor = Color.Red;
PixelSize = 10;
TgtMousePos = Point.Empty;
if (APBox != null && APBox.Image != null)
TgtBitmap = (Bitmap)APBox.Image;
MouseClick +=PixelEditor_MouseClick;
MouseMove +=PixelEditor_MouseMove;
Paint +=PixelEditor_Paint;
}
private void PixelEditor_Paint(object sender, PaintEventArgs e)
{
if (DesignMode) return;
Graphics g = e.Graphics;
int cols = ClientSize.Width / PixelSize;
int rows = ClientSize.Height / PixelSize;
if (TgtMousePos.X < 0 || TgtMousePos.Y < 0) return;
for (int x = 0; x < cols; x++)
for (int y = 0; y < rows; y++)
{
int sx = TgtMousePos.X + x;
int sy = TgtMousePos.Y + y;
if (sx > TgtBitmap.Width || sy > TgtBitmap.Height) continue;
Color col = TgtBitmap.GetPixel(sx, sy);
using (SolidBrush b = new SolidBrush(col))
using (Pen p = new Pen(GridColor))
{
Rectangle rect = new Rectangle(x * PixelSize, y * PixelSize,
PixelSize, PixelSize);
g.FillRectangle(b, rect);
g.DrawRectangle(p, rect);
}
}
}
private void PixelEditor_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
int x = TgtMousePos.X + e.X / PixelSize;
int y = TgtMousePos.Y + e.Y / PixelSize;
if (new Point(x, y) == lastPoint) return;
Bitmap bmp = (Bitmap)APBox.Image;
bmp.SetPixel(x,y, DrawColor);
APBox.Image = bmp;
Invalidate();
lastPoint = new Point(x, y);
}
private void PixelEditor_MouseClick(object sender, MouseEventArgs e)
{
int x = TgtMousePos.X + e.X / PixelSize;
int y = TgtMousePos.Y + e.Y / PixelSize;
Bitmap bmp = (Bitmap)APBox.Image;
bmp.SetPixel(x,y, DrawColor);
APBox.Image = bmp;
Invalidate();
}
}
Note that this solution neither uses a special pixel class nor makes any provisions for selecting sets of pixels. To implement most selection tools you can use a GraphicsPath; you can the e.g. fill the path or loop over its bounds using IsVisible to enumerate the pixels in the path..
Update: Instead of a Panel, which is a Container control and not really meant to draw onto you can use a Picturebox or a Label (with Autosize=false); both have the DoubleBuffered property turned on out of the box and support drawing better than Panels do.

compare one pixel with all pixels

i want to compare pixel of an image with all pixel of second image and then next pixel with all pixel of second image;
i am using this code in which i am comparing pixel (converted in byte) one pixel of one image with second pixel of second but i do not want this approach. Please reply fast.
Thanks in advance.
public static double GetDifferentPercentageSneller(ref Bitmap bmp1, ref Bitmap bmp2)
{
//if (bmp1 == null || bmp2 == null)
// return 100.0;
//if (bmp1.Size != bmp2.Size)
// return 100.0;
//if (bmp1.PixelFormat != bmp2.PixelFormat)
// return 100.0;
int iMismatch = 0;
int iMatch = 0;
unsafe
{
BitmapData data1 = bmp1.LockBits(new Rectangle(0, 0, bmp1.Width, bmp1.Height), ImageLockMode.ReadOnly, bmp1.PixelFormat);
BitmapData data2 = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height), ImageLockMode.ReadOnly, bmp2.PixelFormat);
int pixelBytes = 0;
switch (data1.PixelFormat)
{
case PixelFormat.Format32bppArgb:
pixelBytes = 4;
break;
case PixelFormat.Format24bppRgb:
pixelBytes = 3;
break;
default:
throw new Exception("Bitmap format not supported");
}
int paddingBytes = data1.Stride % pixelBytes;
byte* location1 = (byte*)data1.Scan0;
byte* location2 = (byte*)data2.Scan0;
for (int y = 0; y < data1.Height; ++y)
{
for (int x = 0; x < data1.Width; ++x)
{
if (*location1 == *location2)
{
iMatch++;
}
else
{
iMismatch++;
}
location1 += pixelBytes;
location2 += pixelBytes;
}
location1 += paddingBytes;
location2 += paddingBytes;
}
bmp1.UnlockBits(data1);
bmp2.UnlockBits(data2);
}
double percent = (double)iMatch/ (double)(iMismatch + iMatch);
return percent * 100.0;
}
You have to always compare the LARGER image (both x, y) with the SMALLER. Although I don't know what your are exactly after, you can do it simply like this.
BitmapImage Image1 = new BitmapImage(ImageStream);
BitmapImage Image2 = new BitmapImage(ImageStream);
int X = Image1.Width > Image2.Width ? Image2.Width : Image1.Width;
int Y = Image1.Hieght > Image2.Height ? Image2.Heigth : Image1.Height;
for(int x = 0; x < X; x++){
for(int y = 0; y < Y; y++){
Color color1 = Image1.GetPixel(x, y);
Color color2 = Image2.GetPixel(x, y);
// Do comparison here
}
}

Can't work out why the square won't animate across the grid

I cannot for the life of me work out how to get the block that is supposed to be drawn with every loop through the array of "Arxl" objects to animate across the grid.
Any suggestions would be really appreciated, not looking for someone to complete the code for me. just a fresh set of eyes.
public partial class Game : Form
{
//attributes
private Bitmap _grid;
private Arxl[,] _cartesianGrid;
private int _arxlAmount;
const int ARXL = 4;
public Game()
{
InitializeComponent();
_arxlAmount = (gridPictureBox.Height / ARXL);//in case height/arxl is not an even number?
_cartesianGrid = new Arxl[_arxlAmount, _arxlAmount];
_grid = new Bitmap(gridPictureBox.Width, gridPictureBox.Height);
int x;
int y;
for (x = 0; x < _arxlAmount; x++)
{
for (y = 0; y < _arxlAmount; y++)
{
_cartesianGrid[x, y] = new Arxl();
}
}
SetSeed(_cartesianGrid);
}
private void SetSeed(Arxl[,] cartesianGrid)
{
_cartesianGrid[1, 1].Active = true;
}
private void DrawArxl(Bitmap _grid, Arxl[,] cartesianGrid,int arxlAmount)
{
int x, y;
x=0;
y=0;
Graphics graphics = Graphics.FromImage(_grid);
graphics.Clear(Color.White);
for (x = 1; x < arxlAmount;x++ )
{
for (y = 1; y < arxlAmount; y++)
{
if (cartesianGrid[x, y].Active==true)
{
cartesianGrid[x, y].Area = new Rectangle(x * ARXL, y * ARXL, ARXL, ARXL);
graphics.FillRectangle(Brushes.Black, cartesianGrid[x, y].Area);
}
else if(cartesianGrid[x,y].Active==false)
{
Pen newPen=new Pen(Color.Black);
cartesianGrid[x, y].Area = new Rectangle(x * ARXL, y * ARXL, ARXL, ARXL);
graphics.DrawRectangle(newPen,cartesianGrid[x, y].Area);
newPen.Dispose();
}
}
}
}
private void timer_Tick(object sender, EventArgs e)
{
//GameOfLife(_cartesianGrid, _arxlAmount);
ScrollBlock(_cartesianGrid, _arxlAmount);
DrawArxl(_grid, _cartesianGrid, _arxlAmount);
gridPictureBox.Image = _grid;
}
private void ScrollBlock(Arxl[,] cartesianGrid, int arxlAmount)
{
int x = 0;
int y = 0;
for (x = 0; x < arxlAmount; x++)
{
for (y = 0; y < arxlAmount; y++)
{
if (_cartesianGrid[x, y].Active == true)
{
if (x>=0)
{
if (x == (arxlAmount-1))
{
_cartesianGrid[x, y].Active = false;
_cartesianGrid[1, y].Active = true;
}
else if(x<(arxlAmount-1))
{
_cartesianGrid[x, y].Active = false;
_cartesianGrid[x+1, y].Active = true;
}
}
}
}
}
}
According to a comment in your code, you want to program the life game. It will not work, if you change the cells in place, because you will have to compute the new state from the unchanged old state. Therefore, you will need to have two game boards, one with the current state and one with the new state. Instead of creating new board all the time, it is better to have two boards and to swap them. In addition, there is no point in storing the Rectangles in the board. Therefore, I declare the boards as Boolean matrix.
const int CellSize = 4;
private int _boardSize;
private bool[,] _activeBoard, _inactiveBoard;
Bitmap _grid;
The form constructor is changed like this
public Game()
{
InitializeComponent();
_boardSize = Math.Min(gridPictureBox.Width, gridPictureBox.Height) / CellSize;
_grid = new Bitmap(gridPictureBox.Width, gridPictureBox.Height);
_activeBoard = new bool[_boardSize, _boardSize];
_inactiveBoard = new bool[_boardSize, _boardSize];
SetSeed();
}
We initialize the game like this (as an example)
private void SetSeed()
{
_activeBoard[0, 0] = true;
_activeBoard[7, 4] = true;
DrawGrid();
}
The timer tick does this
ScrollBlock();
DrawGrid();
The logic in ScrollBlock is completely new. We look at the state on the _activeBoard and set the state of _inactiveBoard. Then we swap the two boards.
private void ScrollBlock()
{
for (int x = 0; x < _boardSize; x++) {
for (int y = 0; y < _boardSize; y++) {
if (_activeBoard[x, y]) {
_activeBoard[x, y] = false;
int newX = x + 1;
int newY = y;
if (newX == _boardSize) {
newX = 0;
newY = (newY + 1) % _boardSize;
}
_inactiveBoard[newX, newY] = true;
}
}
}
SwapBoards();
}
The boards are simply swapped like this
private void SwapBoards()
{
bool[,] tmp = _activeBoard;
_activeBoard = _inactiveBoard;
_inactiveBoard = tmp;
}
And finally DrawGrid draws the _activeBoard
private void DrawGrid()
{
Graphics graphics = Graphics.FromImage(_grid);
graphics.Clear(Color.White);
for (int x = 0; x < _boardSize; x++) {
for (int y = 0; y < _boardSize; y++) {
var rect = new Rectangle(x * CellSize, y * CellSize, CellSize, CellSize);
if (_activeBoard[x, y]) {
graphics.FillRectangle(Brushes.Black, rect);
} else {
graphics.DrawRectangle(Pens.Black, rect);
}
}
}
gridPictureBox.Image = _grid;
}
I've spotted your problem.
The problem is that you're updating a cell position (moving it to the right in this particular initial state), but the next iteration in the for loop finds the updated state from the previous iteration, so it updates the cell again, and again, and when the cycle stops, the cell was scrolled over to its initial cell position!, with no repainting in between.
I'm modifying your code to add an UpdateList that will turn on cells that need to be ON after the grid scan has finished to avoid updating the same "active dot" more than once. This should show a moving dot from left to right.
private void ScrollBlock(Arxl[,] cartesianGrid, int arxlAmount) {
int x = 0;
int y = 0;
List<Point> updateList = new List<Point>();
for( x = 0; x < arxlAmount; x++ ) {
for( y = 0; y < arxlAmount; y++ ) {
if( _cartesianGrid[x, y].Active == true ) {
if( x >= 0 ) {
if( x == (arxlAmount - 1) ) {
_cartesianGrid[x, y].Active = false;
//_cartesianGrid[1, y].Active = true;
updateList.Add(new Point(1, y));
} else if( x < (arxlAmount - 1) ) {
_cartesianGrid[x, y].Active = false;
//_cartesianGrid[x + 1, y].Active = true;
updateList.Add(new Point(x + 1, y));
}
}
}
}
}
foreach( var pt in updateList ) {
_cartesianGrid[pt.X, pt.Y].Active = true;
}
}
In your timer try calling gridPictureBox.Invalidate() after you assign the image to the picturebox. This will force the picturebox to redraw itself.

Categories