Change height of all Pictureboxes C# - c#

I ran into a problem when trying to change the size of all PictureBoxes in a project.
The PictureBoxes have been created like this:
for (int x = 0; x < 2; x++)
{
string filePath = fileEntries[i];
string fileName = Path.GetFileName(filePath);
int index = Array.IndexOf(fileEntries, filePath);
PictureBox image = new PictureBox();
image.Text = filePath;
image.Top = (int)y * 185 + 8 + 185;
image.Left = (int)x * 325 + 9;
image.Name = "picbox";
image.Click += picbox_Click;
image.Image = Image.FromFile(filePath);
image.BackColor = Color.FromArgb(0, 0, 110);
image.Height = 181;
image.Width = 318;
image.Padding = new Padding(2);
image.Name = "picbox";
this.Controls.Add(image);
}
Then, when clicking a box, I want to change the height, width, padding and Name of all PictureBoxes on the Form. Currently, I am using the following code:
picbox.BackColor = Color.FromArgb(0, 0, 110);
picbox.Height = 177;
picbox.Width = 314;
picbox.Padding = new Padding(0);
picbox.Name = "picboxnew";
This is not working, does anyone know how I can make this work?
Kind regards,

you can do it using Linq:
var pictureboxes = this.Controls.OfType<PictureBox>().ToList();
foreach (PictureBox pb in pictureboxes)
{
pb.Height = 500;
pb.Name = "some_name";
//etc
}

Related

Lines drawn on a large Bitmap are not visible when the image is saved

I have created a program to draw square grids on a selected image. It works fine for images that has small resolution, but it doesn't work properly on large images.
The all grid lines are not visible seem when the image is saved as file.
The image I am testing has resolution 3600x4320 and can be shown in the link.
How can I fix this problem?
My code:
Image drawGrid(int n, string imgPath)
{
Image img = Image.FromFile(imgPath);
Graphics grp = Graphics.FromImage(img);
grp.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
float m = img.Width * 1f / n;
for (int i = 1; i < n; i++)
{
var x = new PointF(i * m, 0);
var y = new PointF(i * m, img.Height);
grp.DrawLine(Pens.Red, x, y);
}
for (int i = 1; i <= (int)(this.Height / m); i++)
{
var x = new PointF(0, i * m);
var y = new PointF(img.Width, i * m);
grp.DrawLine(new Pen(Color.Red, 5f), x, y);
}
return img;
}
void BtnExportClick(object sender, EventArgs e)
{
if(saveFileDialog1.ShowDialog() == DialogResult.OK)
{
int n = (int)numericUpDown1.Value;
drawGrid(n, txtImagePath.Text).Save(saveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
MessageBox.Show("Done");
}
}
The result image is below (resolution reduced to upload)
The grid lines not shown correctly.
The major problem is in this line:
for (int i = 1; i <= (int)(this.Height / m); i++)
▶ this.Height is clearly not what you wanted to write, let's replace it with the Image.Height
▶ grp.DrawLine(Pens.Red, x, y); and grp.DrawLine(new Pen(Color.Red, 5f), x, y); will draw lines of different size (1 and 5 pixels). In the sample code, the two methods accept Color and float arguments that define the Pen color and size.
▶ grp.SmoothingMode: we don't want any smoothing mode here, not needed to draw straight lines and it will add anti-alias which will be clearly visible, especially when saving the Image in JPEG format (it will anti-alias - sort of, it actually mangles the colors - these lines by itself).
▶ You're not disposing of any of the Graphics object you create. This is quite important with both frequent graphics operations and when working with large Bitmaps.
The Pen and Graphics objects needs to be disposed.
Since it's not exactly clear if you want to generate a grid that has the same number of lines in both dimensions - hence, a grid with Cells in which the Width is not equal to the Height, most probably - or a grid with squared Cells (this is what the sample Image seems to show, not the code), I posted two method that draw both grid types:
First method, same number of lines in both width and height:
var gridSizeX = (float)image.Width / lines;
var gridSizeY = (float)image.Height / lines;
private Image DrawGridLines(int lines, string imgPath, Color penColor, float penSize)
{
var image = Image.FromStream(new MemoryStream(File.ReadAllBytes(imgPath)), true);
using (var g = Graphics.FromImage(image)) {
g.PixelOffsetMode = PixelOffsetMode.Half;
var gridSizeX = (float)image.Width / lines;
var gridSizeY = (float)image.Height / lines;
for (int i = 1; i < lines; i++) {
var pointX1 = new PointF(0, i * gridSizeY);
var pointX2 = new PointF(image.Width, i * gridSizeY);
var pointY1 = new PointF(i * gridSizeX, 0);
var pointY2 = new PointF(i * gridSizeX, image.Height);
using (var pen = new Pen(penColor, penSize)) {
g.DrawLine(pen, pointX1, pointX2);
g.DrawLine(pen, pointY1, pointY2);
}
}
return image;
}
}
Second method, drawing a squared grid. The integer value, gridSection, is used to define a grid Cell based on the minimum dimension of the Bitmap.
This dimension is then used to determine how many lines to draw in the other dimension.
The grid size is calculated on the minimum dimension:
var gridSize = (float)Math.Min(image.Width, image.Height) / gridSection;
And the Cell are determined as a consequence:
var gridStepMin = Math.Min(image.Width, image.Height) / gridSize;
var gridStepMax = Math.Max(image.Width, image.Height) / gridSize;
private Image DrawSquaredGrid(int gridSection, string imgPath, Color penColor, float penSize)
{
var image = Image.FromStream(new MemoryStream(File.ReadAllBytes(imgPath)), true);
using (var g = Graphics.FromImage(image)) {
g.PixelOffsetMode = PixelOffsetMode.Half;
var gridSize = (float)Math.Min(image.Width, image.Height) / gridSection;
var gridStepMin = Math.Min(image.Width, image.Height) / gridSize;
var gridStepMax = Math.Max(image.Width, image.Height) / gridSize;
for (int i = 1; i < gridStepMin; i++) {
var pointY1 = new PointF(i * gridSize, 0);
var pointY2 = new PointF(i * gridSize, image.Height);
using (var pen = new Pen(penColor, penSize)) {
g.DrawLine(pen, pointY1, pointY2);
}
}
for (int i = 1; i < gridStepMax; i++) {
var pointX1 = new PointF(0, i * gridSize);
var pointX2 = new PointF(image.Width, i * gridSize);
using (var pen = new Pen(penColor, penSize)) {
g.DrawLine(pen, pointX1, pointX2);
}
}
return image;
}
}
The SaveFileDialog is refactored to allow multiple Image formats. and to call one of the drawing methods based on a selection (in the sample code, a CheckBox (chkSquared) is used select one of the Grid types).
You can add more formats, the ImageFormatFromFileName() methods selects the ImageFormat type based on the SaveFileDialog.FielName extension.
private void BtnExportClick(object sender, EventArgs e)
{
string imagePath = [Some Path];
using (var sfd = new SaveFileDialog()) {
sfd.Filter = "PNG Image (*.png)|*.png|TIFF Image (*.tif)|*.tif|JPEG Image (*.jpg)|*.jpg";
sfd.RestoreDirectory = true;
sfd.AddExtension = true;
if (sfd.ShowDialog() == DialogResult.OK) {
Image image = null;
if (chkSquared.Checked) {
image = DrawSquaredGrid((int)numericUpDown1.Value, imagePath, Color.Red, 5.0f);
}
else {
image = DrawGridLines((int)numericUpDown1.Value, imagePath, Color.Red, 5.0f);
}
image.Save(sfd.FileName, ImageFormatFromFileName(sfd.FileName));
MessageBox.Show("Done");
image.Dispose();
}
}
}
private ImageFormat ImageFormatFromFileName(string fileName)
{
string fileType = Path.GetExtension(fileName).Remove(0, 1);
if (fileType.Equals("tif")) fileType = "tiff";
if (fileType.Equals("jpg")) fileType = "jpeg";
return (ImageFormat)new ImageFormatConverter().ConvertFromString(fileType);
}

Cannot update Image inside picturebox

I'm making a small Reversi/Othello game and inside my method for drawing the board I have a nested for loop to display a grid of PictureBoxes each with an image in.
The first time the method is called all the PictureBoxes are created correctly and the images placed inside. However if I then call the method again I cannot seem to overwrite the images that are already there.
I've been researching for a while and as I understand it may be something to do with the PictureBox becoming locked or needing to correctly Dispose() the PictureBox before writing another image to it. I couldn't get any of these solutions to work though so any specific help would be much appreciated!
private void Draw()
{
Bitmap White = Properties.Resources.white;
Bitmap Black = Properties.Resources.black;
Bitmap None = Properties.Resources.none;
for (int r = 0; r <= grid.GetUpperBound(0); r++)
{
for (int c = 0; c <= grid.GetUpperBound(0); c++)
{
if (grid[r, c].value == 1)
{
var picbox = new PictureBox() // initialise picturebox for displaying images
{
Name = grid[r, c].name,
Size = new Size(64, 64),
Location = new Point(r * 65 + 15, c * 65 + 60),
Text = grid[r, c].name,
Image = White
};
Controls.Add(picbox); // add picturebox to form
picbox.Click += ClickBox;
MessageBox.Show("white draw" + grid[r, c].name);
}
if (grid[r, c].value == -1)
{
var picbox = new PictureBox()
{
Name = grid[r, c].name,
Size = new Size(64, 64),
Location = new Point(r * 65 + 15, c * 65 + 60),
Text = grid[r, c].name,
Image = Black
};
Controls.Add(picbox);
picbox.Click += ClickBox;
MessageBox.Show("black draw" + grid[r, c].name);
}
if (grid[r, c].value == 0)
{
var picbox = new PictureBox()
{
Name = grid[r, c].name,
Size = new Size(64, 64),
Location = new Point(r * 65 + 15, c * 65 + 60),
Text = grid[r, c].name,
Image = None
};
Controls.Add(picbox);
picbox.Click += ClickBox;
}
}
}
}
The problem is that you create new picturebox but do not remove/update the existing Picture box from Controls.
First of all you need to find a picture box you want to update or remove from Controls.
I suggest to create a grid of a Picture boxes, so you can get the picture box from the grid. First of all create the field.
private var pictureGrid = new PictureBox[8, 8];
And then
if (grid[r, c].value == 1)
{
if (pictureGrid[r,c] != null)
{
pictureGrid[r,c].Image = White;
}
else
{
var picbox = new PictureBox()
{
Name = grid[r, c].name,
Size = new Size(64, 64),
Location = new Point(r * 65 + 15, c * 65 + 60),
Text = grid[r, c].name,
Image = White
};
pictureGrid[r,c] = picbox;
Controls.Add(picbox);
picbox.Click += ClickBox;
MessageBox.Show("white draw" + grid[r, c].name);
}
}
You also can use Dictionary that contains (grid.Value - Color) pairs.
private Dictionary<int, Bitmap> colors = new Dictionary<int, Bitmap>();
private void Load()
{
Bitmap White = Properties.Resources.white;
Bitmap Black = Properties.Resources.black;
Bitmap None = Properties.Resources.none;
colors.Add(1, White);
colors.Add(-1, Black);
colors.Add(0, None);
}
So your method will look like
private var pictureGrid = new PictureBox[8, 8];
private Dictionary<int, Bitmap> colors = new Dictionary<int, Bitmap>();
private void Load()
{
Bitmap White = Properties.Resources.white;
Bitmap Black = Properties.Resources.black;
Bitmap None = Properties.Resources.none;
colors.Add(1, White);
colors.Add(-1, Black);
colors.Add(0, None);
}
private void Draw()
{
for (int r = 0; r <= grid.GetUpperBound(0); r++)
{
for (int c = 0; c <= grid.GetUpperBound(0); c++)
{
if (pictureGrid[r, c] != null)
{
pictureGrid[r,c].Image = colors[grid[r,c]];
}
else
{
var picbox = new PictureBox()
{
Name = grid[r, c].name,
Size = new Size(64, 64),
Location = new Point(r * 65 + 15, c * 65 + 60),
Text = grid[r, c].name,
Image = colors[grid[r,c]]
};
pictureGrid[r,c] = picbox;
Controls.Add(picbox);
picbox.Click += ClickBox;
MessageBox.Show("black draw" + grid[r, c].name);
}
}
}
}
Also you can find the picture box to update using linq
var pictureToRemove = this.Controls.OfType<PictureBox>().Where(x => x.Location.X == r * 65 + 15 && x.Location.Y == c * 65 + 60).First();

C# graphics.drawImage() crops my Image

I am trying to put an image on a bigger image. But the inner image was cropped after drawImage(). Here is my code:
Bitmap im = new Bitmap("D:\\Steffen\\New folder\\I1\\I1\\" + filename + ".png");
int sizeX = im.Width;
int sizeY = im.Height;
int size = 0;
bool isWidth = false;
if (sizeX > sizeY)
{
size = sizeX; isWidth = true;
}
else if(sizeY > sizeX)
{
size = sizeY; isWidth = false;
}
filename = filename + "New";
Bitmap bg = new Bitmap(size,size);
SolidBrush brush = new SolidBrush(Color.Aqua);
using (Graphics g = Graphics.FromImage(bg))
{
g.FillRectangle(brush, 0, 0, size, size);
if (isWidth==true)
{
g.DrawImage(im, 0, (size - sizeY) / 2);
}
else if(isWidth==false)
{
g.DrawImage(im, (size-sizeX)/2, 0);
}
}
Thanks in advance
My guess would be the resolution of the image is the issue:
Try it like this:
Bitmap im = new Bitmap("D:\\Steffen\\New folder\\I1\\I1\\" + filename + ".png");
im.SetResolution(96F, 96F);

Cut an Image into 9 pieces C# [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Image splitting into 9 pieces
Though I googled enough but unfortunately failed to find a help. This Code Project Tutorial also failed to serve me what I actually need.
I have an Image and 9 PictureBox(s) in a WinForm.
Image img = Image.FromFile("media\\a.png"); // a.png has 312X312 width and height
// some code help, to get
// img1, img2, img3, img4, img5, img6, img7, img8, img9
// having equal width and height
// then...
pictureBox1.Image = img1;
pictureBox2.Image = img2;
pictureBox3.Image = img3;
pictureBox4.Image = img4;
pictureBox5.Image = img5;
pictureBox6.Image = img6;
pictureBox7.Image = img7;
pictureBox8.Image = img8;
pictureBox9.Image = img9;
Here is an example Image for you:
This is a part of my Picture Puzzle class project. I have done with photoshop images, now want to dynamically cut.
Thanks in advance.
First off, instead of using img1, img2... use an array with a size of 9. Then it's much easier to do this using a couple of loops like this:
var imgarray = new Image[9];
var img = Image.FromFile("media\\a.png");
for( int i = 0; i < 3; i++){
for( int j = 0; j < 3; j++){
var index = i*3+j;
imgarray[index] = new Bitmap(104,104);
var graphics = Graphics.FromImage(imgarray[index]);
graphics.DrawImage( img, new Rectangle(0,0,104,104), new Rectangle(i*104, j*104,104,104), GraphicsUnit.Pixel);
graphics.Dispose();
}
}
Then you can fill your boxes like this:
pictureBox1.Image = imgarray[0];
pictureBox2.Image = imgarray[1];
...
You could try with this code. It basically creates a matrix of images (like you need in your project) and draws on each Bitmap adequate part of the large image. The same concept you could use for the pictureBoxes and put them in the matrix.
Image img = Image.FromFile("media\\a.png"); // a.png has 312X312 width and height
int widthThird = (int)((double)img.Width / 3.0 + 0.5);
int heightThird = (int)((double)img.Height / 3.0 + 0.5);
Bitmap[,] bmps = new Bitmap[3,3];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
bmps[i, j] = new Bitmap(widthThird, heightThird);
Graphics g = Graphics.FromImage(bmps[i, j]);
g.DrawImage(img, new Rectangle(0, 0, widthThird, heightThird), new Rectangle(j * widthThird, i * heightThird, widthThird, heightThird), GraphicsUnit.Pixel);
g.Dispose();
}
pictureBox1.Image = bmps[0, 0];
pictureBox2.Image = bmps[0, 1];
pictureBox3.Image = bmps[0, 2];
pictureBox4.Image = bmps[1, 0];
pictureBox5.Image = bmps[1, 1];
pictureBox6.Image = bmps[1, 2];
pictureBox7.Image = bmps[2, 0];
pictureBox8.Image = bmps[2, 1];
pictureBox9.Image = bmps[2, 2];

Not able to successfully use lockbits

Hi i m really new in image processing in C# and the code below basically getpixel from the image I browsed from my computer and will compare the RGB value of the pixel with the right pixel and if its the same value, it will setpixel to cyan color. the problem is with the getpixel, it is really very slow even on a small resolution photos and I'm also looking to add more function to it. I have read about lockbits and was trying it out but was unable to successfully write the code.
namespace Disimage
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Bitmap pic;
public Bitmap pic2;
private bool compare_colour_constant(int original, int sample)
{
if (original == sample)
return true;
else
return false;
}
public void btn_browse_Click_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog open = new OpenFileDialog();
open.Filter = "Image Files(*.jpg; *.jpeg; *.gif; *.bmp)|*.jpg; *.jpeg; *.gif; *.bmp";
if (open.ShowDialog() == DialogResult.OK)
{
pic = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
pic2 = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
//pictureBox1.Image = new Bitmap(open.FileName);
pic = new Bitmap(open.FileName);
pic2 = new Bitmap(open.FileName);
pictureBox1.Image = pic;
pictureBox2.Image = pic2;
pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
textBox1.Text = open.FileName;
pictureBox2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
}
}
catch (Exception)
{
throw new ApplicationException("Failed loading image");
}
}
public void scan_Click(object sender, EventArgs e)
{
try
{
//Bitmap pic = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
//Bitmap pic2 = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
pictureBox1.Image = pic;
pictureBox2.Image = pic2;
progressBar1.Minimum = 0;
progressBar1.Maximum = pic.Width;
int []RGB = pic.GetPixel();
for (int w = 1; w < pic.Width - 1; w++)
{
progressBar1.Step = 1;
progressBar1.PerformStep();
if (progressBar1.Value == progressBar1.Maximum)
progressBar1.Value = 0;
for (int h = 1; h < pic.Height - 1; h++)
{
int red = pic.GetPixel(w, h).R;
int green = pic.GetPixel(w, h).G;
int blue = pic.GetPixel(w, h).B;
int colour = pic.GetPixel(w, h).R + pic.GetPixel(w, h).G + pic.GetPixel(w, h).B;
int colour2 = pic.GetPixel(w + 1, h).R + pic.GetPixel(w + 1, h).G + pic.GetPixel(w + 1, h).B;
/*textBox2.Text = red.ToString();
textBox3.Text = green.ToString();
textBox4.Text = blue.ToString();
*/
int Lred = pic.GetPixel(w - 1, h).R;
int Lgreen = pic.GetPixel(w - 1, h).G;
int Lblue = pic.GetPixel(w - 1, h).B;
int Rred = pic.GetPixel(w + 1, h).R;
int Rgreen = pic.GetPixel(w + 1, h).G;
int Rblue = pic.GetPixel(w + 1, h).B;
if (compare_colour_constant(colour, colour2) == true)
pic2.SetPixel(w, h, Color.Cyan);
}
}
}
catch (Exception)
{
throw new ApplicationException("Failed loading image");
}
}
}
}
Though a little late, I'd be happy to answer your question for other users. The first thing you would need to do is to declare a BitmapData variable, which would hold (obviously) the data from the Bitmap image that has been placed into the memory. To do this:
System.Drawing.Imaging.BitmapData bmpdata = pic.LockBits(new Rectangle(pictureBox1.Location.X, pictureBox1.Location.Y, pictureBox1.Width, pictureBox1.Height),
System.Drawing.Imaging.ImageLockMode.ReadWrite,
System.Drawing.Imaging.PixelFormat);
After calling this code, you can proceed to edit the BitmapData to your liking. In this situation you could call for a loop through a byte array of the Data and compare the RGB to the RGB of the pixel immediately to the right's and determine similarity. Example:
unsafe
{
for (int y = 0; y < bmpdata.Height; y++) // Repeats for each row
{
byte* row = (byte*)bmpdata.Scan0 + (y * bmpdata.Stride); // Array of bytes for the current row of pixels
for (int x = 0; x < bmpdata.Width; x++) // Repeats for each pixel on each row
{
if (row[x * 4] == row[(x + 1) * 4] && row[(x * 4) + 1] == row[((x + 1) * 4) + 1] && row[(x * 4) + 2] == row[((x + 1) * 4) + 2])
{
row[x * 4] = 255; // Blue value of current pixel
row[(x * 4) + 1] = 255; // Green Value of current pixel
row[(x * 4) + 2] = 0; // Red value of current pixel
}
}
}
}
ATTENTION: Though the above might work (and let me stress might), it would probably be much more reliable to go to Bob Powell's site and read his page on LockBits. Though it may be hard to understand at first, it gets simpler as you go along. His page is much more detailed than I could be in this answer, and he probably has working examples.

Categories