Distortion when drawing an image

unnamed

New member
Joined
Aug 10, 2023
Messages
3
Programming Experience
1-3
Hi !

I'm writing code to draw points on an image whose coordinates come from a datagridview. For this I import an image in a picturebox, I select two rows of the datagridview then select these two points on the image in order to define the scale.
Depending on the imported image I get different results, sometimes the scale is not the right one, sometimes there is a distortion of the drawn points.

If anyone has any idea, here is my code.

Thank you all!

C#:
    public partial class PlanForm : Form
    {
        public PlanForm()
        {
            InitializeComponent();
        }

        private Dictionary<string, Color> designationColors = new Dictionary<string, Color>();
        private List<Color> availableColors = new List<Color> { Color.Blue, Color.Green, Color.Red, Color.Yellow, Color.Magenta };
        private Image originalPlanImage;
        private DataGridViewRow[] selectedRows = null;
        private PointF? scaleStartPoint = null;
        private PointF? scaleEndPoint = null;
        private PointF translation = new PointF(0, 0);
        private bool isScaling = false;
        private bool isScalingCancelled = false;
        private float scaleFactor = 1;
        private float imageScaleFactorX = 1;
        private float imageScaleFactorY = 1;

        private void btnImportPnp_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.Filter = "Text Files (*.txt)|*.txt";
                openFileDialog.Title = "Import File";

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string filePath = openFileDialog.FileName;
                    string[] lines = File.ReadAllLines(filePath);

                    DataTable dataTable = new DataTable();
                    dataTable.Columns.Add("R");
                    dataTable.Columns.Add("D");
                    dataTable.Columns.Add("X");
                    dataTable.Columns.Add("Y");

                    foreach (string line in lines)
                    {
                        string[] columns = line.Split('\t');
                        if (columns.Length == 4)
                        {
                            dataTable.Rows.Add(columns);
                        }
                    }

                    dgvPnp.DataSource = dataTable;
                    DataGridViewCheckBoxColumn checkboxColumn = new DataGridViewCheckBoxColumn();
                    checkboxColumn.HeaderText = "Visible";
                    dgvPnp.Columns.Add(checkboxColumn);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error : {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnSelectAllPnp_Click(object sender, EventArgs e)
        {
            foreach (DataGridViewRow row in dgvPnp.Rows)
            {
                DataGridViewCheckBoxCell checkBoxCell = row.Cells[4] as DataGridViewCheckBoxCell;
                checkBoxCell.Value = true;
            }
        }

        private void btnUnselectAllPnp_Click(object sender, EventArgs e)
        {
            foreach (DataGridViewRow row in dgvPnp.Rows)
            {
                DataGridViewCheckBoxCell checkBoxCell = row.Cells[4] as DataGridViewCheckBoxCell;
                checkBoxCell.Value = false;
            }
        }

        private void btnImportPlan_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.Filter = "Image (*.png;*.jpg;*.jpeg;*.gif;*.bmp)|*.png;*.jpg;*.jpeg;*.gif;*.bmp";
                openFileDialog.Title = "Import Image";

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    originalPlanImage = Image.FromFile(openFileDialog.FileName);
                    pbImport.Image = (Image)originalPlanImage.Clone();
                    pbImport.SizeMode = PictureBoxSizeMode.StretchImage;

                    imageScaleFactorX = (float)pbImport.Width / originalPlanImage.Width;
                    imageScaleFactorY = (float)pbImport.Height / originalPlanImage.Height;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error : {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void ColorPlan()
        {
            if (pbImport.Image == null)
                return;

            Bitmap planImage = new Bitmap(originalPlanImage);
            using (Graphics g = Graphics.FromImage(planImage))
            {
                foreach (DataGridViewRow row in dgvPnp.Rows)
                {
                    DataGridViewCheckBoxCell checkBoxCell = row.Cells[4] as DataGridViewCheckBoxCell;
                    if (checkBoxCell.Value != null && (bool)checkBoxCell.Value)
                    {
                        string designation = row.Cells["D"].Value.ToString();
                        float x = (float.Parse(row.Cells["X"].Value.ToString()) * scaleFactor + translation.X) / imageScaleFactorX;
                        float y = pbImport.Image.Height - (float.Parse(row.Cells["Y"].Value.ToString()) * scaleFactor + translation.Y) / imageScaleFactorY;

                        Color color = GetDesignationColor(designation);

                        using (Brush brush = new SolidBrush(color))
                        {
                            g.FillEllipse(brush, x - 5, y - 5, 10, 10);
                        }
                    }
                }
            }
            pbImport.Image = planImage;
        }

        private Color GetDesignationColor(string designation)
        {
            if (!designationColors.ContainsKey(designation))
            {
                Color color = availableColors[designationColors.Count % availableColors.Count];
                designationColors.Add(designation, color);
            }
            return designationColors[designation];
        }

        private void btnStartScale_Click(object sender, EventArgs e)
        {
            if (dgvPnp.SelectedRows.Count != 2)
            {
                MessageBox.Show("Please select two rows.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            selectedRows = new DataGridViewRow[] { dgvPnp.SelectedRows[0], dgvPnp.SelectedRows[1] };
            isScaling = true;
            isScalingCancelled = false;
            scaleStartPoint = null;
            scaleEndPoint = null;
        }

        private void pbImport_MouseDown(object sender, MouseEventArgs e)
        {
            if (isScaling && !isScalingCancelled)
            {
                float scaledX = e.X / imageScaleFactorX;
                float scaledY = e.Y / imageScaleFactorY;

                if (scaleStartPoint == null)
                {
                    scaleStartPoint = new PointF(scaledX, scaledY);
                }
                else if (scaleEndPoint == null)
                {
                    scaleEndPoint = new PointF(scaledX, scaledY);
                    CalculateScaleFactor();
                    isScaling = false;
                }
            }
        }

        private void CalculateScaleFactor()
        {
            float x1 = float.Parse(selectedRows[0].Cells["X"].Value.ToString());
            float y1 = float.Parse(selectedRows[0].Cells["Y"].Value.ToString());
            float x2 = float.Parse(selectedRows[1].Cells["X"].Value.ToString());
            float y2 = float.Parse(selectedRows[1].Cells["Y"].Value.ToString());
            float knownDistanceMM = (float)Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2));

            float pixelDistance = (float)Math.Sqrt(
            Math.Pow((scaleEndPoint.Value.X * imageScaleFactorX) - (scaleStartPoint.Value.X * imageScaleFactorX), 2) +
            Math.Pow((scaleEndPoint.Value.Y * imageScaleFactorY) - (scaleStartPoint.Value.Y * imageScaleFactorY), 2));

            scaleFactor = pixelDistance / knownDistanceMM;
            translation.X = (scaleStartPoint.Value.X * imageScaleFactorX) - (x1 * scaleFactor);
            translation.Y = (scaleStartPoint.Value.Y * imageScaleFactorY) - (y1 * scaleFactor);
        }

        private void btnGenerer_Click(object sender, EventArgs e)
        {
            ColorPlan();
        }

        private void trackBarX_ValueChanged(object sender, EventArgs e)
        {
            translation.X = trackBarX.Value;
            ColorPlan();
        }

        private void trackBarY_ValueChanged(object sender, EventArgs e)
        {
            translation.Y = trackBarY.Value;
            ColorPlan();
        }

        private void btnCancelScale_Click(object sender, EventArgs e)
        {
            isScaling = false;
            isScalingCancelled = true;
            scaleStartPoint = null;
            scaleEndPoint = null;
        }
    }
 
Graphics Class (System.Drawing) has a handful of properties that may affect the quality of drawing, test them out, I can never remember which ones it is.
 
Moving to WinForms...
 
Also the OP maybe fighting against the effects of using StretchMode.
 

Latest posts

Back
Top Bottom