Plasma effect in WinForms, how to create continous loop - c#

I'm trying to create some simple graphics ("plasma" effect) with C# and Winforms.
I have two classes in my code, (main)Form1 and Plasmadraw.
In Plasmadraw I have following setup:
class Plasmadraw
{
int y;
int x;
double i;
double pii = 3.1415;
public void Draw(Graphics gfx, int addition)
{
for (int i = 0; i < 23040; i++)
{
x = x + 10;
if (x == 1920)
{
x = 0;
y = y + 10;
}
if (y == 1200)
{
y = 0;
}
double v = Math.Sin((x * 0.5) + i * 0.001 * addition);
double c = v * pii;
double d = c + (2 * pii / 3);
double f = c + (6 * pii / 3);
double r = 255 * Math.Abs(Math.Sin(c));
double g = 255 * Math.Abs(Math.Sin(d));
double b = 255 * Math.Abs(Math.Sin(f));
int r1 = (int)r;
int g1 = (int)g;
int b1 = (int)b;
Color e = Color.FromArgb(r1, g1, b1);
SolidBrush brush = new SolidBrush(e);
Rectangle rect = new Rectangle(x, y, 10, 10);
gfx.FillRectangle(brush, rect);
}
}
}
and then in Form1 I have Paint event:
private void Form1_Paint(object sender, PaintEventArgs e)
{
Plasmadraw plasmaeffect = new Plasmadraw();
for (int a = 0; a < 30; a++)
{
plasmaeffect.Draw(e.Graphics, a);
Invalidate();
}
Is this somehow completely wrong way to build the logic ? I've managed to create some graphics effects (moving sprites etc.) by creating a list and then running through the list with Foreach in Paint event (& Invalidate()). However, I'd like to learn some new way to do things, rather than copying the old way.

Related

Remove gray from the photo c# windows forms

I want to remove grayness from the picture in pictureBox1, as in the first photo below. The second photo shows the formulas that can be used to do this. I wrote an approximate code, but the compiler throws an error, that variables red1, green1 and blue1 cannot be written to Color newPixel due to type incompatibility. Please help me fixing my code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void pictureBox1_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Title = "Відкрити зображення";
dlg.Filter = "jpg files (*.jpg)|*.jpg|All filles (*.*)|*.*";
if (dlg.ShowDialog() == DialogResult.OK)
{
pictureBox1.Image = new Bitmap(dlg.OpenFile());
pictureBox1.Height = pictureBox1.Image.Height;
pictureBox1.Width = pictureBox1.Image.Width;
}
dlg.Dispose();
label1.Visible = false;
}
private void button1_Click(object sender, EventArgs e)
{
Bitmap input = new Bitmap(pictureBox1.Image);
Bitmap output = new Bitmap(input.Width, input.Height);
int[] red = new int[256];
int[] green = new int[256];
int[] blue = new int[256];
for (int x = 0; x < input.Width; x++)
{
for (int y = 0; y < input.Height; y++)
{
Color pixel = ((Bitmap)pictureBox1.Image).GetPixel(x, y);
red[pixel.R]++;
green[pixel.G]++;
blue[pixel.B]++;
double Ri = red.Average();
double Gi = green.Average();
double Bi = blue.Average();
double Avg = (Ri+Bi+Gi)/3;
double red1 = red (Avg/Ri);
double green1 = green(Avg / Gi);
double blue1 = blue(Avg / Bi);
Color newPixel = ((Color)red1| (Color)green1 | (Color)blue1);
output.SetPixel(x, y, Color.((int)newPixel));
}
}
pictureBox2.Image = output;
}
}
}
You should use Color.FromArgb() to create the new color. However, this method expects 3 int as input and not double, so you need to convert your doubles to integers.
Simple type cast - (int)someDouble
This solution will simply remove any decimals from the double value (1.9 => 1):
double red1 = 123.45;
double green1 = 12.345;
double blue1 = 234.56;
Color newPixel = Color.FromArgb((int)red1, (int)green1, (int)blue1);
// R=123, G=12, B=234
Math.Round(someDouble)
This solution will round the double value to the nearest integer (1.5 => 2 and 1.49 => 1):
int red1 = (int)Math.Round(123.45);
int green1 = (int)Math.Round(12.345);
int blue1 = (int)Math.Round(234.56);
Color newPixel = Color.FromArgb(red1, green1, blue1);
// R=123, G=12, B=235
You misinterpreted the formula. N in the formula specifies the total number of the pixels in the image. The overlined letters means the average channel value over the image. These variable should be the type of double. I called them redAverage, greenAverage and blueAverage, respectively. And as you
already know, Avg is the average of these variables. Finally, R', G', B' are the new channel values calculated using the old values.
using System.Drawing.Imaging;
namespace Convert2Gray
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private Bitmap m_inputImage;
private Bitmap m_outputImage;
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
m_inputImage = (Bitmap)Image.FromFile("sample.png");
m_outputImage = new Bitmap(m_inputImage.Width, m_inputImage.Height, m_inputImage.PixelFormat);
pictureBox1.Image = m_inputImage;
pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
DoConversion();
pictureBox2.Image = m_outputImage;
pictureBox2.SizeMode = PictureBoxSizeMode.AutoSize;
}
private unsafe void DoConversion()
{
BitmapData inputBitmapData = m_inputImage.LockBits(new Rectangle(0, 0, m_inputImage.Width, m_inputImage.Height), ImageLockMode.ReadWrite, m_inputImage.PixelFormat);
BitmapData outputBitmapData = m_outputImage.LockBits(new Rectangle(0, 0, m_outputImage.Width, m_outputImage.Height), ImageLockMode.ReadWrite, m_outputImage.PixelFormat);
byte* inputScan0 = (byte*)inputBitmapData.Scan0;
byte* outputScan0 = (byte*)outputBitmapData.Scan0;
int inputStride = inputBitmapData.Stride;
int outputStride = outputBitmapData.Stride;
int bytesPerPixel = Image.GetPixelFormatSize(m_inputImage.PixelFormat) / 8;
double redAverage = 0.0;
double greenAverage = 0.0;
double blueAverage = 0.0;
double average = 0.0;
int pixelCount = m_inputImage.Width * m_inputImage.Height;
for (int y = 0; y < m_inputImage.Height; y++)
{
byte* inputCurrentRow = inputScan0 + y * inputStride;
byte* outputCurrentRow = outputScan0 + y * outputStride;
for (int x = 0; x < m_inputImage.Width; x++)
{
ColorBgr* inputColor = (ColorBgr*)(inputCurrentRow + x * bytesPerPixel);
redAverage += inputColor->R;
greenAverage += inputColor->G;
blueAverage += inputColor->B;
}
}
redAverage /= pixelCount;
greenAverage /= pixelCount;
blueAverage /= pixelCount;
average = (redAverage + greenAverage + blueAverage) / 3;
for (int y = 0; y < m_inputImage.Height; y++)
{
byte* inputCurrentRow = inputScan0 + y * inputStride;
byte* outputCurrentRow = outputScan0 + y * outputStride;
for (int x = 0; x < m_inputImage.Width; x++)
{
ColorBgr* inputColor = (ColorBgr*)(inputCurrentRow + x * bytesPerPixel);
ColorBgr* outputColor = (ColorBgr*)(outputCurrentRow + x * bytesPerPixel);
outputColor->R = (byte)(inputColor->R * average / redAverage);
outputColor->G = (byte)(inputColor->G * average / greenAverage);
outputColor->B = (byte)(inputColor->B * average / blueAverage);
}
}
m_inputImage.UnlockBits(inputBitmapData);
m_outputImage.UnlockBits(outputBitmapData);
}
private struct ColorBgr : IEquatable<ColorBgr>
{
public byte B;
public byte G;
public byte R;
public ColorBgr(byte b, byte g, byte r)
{
B = b;
G = g;
R = r;
}
public static bool operator ==(ColorBgr left, ColorBgr right)
{
return left.Equals(right);
}
public static bool operator !=(ColorBgr left, ColorBgr right)
{
return !(left == right);
}
public bool Equals(ColorBgr other)
{
return this.B == other.B && this.G == other.G && this.R == other.R;
}
public override bool Equals(object? obj)
{
if (obj is ColorBgr)
return Equals((ColorBgr)obj);
return false;
}
public override int GetHashCode()
{
return new byte[] { B, G, R }.GetHashCode();
}
}
}
}

How to draw a rainbow line using Graphic class c#

So i'm trying to create infinite rainbow line. Here ColorUtils class How do I get a rainbow color gradient in C#? (I'm using Framework 4.7.3
int rainbowStage = 0;
int rainbowNext = 0;
private void Form1_Paint(object sender, PaintEventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
PointF point1 = new PointF(100.0F, 100.0F);
PointF point2 = new PointF(235.0F, 100.0F);
worker.DoWork += async delegate (object s, DoWorkEventArgs args)
{
do
{
Console.WriteLine(await getRainbow());
rainbowNext++;
Pen pen = new Pen(await getRainbow(), 3);
e.Graphics.DrawLine(pen, point1, point2);
e.Graphics.Clear(Color.FromArgb(26, 26, 26));
} while (rainbowStage == rainbowNext);
};
worker.RunWorkerCompleted += delegate (object s, RunWorkerCompletedEventArgs args)
{
rainbowStage++;
};
}
async Task<ColorUtils.ColorRGB> getRainbow()
{
for (double i = 0; i < 1; i += 0.01)
{
ColorUtils.ColorRGB c = ColorUtils.HSL2RGB(i, 0.5, 0.5);
return c;
}
ColorUtils.ColorRGB c1 = ColorUtils.HSL2RGB(0, 0.5, 0.5);
return c1;
}
So, you have found how to generate a sequence of rainbow colors. But your code is not actually correct, it should be something like:
IEnumerable<Color> GetRainbow()
{
for (double i = 0; i < 1; i += 0.1)
{
Color c = ColorUtils.HSL2RGB(i, 0.5, 0.5);
yield return c;
}
}
That will give you a sequence of ten colors, using the actual color type used by winforms.
To draw the rainbow we need to draw each color as a separate line, slightly offset from each other. To get the offset we need to do some vector math:
var dir = point1 - point2;
var offset= new PointF(dir.Y, -dir.X).Normalize();
...
public static PointF Normalize(this PointF A)
{
float distance = Math.Sqrt(A.X * A.X + A.Y * A.Y);
return new PointF(A.X / distance, A.Y / distance);
}
public static PointF Mul(this PointF a, float b)
{
return new PointF(a.X * b, a.Y * b);
}
We can then begin drawing our line:
var colors = GetRainbow().ToList();
var width = 10f / colors.Count;
for(int i = 0; i < colors.Count; i++){
using var pen = new Pen(colors[i], width);
var o = offset.Mul( width * i)
e.Graphics.DrawLine(pen, point1 + o, point2 + o);
}
That should give you a rainbow line of with 10 with one pixel per color, adjust the width literal to get a wider line.
An alternative approach would be to create something like a texture brush displaying the rainbow and use that for drawing.
Note that all drawing code need to be run on the UI thread, and any other calculations are really fast, they just involve a handful of simple math operations. So there is nothing at all to be gained from trying to run anything on any background thread.
Here's a copy, paste, run, version of what you're trying to do:
public class Form1 : Form
{
public Form1()
{
this.Paint += Form1_Paint;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (var rgb in GetRainbow().Select((colour, indexer) => (colour, indexer)))
{
Console.WriteLine(rgb.colour);
using (Pen pen = new Pen(rgb.colour, 3))
{
e.Graphics.DrawLine(pen, new PointF(100.0F, 100.0F + rgb.indexer), new PointF(235.0F, 100.0F + rgb.indexer));
}
}
}
IEnumerable<ColorRGB> GetRainbow()
{
for (double i = 0; i < 1; i += 0.01)
{
yield return HSL2RGB(i, 0.5, 0.5);
}
}
public struct ColorRGB
{
public byte R;
public byte G;
public byte B;
public ColorRGB(Color value)
{
this.R = value.R;
this.G = value.G;
this.B = value.B;
}
public static implicit operator Color(ColorRGB rgb)
{
Color c = Color.FromArgb(rgb.R, rgb.G, rgb.B);
return c;
}
public static explicit operator ColorRGB(Color c)
{
return new ColorRGB(c);
}
}
public static ColorRGB HSL2RGB(double h, double sl, double l)
{
double v;
double r, g, b;
r = l; // default to gray
g = l;
b = l;
v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
if (v > 0)
{
double m;
double sv;
int sextant;
double fract, vsf, mid1, mid2;
m = l + l - v;
sv = (v - m) / v;
h *= 6.0;
sextant = (int)h;
fract = h - sextant;
vsf = v * sv * fract;
mid1 = m + vsf;
mid2 = v - vsf;
switch (sextant)
{
case 0:
r = v;
g = mid1;
b = m;
break;
case 1:
r = mid2;
g = v;
b = m;
break;
case 2:
r = m;
g = v;
b = mid1;
break;
case 3:
r = m;
g = mid2;
b = v;
break;
case 4:
r = mid1;
g = m;
b = v;
break;
case 5:
r = v;
g = m;
b = mid2;
break;
}
}
ColorRGB rgb;
rgb.R = Convert.ToByte(r * 255.0f);
rgb.G = Convert.ToByte(g * 255.0f);
rgb.B = Convert.ToByte(b * 255.0f);
return rgb;
}
}
When run, I get this:
There were too many things going wrong with your original code, but don't use async/await, don't forget to dispose disposables, don't forget to compute the actual line you're trying to draw, use yield return to get your rainbow colours, etc.

Circle using Graphics.DrawLine()

I'm trying to make a circle using graphics.DrawLine() property and using BRESENHAM'S CIRCLE ALGORITHM but I'm not able to make it. Here is the method for making the circle
Pen pen = new Pen(Color.Red, 2);
Graphics graphics = this.Shape_PictureBox.CreateGraphics();
int radius = 40;
int x = 0, y = radius;
int xc = 50, yc = 50;
int d = 3 - 2 * radius;
// graphics.DrawLine(pen, xc, yc, x, y);
while (y >= x)
{
x++;
if (d > 0)
{
y--;
d = d + 4 * (x - y) + 10;
}
else
{
d = d + 4 * x + 6;
}
//drawCircle(xc, yc, x, y);
graphics.DrawLine(pen, xc, yc, x, y);
}
Well, there appears to be a bug in your algorithm implementation, as posted - but I suppose you're first and foremost asking as to why nothing is visible in the Shape_PictureBox? You should create a Bitmap buffer (think of it as a canvas) to draw to, and then assign it to the Shape_PictureBox.Image property.
IMPORTANT: Make sure to do this in the Form_Shown, not Form_Load event!
private void Child2_Shown(object sender, EventArgs e)
{
Pen pen = new Pen(Color.Red, 2);
Bitmap canvas = new Bitmap(Shape_PictureBox.Width, Shape_PictureBox.Height);
Graphics graphics = Graphics.FromImage(canvas);
int radius = 40;
int x = 0;
int y = radius;
int xc = 50;
int yc = 50;
int d = 3 - 2 * radius;
graphics.DrawLine(pen, xc, yc, x, y);
while (y >= x)
{
x++;
if (d > 0)
{
y--;
d = d + 4 * (x - y) + 10;
}
else
{
d = d + 4 * x + 6;
}
// drawCircle(xc, yc, x, y);
graphics.DrawLine(pen, xc, yc, x, y);
}
Shape_PictureBox.Image = canvas;
}
Currently, it looks like this:
You'll need to revise your implementation of Bresenham's Circle algorithm :)

Image convolution in spatial domain

I am trying to replicate the outcome of this link using linear convolution in spatial-domain.
Images are first converted to 2d double arrays and then convolved. Image and kernel are of the same size. The image is padded before convolution and cropped accordingly after the convolution.
As compared to the FFT-based convolution, the output is weird and incorrect.
How can I solve the issue?
Note that I obtained the following image output from Matlab which matches my C# FFT output:
.
Update-1: Following #Ben Voigt's comment, I changed the Rescale() function to replace 255.0 with 1 and thus the output is improved substantially. But, still, the output doesn't match the FFT output (which is the correct one).
.
Update-2: Following #Cris Luengo's comment, I have padded the image by stitching and then performed spatial convolution. The outcome has been as follows:
So, the output is worse than the previous one. But, this has a similarity with the 2nd output of the linked answer which means a circular convolution is not the solution.
.
Update-3: I have used the Sum() function proposed by #Cris Luengo's answer. The result is a more improved version of **Update-1**:
But, it is still not 100% similar to the FFT version.
.
Update-4: Following #Cris Luengo's comment, I have subtracted the two outcomes to see the difference:
,
1. spatial minus frequency domain
2. frequency minus spatial domain
Looks like, the difference is substantial which means, spatial convolution is not being done correctly.
.
Source Code:
(Notify me if you need more source code to see.)
public static double[,] LinearConvolutionSpatial(double[,] image, double[,] mask)
{
int maskWidth = mask.GetLength(0);
int maskHeight = mask.GetLength(1);
double[,] paddedImage = ImagePadder.Pad(image, maskWidth);
double[,] conv = Convolution.ConvolutionSpatial(paddedImage, mask);
int cropSize = (maskWidth/2);
double[,] cropped = ImageCropper.Crop(conv, cropSize);
return conv;
}
static double[,] ConvolutionSpatial(double[,] paddedImage1, double[,] mask1)
{
int imageWidth = paddedImage1.GetLength(0);
int imageHeight = paddedImage1.GetLength(1);
int maskWidth = mask1.GetLength(0);
int maskHeight = mask1.GetLength(1);
int convWidth = imageWidth - ((maskWidth / 2) * 2);
int convHeight = imageHeight - ((maskHeight / 2) * 2);
double[,] convolve = new double[convWidth, convHeight];
for (int y = 0; y < convHeight; y++)
{
for (int x = 0; x < convWidth; x++)
{
int startX = x;
int startY = y;
convolve[x, y] = Sum(paddedImage1, mask1, startX, startY);
}
}
Rescale(convolve);
return convolve;
}
static double Sum(double[,] paddedImage1, double[,] mask1, int startX, int startY)
{
double sum = 0;
int maskWidth = mask1.GetLength(0);
int maskHeight = mask1.GetLength(1);
for (int y = startY; y < (startY + maskHeight); y++)
{
for (int x = startX; x < (startX + maskWidth); x++)
{
double img = paddedImage1[x, y];
double msk = mask1[x - startX, y - startY];
sum = sum + (img * msk);
}
}
return sum;
}
static void Rescale(double[,] convolve)
{
int imageWidth = convolve.GetLength(0);
int imageHeight = convolve.GetLength(1);
double maxAmp = 0.0;
for (int j = 0; j < imageHeight; j++)
{
for (int i = 0; i < imageWidth; i++)
{
maxAmp = Math.Max(maxAmp, convolve[i, j]);
}
}
double scale = 1.0 / maxAmp;
for (int j = 0; j < imageHeight; j++)
{
for (int i = 0; i < imageWidth; i++)
{
double d = convolve[i, j] * scale;
convolve[i, j] = d;
}
}
}
public static Bitmap ConvolveInFrequencyDomain(Bitmap image1, Bitmap kernel1)
{
Bitmap outcome = null;
Bitmap image = (Bitmap)image1.Clone();
Bitmap kernel = (Bitmap)kernel1.Clone();
//linear convolution: sum.
//circular convolution: max
uint paddedWidth = Tools.ToNextPow2((uint)(image.Width + kernel.Width));
uint paddedHeight = Tools.ToNextPow2((uint)(image.Height + kernel.Height));
Bitmap paddedImage = ImagePadder.Pad(image, (int)paddedWidth, (int)paddedHeight);
Bitmap paddedKernel = ImagePadder.Pad(kernel, (int)paddedWidth, (int)paddedHeight);
Complex[,] cpxImage = ImageDataConverter.ToComplex(paddedImage);
Complex[,] cpxKernel = ImageDataConverter.ToComplex(paddedKernel);
// call the complex function
Complex[,] convolve = Convolve(cpxImage, cpxKernel);
outcome = ImageDataConverter.ToBitmap(convolve);
outcome = ImageCropper.Crop(outcome, (kernel.Width/2)+1);
return outcome;
}
Your current output looks more like the auto-correlation function than the convolution of Lena with herself. I think the issue might be in your Sum function.
If you look at the definition of the convolution sum, you'll see that the kernel (or the image, doesn't matter) is mirrored:
sum_m( f[n-m] g[m] )
For the one function, m appears with a plus sign, and for the other it appears with a minus sign.
You'll need to modify your Sum function to read the mask1 image in the right order:
static double Sum(double[,] paddedImage1, double[,] mask1, int startX, int startY)
{
double sum = 0;
int maskWidth = mask1.GetLength(0);
int maskHeight = mask1.GetLength(1);
for (int y = startY; y < (startY + maskHeight); y++)
{
for (int x = startX; x < (startX + maskWidth); x++)
{
double img = paddedImage1[x, y];
double msk = mask1[maskWidth - x + startX - 1, maskHeight - y + startY - 1];
sum = sum + (img * msk);
}
}
return sum;
}
The other option is to pass a mirrored version of mask1 to this function.
I have found the solution from this link. The main clue was to introduce an offset and a factor.
factor is the sum of all values in the kernel.
offset is an arbitrary value to fix the output further.
.
#Cris Luengo's answer also raised a valid point.
.
The following source code is supplied in the given link:
private void SafeImageConvolution(Bitmap image, ConvMatrix fmat)
{
//Avoid division by 0
if (fmat.Factor == 0)
return;
Bitmap srcImage = (Bitmap)image.Clone();
int x, y, filterx, filtery;
int s = fmat.Size / 2;
int r, g, b;
Color tempPix;
for (y = s; y < srcImage.Height - s; y++)
{
for (x = s; x < srcImage.Width - s; x++)
{
r = g = b = 0;
// Convolution
for (filtery = 0; filtery < fmat.Size; filtery++)
{
for (filterx = 0; filterx < fmat.Size; filterx++)
{
tempPix = srcImage.GetPixel(x + filterx - s, y + filtery - s);
r += fmat.Matrix[filtery, filterx] * tempPix.R;
g += fmat.Matrix[filtery, filterx] * tempPix.G;
b += fmat.Matrix[filtery, filterx] * tempPix.B;
}
}
r = Math.Min(Math.Max((r / fmat.Factor) + fmat.Offset, 0), 255);
g = Math.Min(Math.Max((g / fmat.Factor) + fmat.Offset, 0), 255);
b = Math.Min(Math.Max((b / fmat.Factor) + fmat.Offset, 0), 255);
image.SetPixel(x, y, Color.FromArgb(r, g, b));
}
}
}

How to create a "sharp" gradient in Windows Forms?

I need to fill a rectangle with a black to white (transparent) gradient. However, I could only find a GradientBrush class and all examples I found showed smooth transition and I want sharp bars. That's what I need:
You need to average the colors between your start color and your end color. Here is a routine that does all that, using an averaging formula found here: Generate Color Gradient in C#
private void PaintGradientBars(Graphics g, Rectangle r,
Color startColor, Color endColor, int numBars) {
int rMin = startColor.R;
int gMin = startColor.G;
int bMin = startColor.B;
int rMax = endColor.R;
int gMax = endColor.G;
int bMax = endColor.B;
int left = 0;
for (int i = 0; i < numBars; i++) {
int rAvg = rMin + (int)((rMax - rMin) * i / numBars);
int gAvg = gMin + (int)((gMax - gMin) * i / numBars);
int bAvg = bMin + (int)((bMax - bMin) * i / numBars);
Color useColor = Color.FromArgb(rAvg, gAvg, bAvg);
int width = (r.Width - left) / (numBars - i);
using (SolidBrush br = new SolidBrush(useColor)) {
g.FillRectangle(br, new Rectangle(left, 0, width, r.Height));
}
left += width;
}
}
Then you make a simple call:
private void panel1_Paint(object sender, PaintEventArgs e) {
PaintGradientBars(e.Graphics, panel1.ClientRectangle,
Color.Blue, Color.Green, 5);
}
Resulting in:
in this code i use picturebox, play with 'k' and 'i'
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
int k = 20;
Color mycolor = new Color();
for (int i = 0; i < 10; i++)
{
mycolor = Color.FromArgb(i * k, i * k, i * k);
SolidBrush mybrash = new SolidBrush(mycolor);
e.Graphics.FillRectangle((Brush)mybrash, 0 + i * k, 0, k, k);
}
}
Good luck!

Categories

Resources