How to resize a cropped image? - c#

Goal:
My current goal is to crop the original image from pictureBox1 and show it in pictureBox2 and increase it's size (Height & Width) by 0.8.
Current Code:
//...
private Point LocationXY;
private Point LocationX1Y1;
private void button1_Click(object sender, EventArgs e)
{
if (Clipboard.ContainsImage())
{
pictureBox1.Image?.Dispose();
pictureBox1.Image = Clipboard.GetImage();
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
LocationXY = e.Location;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
LocationX1Y1 = e.Location;
pictureBox1.Invalidate();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
LocationX1Y1 = e.Location;
pictureBox1.Invalidate();
pictureBox2.Invalidate();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (MouseButtons == MouseButtons.Left)
e.Graphics.DrawRectangle(Pens.Red, GetRect());
}
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
var src = GetRect();
if (src == Rectangle.Empty) return;
var des = new Rectangle(0, 0, src.Width, src.Height);
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
e.Graphics.DrawImage(pictureBox1.Image,
des, src, GraphicsUnit.Pixel);
}
private Rectangle GetRect()
{
return new Rectangle(
Math.Min(LocationXY.X, LocationX1Y1.X),
Math.Min(LocationXY.Y, LocationX1Y1.Y),
Math.Abs(LocationXY.X - LocationX1Y1.X),
Math.Abs(LocationXY.Y - LocationX1Y1.Y)
);
}
//...
Cropping the image:
//...
private Bitmap GetCroppedImage()
{
var src = GetRect();
if (src == Rectangle.Empty) return null;
var des = new Rectangle(0, 0, src.Width, src.Height);
var b = new Bitmap(src.Width, src.Height);
using (var g = Graphics.FromImage(b))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(pictureBox1.Image, des, src, GraphicsUnit.Pixel);
}
return b;
}
//...
Current code - what does it do
Currently this code is able to mark an red area in pictureBox1 and show the cropped image in pictureBox2.
Question:
How do I increase/resize the cropped image height and width by 0.8?

Calculate the ratio of the scale up against the source size and use it to calculate the new size of the image. Accordingly, the pictureBox2.Paint event code:
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
var src = GetRect();
if (src == Rectangle.Empty || src.Width == 0 || src.Height == 0) return;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
var widthScale = 0.8;
var heightScale = 0.8;
var widthRatio = (src.Width * widthScale + src.Width) / src.Width;
var heightRatio = (src.Height * heightScale + src.Height) / src.Height;
var newWidth = (int)(src.Width * widthRatio);
var newHeight = (int)(src.Height * heightRatio);
var des = new Rectangle(0, 0, newWidth, newHeight);
e.Graphics.DrawImage(pictureBox1.Image,
des, src, GraphicsUnit.Pixel);
}
To apply that on the GetCroppedImage() function:
private Image GetCroppedImage(double scale = 0)
{
var src = GetRect();
if (src == Rectangle.Empty || src.Width == 0 || src.Height == 0) return null;
var widthRatio = (src.Width * scale + src.Width) / src.Width;
var heightRatio = (src.Height * scale + src.Height) / src.Height;
var newWidth = (int)(src.Width * widthRatio);
var newHeight = (int)(src.Height * heightRatio);
if (newWidth == 0 || newHeight == 0) return null;
var des = new Rectangle(0, 0, newWidth, newHeight);
var b = new Bitmap(newWidth, newHeight);
using (var g = Graphics.FromImage(b))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(pictureBox1.Image, des, src, GraphicsUnit.Pixel);
}
return b;
}
Also, you could use the Image.GetThumbnailImage to get small sizes from the main image. Not recommended if you need to return large ones. Read the Remarks for more information.

public static Bitmap ResizeImage(System.Drawing.Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
Usage:
ResizeImage(originalImg, (int)(originalImg.Width * 0.8), (int)(originalImg.Height * 0.8));

Related

How to draw the diffrenet pixels in yellow only when the pie is rotating above this pixels?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Doppler_Radar
{
public partial class Form1 : Form
{
int myPiePercent = 15;
float distanceFromCenterPixels;
float distanceFromCenterKm = 200F;
public Form1()
{
InitializeComponent();
pictureBox1.Image = Image.FromFile(#"D:\New folder (4)\Weather Radar\WithClouds.bmp");
timer1.Enabled = true;
distanceFromCenterPixels = (float)(183d * (double)distanceFromCenterKm / 200d);
pictureBox1.Image = CalcDifference(new Bitmap(pictureBox1.Image),
new Bitmap(#"D:\New folder (4)\Weather Radar\WithoutClouds.bmp"));
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
DrawPieOnPicturebox(e.Graphics);
}
public void DrawPieOnPicturebox(Graphics myPieGraphic)
{
Color myPieColors = Color.FromArgb(150, Color.LightGreen);
Size myPieSize = new Size((int)distanceFromCenterPixels, (int)distanceFromCenterPixels);
Point myPieLocation = new Point((pictureBox1.Width - myPieSize.Width) / 2, (pictureBox1.Height - myPieSize.Height) / 2);
DrawMyPie(myPiePercent, myPieColors, myPieGraphic, myPieLocation, myPieSize);
}
public void DrawMyPie(int myPiePerecent, Color myPieColor, Graphics myPieGraphic, Point
myPieLocation, Size myPieSize)
{
using (SolidBrush brush = new SolidBrush(myPieColor))
{
myPieGraphic.FillPie(brush, new Rectangle(myPieLocation, myPieSize), Convert.ToSingle(myPiePerecent * 360 / 100), Convert.ToSingle(15 * 360 / 100));
}
}
private void timer1_Tick(object sender, EventArgs e)
{
myPiePercent++;
pictureBox1.Invalidate();
}
public Bitmap CalcDifference(Bitmap bmp1, Bitmap bmp2)
{
Rectangle rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
BitmapData bitmapdata = bmp1.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
IntPtr source = bitmapdata.Scan0;
BitmapData data2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
IntPtr ptr2 = data2.Scan0;
int length = (bmp1.Width * bmp1.Height) * 4;
byte[] destination = new byte[length];
byte[] buffer2 = new byte[length];
Marshal.Copy(source, destination, 0, length);
Marshal.Copy(ptr2, buffer2, 0, length);
for (int i = 0; i < length; i += 4)
{
if (((destination[i] == buffer2[i]) && (destination[i + 1] == buffer2[i + 1])) && (destination[i + 2] == buffer2[i + 2]))
{
destination[i] = 0xff;
destination[i + 1] = 0xff;
destination[i + 2] = 0xff;
destination[i + 3] = 0;
}
else
{
destination[i] = 0;
destination[i + 1] = 255;
destination[i + 2] = 255;
}
}
Marshal.Copy(destination, 0, source, length);
bmp1.UnlockBits(bitmapdata);
bmp2.UnlockBits(data2);
return bmp1;
}
}
}
this color in the yellow the diffrenet pixels all the time because i'm calling the method CalcDifference in the constructor. but what i want is that only when the rotating pie is over/above this diffrenet pixels then color this diffrenet pixels that are under the pie and not all the diffrenet pixels.
on the left side is when coloring the diffrenet pixels with the method CalcDifference.
on the right side the image at it's original.
the goal is to make a doppler radar effect that detect the clouds when the pie is rotating abvoe them.
Yes, you can use a little trick to change the colors of the clouds under the pie and skip the others.
To optimize your CalcDifference method and speed things up, get from each image only the pie region to process. The rest of the image does not change and you don't need to traverse the data of that region.
Pass the clipped images to the CalcDifference method and change the colors of the clouds in that region. All of them. Note, I have changed the method to convert the original images to 32bppArgb images if needed so you can pass images of different formats that the LockBits supports to process.
Assign the full-size image with clouds to the .Image property of the PictureBox.
Here's the trick. Handle the PictureBox.Paint event and create a GraphicsPath object, add the pie and pass it to Graphics.SetClip method. Draw the yellow clouds image then reset the clip (Graphics.ResetClip) to draw the pie.
public partial class SomeForm : Form
{
private float startAngle;
private readonly SolidBrush brPie;
private Rectangle pieRect;
private Bitmap imgWithYellowClouds;
public SomeForm()
{
InitializeComponent();
brPie = new SolidBrush(Color.FromArgb(150, Color.LightGreen));
picWithoutClouds.Image = Image.FromFile(#"...");
picWithClouds.Image = picCanvas.Image = Image.FromFile(#"...");
CreateYellowCloudsImage();
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
brPie.Dispose();
imgWithYellowClouds?.Dispose();
}
private void picCanvas_Resize(object sender, EventArgs e) =>
CreateYellowCloudsImage();
private void picCanvas_Paint(object sender, PaintEventArgs e)
{
if (pieRect.Width < 1 || pieRect.Height < 1 ||
imgWithYellowClouds == null) return;
var g = e.Graphics;
using (var gp = new GraphicsPath())
{
gp.AddPie(pieRect, startAngle, 360f / 8);
g.SetClip(gp);
g.DrawImage(imgWithYellowClouds, pieRect);
g.ResetClip();
g.SmoothingMode = SmoothingMode.AntiAlias;
g.FillPath(brPie, gp);
}
}
private void SomeButton(object sender, EventArgs e)
{
timer1.Enabled = !timer1.Enabled;
}
private void timer1_Tick(object sender, EventArgs e)
{
// Change as needed...
startAngle = (startAngle + 10) % 360;
picCanvas.Invalidate();
}
public Bitmap CalcDifference(Bitmap bmp1, Bitmap bmp2)
{
var disImg1 = !Is32bppArgbFormat(bmp1);
var disImg2 = !Is32bppArgbFormat(bmp2);
var img1 = disImg1 ? To32bppArgbFormat(bmp1) : new Bitmap(bmp1);
var img2 = disImg2 ? To32bppArgbFormat(bmp2) : bmp2;
var img1Data = img1.LockBits(
new Rectangle(Point.Empty, img1.Size),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
var img2Data = img2.LockBits(
new Rectangle(Point.Empty, img2.Size),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
var img1Buffer = new byte[img1Data.Stride * img1Data.Height];
var img2Buffer = new byte[img2Data.Stride * img2Data.Height];
Marshal.Copy(img1Data.Scan0, img1Buffer, 0, img1Buffer.Length);
Marshal.Copy(img2Data.Scan0, img2Buffer, 0, img2Buffer.Length);
img2.UnlockBits(img2Data);
for (int i = 0; i + 4 < img1Buffer.Length; i += 4)
{
if (img1Buffer[i] == img2Buffer[i] &&
img1Buffer[i + 1] == img2Buffer[i + 1] &&
img1Buffer[i + 2] == img2Buffer[i + 2])
{
img1Buffer[i] = 0;
img1Buffer[i + 1] = 0;
img1Buffer[i + 2] = 0;
img1Buffer[i + 3] = 0;
}
else
{
img1Buffer[i] = 0;
img1Buffer[i + 1] = 255;
img1Buffer[i + 2] = 255;
}
}
Marshal.Copy(img1Buffer, 0, img1Data.Scan0, img1Buffer.Length);
img1.UnlockBits(img1Data);
if (disImg2) img2.Dispose();
return img1;
}
private bool Is32bppArgbFormat(Bitmap bmp) =>
Image.GetPixelFormatSize(bmp.PixelFormat) == 32 &&
bmp.PixelFormat != PixelFormat.Indexed;
private Bitmap To32bppArgbFormat(Bitmap src)
{
var bmp = new Bitmap(src.Width, src.Height, PixelFormat.Format32bppArgb);
using (var g = Graphics.FromImage(bmp))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(src, new Rectangle(0, 0, bmp.Width, bmp.Height),
0, 0, src.Width, src.Height, GraphicsUnit.Pixel);
return bmp;
}
}
private void CreateYellowCloudsImage()
{
var cs = picCanvas.ClientSize;
// Change as needed...
var sz = new Size(128, 128);
pieRect = new Rectangle(
(cs.Width - sz.Width) / 2,
(cs.Height - sz.Height) / 2,
sz.Width, sz.Height);
// To get the image rectangle regardless of the SizeMode property
// so we can get the pie's region to process...
var method = typeof(PictureBox).GetMethod("ImageRectangleFromSizeMode",
BindingFlags.NonPublic | BindingFlags.Instance);
var imageRect = (Rectangle)method.Invoke(picCanvas,
new object[] { picCanvas.SizeMode });
var cx = picCanvas.Image.Width / (float)imageRect.Width;
var cy = picCanvas.Image.Height / (float)imageRect.Height;
var r2 = RectangleF.Intersect(imageRect, pieRect);
r2.Offset(-imageRect.X, -imageRect.Y);
var cloneRect = new RectangleF(
r2.X * cx,
r2.Y * cy,
r2.Width * cx,
r2.Height * cy);
imgWithYellowClouds?.Dispose();
imgWithYellowClouds = null;
using (var cloulds = (picWithClouds.Image as Bitmap)
.Clone(cloneRect, picWithClouds.Image.PixelFormat))
using (var noClouds = (picWithoutClouds.Image as Bitmap)
.Clone(cloneRect, picWithoutClouds.Image.PixelFormat))
{
// The yellow clouds image...
imgWithYellowClouds = CalcDifference(cloulds, noClouds);
}
}
}
Taken from your previous questions for this demo.

When the Bitmap is scaled, it goes like this

I have an image drawn in the picturebox and I need to scale it using a trackbar. But this happens whenever I scale it up, and if I continue scaling - it becomes more blurry.
My code:
Image Drawing
public LayerClass ImageDrawing(LayerClass.Type img, Bitmap bm, Rectangle imgRect, String filepath, int angle, PaintEventArgs e)
{
bm = ImageClass.GrayscaleImage(bm);
bm = MakeTransparentImage(bm);
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
bm = RotateImage(bm, angle);
imgRect = new Rectangle((int)(Shape.center.X - (bm.Width / 2)), (int)(Shape.center.Y - (bm.Height / 2)), (int)bm.Width, (int)bm.Height);
e.Graphics.DrawRectangle(new Pen(Color.Red, 1), imgRect);
e.Graphics.DrawImage(bm, imgRect);
this.imageBitmap = bm;
this.filePath = filePath;
this.rotationAngle = angle;
this.location = location;
this.imageRect = imgRect;
return new LayerClass(LayerClass.Type.Image, this, filePath, imgRect);
}
Scaling
private void trackBar_ScaleImg_Scroll(object sender, EventArgs e)
{
//Width Scaling
if(rb_WidthImage.Checked)
{
imgRect.Width = trackBar_ScaleImg.Value;
imgRect.X = (int)(Shape.center.X - (imgRect.Width / 2));
lbl_imgWidth.Text = Math.Round((trackBar_ScaleImg.Value * 25.4) / 96).ToString();
toolTip_Scroll.SetToolTip(trackBar_ScaleImg, lbl_imgWidth.Text);
ImageBitmap = new Bitmap(ImageBitmap, new Size(imgRect.Width, imgRect.Height));
}
}

C# - Forcing Rectangle to be in a fixed size/ratio

Similar to Photoshop, where you can type in a ratio or in my case a certain dimention such as 800x600, I want to be able to force a Rectangle to be a fixed ratio/size when dragging the mouse..
At the moment I have this:
Which will crop an image using the Rectangle created from clicking and dragging on the PictureBox. The bounding box selects the area without any constraints. I want to be able to force the rectangle to be a certain ratio (prefereably from a set resolution) similar to the way Photoshop's cropping tool works.
My source if anyone needs more detail:
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CropResize
{
public partial class Form1 : Form
{
private static string path;
public Form1(string filePath)
{
InitializeComponent();
path = filePath;
}
private Image _originalImage;
private Image _newImage;
private bool _selecting;
private Rectangle _selection;
private void Form1_Load(object sender, System.EventArgs e)
{
pictureBox1.Image = Image.FromFile(path);
if (pictureBox1.Image.Height > Screen.PrimaryScreen.Bounds.Height - 50 || pictureBox1.Image.Width > Screen.PrimaryScreen.Bounds.Width - 50)
{
if (pictureBox1.Image.Height > Screen.PrimaryScreen.Bounds.Height - 50)
{
Height = Screen.PrimaryScreen.Bounds.Height - 50;
panel1.Height = Size.Height - statusStrip1.Height - buttonSave.Height - 60;
}
if (pictureBox1.Image.Width > Screen.PrimaryScreen.Bounds.Width - 50)
{
Size = new Size(Screen.PrimaryScreen.Bounds.Width - 50, Screen.PrimaryScreen.Bounds.Height - 50);
panel1.Width = Size.Width - statusStrip1.Height - buttonSave.Height - 60;
}
pictureBox1.Image = pictureBox1.Image.Fit2PictureBox(pictureBox1);
panel1.Size = new Size(pictureBox1.Image.Width, pictureBox1.Image.Height);
}
Size = new Size(panel1.Size.Width + 50, panel1.Size.Height + buttonSave.Height + statusStrip1.Height + 80);
// Create a copy of the original image for later use
_originalImage = pictureBox1.Image.Clone() as Image;
_newImage = pictureBox1.Image.Clone() as Image;
}
private void buttonOrig_Click(object sender, System.EventArgs e)
{
pictureBox1.Image = _originalImage.Clone() as Image;
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
// Starting point of the selection:
if (e.Button == MouseButtons.Left)
{
pictureBox1.Image.Dispose();
pictureBox1.Image = _originalImage.Clone() as Image;
_selecting = true;
_selection = new Rectangle(new Point(e.X, e.Y), new Size());
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
// Update the actual size of the selection:
if (_selecting)
{
_selection.Width = (e.X - _selection.X);
_selection.Height = (e.Y - _selection.Y);
//int nGCD = GetGreatestCommonDivisor(1920, 1080);
//_selection.Width = _selection.Width / nGCD;
//_selection.Height = _selection.Height / nGCD;
int widthRatio = 16;
int heightRatio = 9;
if (_selection.Height * widthRatio <= _selection.Width)
{
_selection.Width = _selection.Height * widthRatio;
}
else if (_selection.Width * heightRatio <= _selection.Width)
{
_selection.Height = _selection.Width * heightRatio;
}
// Redraw the picturebox:
pictureBox1.Refresh();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (_selecting && _selection.Height != 0)
{
// Draw a rectangle displaying the current selection
e.Graphics.DrawRectangle(Pens.WhiteSmoke, _selection);
//e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(50, Color.Gray)), 0, pictureBox1.Height - pictureBox1.Image.Height, pictureBox1.Image.Width, pictureBox1.Image.Height);
e.Graphics.SetClip(_selection, CombineMode.Exclude);
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(100, Color.Black)), 0, 0, pictureBox1.Width, pictureBox1.Height);
int nGCD = GetGreatestCommonDivisor(_selection.Width, _selection.Height);
string str = string.Format("{0}:{1}", _selection.Width / nGCD, _selection.Height / nGCD);
toolStripStatusLabel1.Text = "Image Size: " + _selection.Width + "x" + _selection.Height + "px. Aspect Ratio: " + str;
}
}
public static int GetGreatestCommonDivisor(int height, int width)
{
return width == 0 ? height : GetGreatestCommonDivisor(width, height % width);
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left &&
_selecting &&
_selection.Size != new Size())
{
// Create cropped image:
_newImage = pictureBox1.Image.Crop(_selection);
_selecting = false;
try
{
// Set new image to the picturebox:
//pictureBox1.Image = _newImage.Fit2PictureBox(pictureBox1);
pictureBox1.Image = _newImage;
//toolStripStatusLabel1.Text = "Image Cropped.";
}
catch (Exception)
{ }
}
else
{
_selecting = false;
}
}
private void buttonResize_Click(object sender, EventArgs e)
{
pictureBox1.Image = ResizeImage(pictureBox1.Image, new Size(800, 600));
int nGCD = GetGreatestCommonDivisor(pictureBox1.Image.Width, pictureBox1.Image.Height);
string str = string.Format("{0}:{1}", pictureBox1.Image.Width / nGCD, pictureBox1.Image.Height / nGCD);
toolStripStatusLabel1.Text = "Image Resized to " + pictureBox1.Image.Width + "x" + pictureBox1.Image.Height + "px. Aspect Ratio: " + str;
}
public static Image ResizeImage(Image image, Size size, bool preserveAspectRatio = true)
{
int newWidth;
int newHeight;
if (preserveAspectRatio)
{
int originalWidth = image.Width;
int originalHeight = image.Height;
float percentWidth = size.Width / originalWidth;
float percentHeight = size.Height / originalHeight;
float percent = percentHeight < percentWidth ? percentHeight : percentWidth;
newWidth = (int)(originalWidth * percent);
newHeight = (int)(originalHeight * percent);
}
else
{
newWidth = size.Width;
newHeight = size.Height;
}
Image newImage = new Bitmap(newWidth, newHeight);
using (Graphics graphicsHandle = Graphics.FromImage(newImage))
{
graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight);
}
return newImage;
}
private void buttonSave_Click(object sender, EventArgs e)
{
string filename = path.Substring(path.LastIndexOf("\\") + 1);
string newPath = path.Substring(0, path.LastIndexOf(".") - 1) + "NEW.png";
toolStripStatusLabel1.Text = "Saving " + filename + " to " + newPath;
pictureBox1.Image.Save(newPath, ImageFormat.Png);
toolStripStatusLabel1.Text = filename + " saved to " + newPath;
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CropResize
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(args[0]));
}
public static Image SetImageWithinResolution(this Image image, PictureBox pictureBox)
{
//Bitmap bitmap = null;
if (image.Height > Screen.PrimaryScreen.Bounds.Height)
{
//ActiveForm.Size = new Size(100, 100);
Form.ActiveForm.Size = new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
image = image.Fit2PictureBox(pictureBox);
//Bitmap bitmap = new Bitmap(image, );
}
if (image.Width > Screen.PrimaryScreen.Bounds.Width)
{
//ActiveForm.Size = new Size(100, 100);
Form.ActiveForm.Size = new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
image = image.Fit2PictureBox(pictureBox);
//Bitmap bitmap = new Bitmap();
}
return image;
}
public static Image Crop(this Image image, Rectangle selection)
{
Bitmap bmp = image as Bitmap;
try
{
// Check if it is a bitmap:
if (bmp == null)
throw new ArgumentException("No valid bitmap");
// Crop the image:
Bitmap cropBmp = bmp.Clone(selection, bmp.PixelFormat);
// Release the resources:
image.Dispose();
return cropBmp;
}
catch (Exception)
{
return bmp;
}
}
public static Image Fit2PictureBox(this Image image, PictureBox picBox)
{
Bitmap bmp = null;
Graphics g;
// Scale:
double scaleY = (double)image.Width / picBox.Width;
double scaleX = (double)image.Height / picBox.Height;
double scale = scaleY < scaleX ? scaleX : scaleY;
// Create new bitmap:
bmp = new Bitmap(
(int)((double)image.Width / scale),
(int)((double)image.Height / scale));
// Set resolution of the new image:
bmp.SetResolution(
image.HorizontalResolution,
image.VerticalResolution);
// Create graphics:
g = Graphics.FromImage(bmp);
// Set interpolation mode:
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Draw the new image:
g.DrawImage(
image,
new Rectangle( // Destination
0, 0,
bmp.Width, bmp.Height),
new Rectangle( // Source
0, 0,
image.Width, image.Height),
GraphicsUnit.Pixel);
// Release the resources of the graphics:
g.Dispose();
// Release the resources of the origin image:
image.Dispose();
return bmp;
}
}
Maybe this example will help; is shows how to restrict a drawn rectangle to a given ratio:
float ratio = 0.33f;
Rectangle setRect()
{
int x = Math.Min(mDown.X, currPt.X);
int y = Math.Min(mDown.Y, currPt.Y);
int w = Math.Max(mDown.X, currPt.X) - x;
int h = Math.Max(mDown.Y, currPt.Y) - y;
if (ratio > 1) h = (int)(1f * w / ratio);
else w = (int)(1f * h * ratio);
return new Rectangle(x, y, w, h);
}
It uses two Points, one set in the MouseDown and one updated in the MouseMove.
It is up to you to integrate it with you programm; instead of painting all those pixels during MouseMove I would simply draw a rubberband rectangle on the surface of the control using the Paint event..
If you are scaling things you may want to switch to using all floats.

ColorImageFrame can not be used in kinect v2 (VS2013 C# kinectSDK V2)

(RgbResolution640x480Fps30) have problom
public partial class TrainWPF : Window
{
KinectSensor kinectSensor = null;
ColorImageFormat imageFormat = ColorImageFormat.RgbResolution640x480Fps30;
ColorImageFrame Originally kinect v1 can be used, but it can not be used in kinect v2 How to use the ColorImageFrame in KINECT v2
/////stop&ColorFrameReady&Dispose can't be use
private void DeActivateSensor()
{
if (kinectSensor != null)
{
kinectSensor.Stop();
kinectSensor.ColorFrameReady -= new EventHandler<ColorImageFrameReadyEventArgs>(sensor_ColorFrameReady);
kinectSensor.Dispose();
}
}
private void SetupSensorVideoInput()
{
if (kinectSensor != null)
{
imageFormat = (ColorImageFormat)cmbDisplayMode.SelectedItem;
kinectSensor.ColorStream.Enable(imageFormat);
kinectSensor.ColorFrameReady += new EventHandler<ColorImageFrameReadyEventArgs>(sensor_ColorFrameReady);
kinectSensor.Start();
}
}
void sensor_ColorFrameReady(object sender, ColorFrameArrivedEventArgs e)
{
using (ColorImageFrame image = e.OpenColorImageFrame())
{
if (image == null)
return;
Image<Bgr, byte> currentImage = EmguImageExtensions.ToOpenCVImage<Bgr, byte>(image);
Image<Gray, byte> grayFrame = currentImage.Convert<Gray, byte>();
System.Drawing.Rectangle[] facesDetected = Face.DetectMultiScale(grayFrame, 1.2, 10, new System.Drawing.Size(50, 50), System.Drawing.Size.Empty);
for (int i = 0; i < facesDetected.Length; i++)// (Rectangle face_found in facesDetected)
{
//This will focus in on the face from the haar results its not perfect but it will remove a majoriy
//of the background noise
facesDetected[i].X += (int)(facesDetected[i].Height * 0.15);
facesDetected[i].Y += (int)(facesDetected[i].Width * 0.22);
facesDetected[i].Height -= (int)(facesDetected[i].Height * 0.3);
facesDetected[i].Width -= (int)(facesDetected[i].Width * 0.35);
result = currentImage.Copy(facesDetected[i]).Convert<Gray, byte>().Resize(100, 100, Emgu.CV.CvEnum.INTER.CV_INTER_CUBIC);
result._EqualizeHist();
face_PICBX.Source = result.ToBitmapSource();
}
if (colorBytes == null ||
colorBytes.Length != image.PixelDataLength)
{
colorBytes = new byte[image.PixelDataLength];
}
image.CopyPixelDataTo(colorBytes);
BitmapSource source = BitmapSource.Create(image.Width,
image.Height,
96,
96,
PixelFormats.Bgr32,
null,
colorBytes,
image.Width * image.BytesPerPixel);
picVideoDisplay.Source = source;
}
}
private Bitmap ImageToBitmap(ColorImageFrame Image)
{
byte[] pixeldata = new byte[Image.PixelDataLength];
Image.CopyPixelDataTo(pixeldata);
Bitmap bmap = new Bitmap(Image.Width, Image.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
BitmapData bmapdata = bmap.LockBits(
new System.Drawing.Rectangle(0, 0, Image.Width, Image.Height),
ImageLockMode.WriteOnly,
bmap.PixelFormat);
IntPtr ptr = bmapdata.Scan0;
Marshal.Copy(pixeldata, 0, ptr, Image.PixelDataLength);
bmap.UnlockBits(bmapdata);
return bmap;
}

How do I properly select a certain part of an image inside a picture box in C# and highlight it?

I have been trying to write a program, to be able to load an image on a form and select a rectangle on it, then load that rectangle onto another picture box (pictureBox2), and I also want to be able to highlight what I have selected on the original picture, in pictureBox1, as I move my mouse.
So far I have this code, but it doesn't properly respond to the mouseMove event, the rectangle that I highlight isn't selected properly. What is the problem?
public partial class Form1 : Form
{
Bitmap original;
bool isSelecting;
int x0, y0, x1, y1;
public Form1()
{
InitializeComponent();
pictureBox1.MouseDown += new MouseEventHandler(picOriginal_MouseDown);
pictureBox1.MouseMove += new MouseEventHandler(picOriginal_MouseMove);
pictureBox1.MouseUp += new MouseEventHandler(picOriginal_MouseUp);
}
#region helpder methods
// Start selecting the rectangle.
private void picOriginal_MouseDown(object sender, MouseEventArgs e)
{
if(original != null)
{
isSelecting = true;
// Save the start point.
x0 = e.X;
y0 = e.Y;
}
}
// Continue selecting.
private void picOriginal_MouseMove(object sender, MouseEventArgs e)
{
if(original != null)
{
// Do nothing it we're not selecting an area.
if(!isSelecting) return;
// Save the new point.
x1 = e.X;
y1 = e.Y;
// Make a Bitmap to display the selection rectangle.
Bitmap bm = new Bitmap(original);
// Draw the rectangle.
using(Graphics gr = Graphics.FromImage(bm))
{
gr.DrawRectangle(Pens.Red,
Math.Min(x0, x1), Math.Min(y0, y1),
Math.Abs(x0 - x1), Math.Abs(y0 - y1)
);
}
// Display the temporary bitmap.
pictureBox1.Image = new Bitmap(bm, new Size(pictureBox1.Width, pictureBox1.Height));
}
}
// Finish selecting the area.
private void picOriginal_MouseUp(object sender, MouseEventArgs e)
{
if(original != null)
{
// Do nothing it we're not selecting an area.
if(!isSelecting) return;
isSelecting = false;
// Display the original image.
pictureBox1.Image = original;
// Copy the selected part of the image.
int wid = Math.Abs(x0 - x1);
int hgt = Math.Abs(y0 - y1);
if((wid < 1) || (hgt < 1)) return;
Bitmap area = new Bitmap(wid, hgt);
using(Graphics gr = Graphics.FromImage(area))
{
Rectangle source_rectangle =
new Rectangle(Math.Min(x0, x1), Math.Min(y0, y1),
wid, hgt);
Rectangle dest_rectangle =
new Rectangle(0, 0, wid, hgt);
gr.DrawImage(original, dest_rectangle,
source_rectangle, GraphicsUnit.Pixel);
}
// Display the result.
pictureBox2.Image = area;
}
}
#endregion
private void button1_Click(object sender, EventArgs e)
{
if(original != null)
{
}
}
private void button2_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "jpg files (*.jpg)|*.jpg|All files(*.*)|*.*";
if(dialog.ShowDialog() == DialogResult.OK)
{
original = new Bitmap(dialog.FileName);
pictureBox1.Image = new Bitmap(original, new Size(pictureBox1.Width, pictureBox1.Height));
}
dialog.Dispose();
}
}
I think your problem is the 'original' image size which is not the same as the picturebox size. Try this code to compensate for the zoom ratio between your 'original' image and the picturebox size:
// Draw the rectangle.
float zoomX = (float)original.Size.Width / pictureBox1.Width;
float zoomY = (float)original.Size.Height / pictureBox1.Height;
using (Graphics gr = Graphics.FromImage(bm))
{
gr.DrawRectangle(Pens.Red,
Math.Min(x0, x1) * zoomX, Math.Min(y0, y1) * zoomY,
Math.Abs(x0 - x1) * zoomX, Math.Abs(y0 - y1) * zoomY
);
}
This fixes the red rectangle in my case. But the copied part in picturebox2 is still not correct...
And this fixes the copy to the second picturebox:
// Copy the selected part of the image.
float zoomX = (float)original.Size.Width / pictureBox1.Width;
float zoomY = (float)original.Size.Height / pictureBox1.Height;
int wid = (int)(zoomX * Math.Abs(x0 - x1));
int hgt = (int)(zoomY * Math.Abs(y0 - y1));
if ((wid < 1) || (hgt < 1)) return;
Bitmap area = new Bitmap(wid, hgt);
using (Graphics gr = Graphics.FromImage(area))
{
Rectangle source_rectangle =
new Rectangle((int)(zoomX * Math.Min(x0, x1)), (int)(zoomY * Math.Min(y0, y1)),
wid, hgt);
Rectangle dest_rectangle =
new Rectangle(0, 0, wid, hgt);
gr.DrawImage(original, dest_rectangle,
source_rectangle, GraphicsUnit.Pixel);
}

Categories