Click here to Skip to main content
15,884,298 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I've created a custom control that allows me to render an image. This image is supposed to be scalable, which is performed by using an up/down control. The image scales just fine, but when it does, it leaves the original image on the screen along with the rescaled version of it. I've tried a number of ways to get rid of the original (unscaled) image, but nothing has worked. How do I get rid of it?

Here's the code:

C#
using System;
//using System.Collections.Generic;
//using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
//using System.Data;
//using System.Linq;
//using System.Text;
using System.Windows.Forms;

namespace BitmapTest
{
	public partial class CPCanvas : UserControl
	{
		public Bitmap OriginalBitmap  { get; set; }
		public Bitmap CurrentBitmap   { get; set; }

		private bool m_moving             = false;
		private bool m_backgroundRendered = false;
		private Rectangle m_bmpRect;
		private int   m_moveOffsetX = 0;
		private int   m_moveOffsetY = 0;
		private Point m_bmpOrigin   = new Point(0,0);
		private float m_bmpScale    = 0f;
		private float m_bmpAngle    = 0f;
		
		//--------------------------------------------------------------------------------
		public CPCanvas()
		{
			CommonInit();
		}

		//--------------------------------------------------------------------------------
		public CPCanvas(Bitmap background, Bitmap weapon)
		{
			CommonInit();
			BackgroundImage = background;
			OriginalBitmap  = weapon;
			CloneOriginal();
			GetBitmapRectangle();
		}

		//--------------------------------------------------------------------------------
		public CPCanvas(Bitmap weapon)
		{
			CommonInit();
			m_backgroundRendered = true;
			OriginalBitmap       = weapon;
			CloneOriginal();
			GetBitmapRectangle();
		}

		//--------------------------------------------------------------------------------
		private void GetBitmapRectangle()
		{
			m_bmpRect = new Rectangle(m_bmpOrigin.X, 
									  m_bmpOrigin.Y, 
									  OriginalBitmap.Width, 
									  OriginalBitmap.Height);
		}

		//--------------------------------------------------------------------------------
		protected void CommonInit()
		{
			OriginalBitmap       = null;
			CurrentBitmap        = null;
			BackgroundImage      = null;
			m_bmpOrigin            = new Point(0,0);
			m_bmpScale             = 100f;
			m_bmpAngle             = 0f;
			m_backgroundRendered = false;

			InitializeComponent();
			SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
			Dock                  = DockStyle.Top | DockStyle.Left;
			BackgroundImageLayout = ImageLayout.Stretch;
		}

		//--------------------------------------------------------------------------------
		private void CloneOriginal()
		{
			CurrentBitmap = OriginalBitmap.Clone() as Bitmap;
		}

		//--------------------------------------------------------------------------------
		protected override void OnPaint(PaintEventArgs e)
		{
			RenderOverlay(e);
		}

		//--------------------------------------------------------------------------------
		private void RenderOverlay(PaintEventArgs e)
		{
			try
			{
				e.Graphics.DrawImage(CurrentBitmap, m_bmpOrigin);
			}
			catch (Exception ex)
			{
				if (ex != null) {}
			}
		}

		//--------------------------------------------------------------------------------
		protected override void OnPaintBackground(PaintEventArgs e)
		{
			if (!m_backgroundRendered)
			{
				base.OnPaintBackground(e);
			}
		}

		//--------------------------------------------------------------------------------
		protected override void OnMouseUp(MouseEventArgs e)
		{
			m_moving = false;
			base.OnMouseUp(e);
		}

		//--------------------------------------------------------------------------------
		protected override void OnMouseDown(MouseEventArgs e)
		{
			if (m_bmpRect.Contains(e.Location))
			{
				m_moveOffsetX = e.Location.X - m_bmpRect.X;
				m_moveOffsetY = e.Location.Y - m_bmpRect.Y;
				m_moving = (e.Button == System.Windows.Forms.MouseButtons.Left);
				m_moving = true;
				base.OnMouseDown(e);
			}
		}

		//--------------------------------------------------------------------------------
		protected override void OnMouseMove(MouseEventArgs e)
		{
			if (m_moving)
			{
				MoveImage(e.Location);
			}
			base.OnMouseMove(e);
		}

		//--------------------------------------------------------------------------------
		public void MoveImage(Point pt)
		{
			m_bmpOrigin.X = (pt.X - m_moveOffsetX);
			m_bmpOrigin.Y = (pt.Y - m_moveOffsetY);
			m_bmpRect.X = m_bmpOrigin.X;
			m_bmpRect.Y = m_bmpOrigin.Y;
			Refresh();
		}

		public void ScaleImage(float percent)
		{
			// this doesn't work
			//using (Graphics g = this.CreateGraphics())
			//{
			//    ColorMatrix matrix = new ColorMatrix();
			//    matrix.Matrix33 = 0f;
			//    using (ImageAttributes attributes = new ImageAttributes())
			//    {
			//        attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
			//        g.DrawImage(OriginalBitmap, m_bmpRect, 0, 0, OriginalBitmap.Width, OriginalBitmap.Height, GraphicsUnit.Pixel, attributes);
			//    }
			//}

			// if I don't do this, EVERY scaled version of the bitmap 
			// remains on the screen
			CurrentBitmap.Dispose();
			CurrentBitmap = null;
			CloneOriginal();

			this.m_bmpScale = percent * 0.01f;
			using (Graphics g = Graphics.FromImage(CurrentBitmap))
			{
			    g.ScaleTransform(m_bmpScale, m_bmpScale);
			    g.DrawImage(this.CurrentBitmap, 0,0);
			    m_bmpRect.Width  = this.CurrentBitmap.Width;
			    m_bmpRect.Height = this.CurrentBitmap.Height;
			}
			Refresh();
		}
	}
}
Posted
Updated 8-Oct-11 11:24am
v2

1 solution

Hi John,

I think you shouldn't do it like this. You create a Graphics object out of your picture and then redraw the picture to the same object, this is why you still see the "old" pictures (they are still on the graphics). I'd avoid the problem like this: just remove the complete cloning and drawing part of Scale Image like this:

C#
public void ScaleImage(float percent)
 {
     this.m_bmpScale = percent * 0.01f;

     Refresh();
 }


and in your draw method just scale before drawing:

C#
private void RenderOverlay(PaintEventArgs e)
 {
     try
     {
         e.Graphics.ScaleTransform(m_bmpScale, m_bmpScale);
         e.Graphics.DrawImage(CurrentBitmap, m_bmpOrigin);
     }
     catch (Exception ex)
     {
         if (ex != null) { }
     }
 }


You have another problem when moving the image because you don't consider the current scale.
I'd do the whole thing like this:

using System;
using System.Windows.Forms;
using System.Drawing;

namespace Common.Controls
{
    public class PictureContainer : UserControl
    {
        bool bMoving;
        Point ptOffsetFromImagePosition; // used for moving

        public Image BackgroundImage { get; set; }
        public Image Picture { get; set; }
        public float PictureScale { get; set; }
        public Point PicturePosition { get; set; }

        public PictureContainer() : this(null, null) { }
        public PictureContainer(Image imagePicture) : this(imagePicture, null) { }
        public PictureContainer(Image imagePicture, Image imageBackground)
        {
            SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);

            Picture = imagePicture;
            BackgroundImage = imageBackground;

            PictureScale = 1f; // set default scale
        }

        public Rectangle CurrentPictureRectangle
        {
            get
            {
                return Picture != null ?
                    new Rectangle(PicturePosition.X, PicturePosition.Y,
                        (int)(PictureScale * Picture.Width), (int)(PictureScale * Picture.Height)) :
                    new Rectangle();
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (Picture != null)
            {
                e.Graphics.ScaleTransform(PictureScale, PictureScale);
                e.Graphics.DrawImage(Picture, PicturePosition);
            }

            base.OnPaint(e);
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            if (BackgroundImage != null)
                e.Graphics.DrawImage(BackgroundImage, ClientRectangle);
            else
                base.OnPaintBackground(e);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left &&
                CurrentPictureRectangle.Contains(e.Location))
            {
                ptOffsetFromImagePosition = new Point(e.X - PicturePosition.X, e.Y - PicturePosition.Y);
                bMoving = true;
            }

            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
                bMoving = false;

            base.OnMouseUp(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (bMoving)
            {
                PicturePosition = new Point(e.X - ptOffsetFromImagePosition.X, e.Y - ptOffsetFromImagePosition.Y);
                Refresh();
            }

            base.OnMouseMove(e);
        }
    }
}
 
Share this answer
 
v2
Comments
#realJSOP 9-Oct-11 15:36pm    
I implemented your code, and while it solved the immediate problem, I'm still having issues which I think call for a separate question. I just can't get my head around this GDI stuff...
johannesnestler 10-Oct-11 9:56am    
Hi John, I'm glad it solved "this" problem. What other problems do you have?
#realJSOP 12-Oct-11 7:58am    
I have them mostly resolved now. I've moved on to other parts of the code, but will probably revisit the remaining image weirdness in the future.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900