Memory leaks looping through images to byte arrays - c#

I have a routine that scans a folder for images, then for each image, converts it to a thumbnail, and then uploads that thumbnail to a database. It will only run if there isn't any items for that particular folder in the db. My problem is I am receiving an out of memory exception after processing a couple of folders and I'm not sure where the leak is occurring. I have tried disposing of everything disposable that I can in the loop, but obviously something is still falling though the cracks.
private bool LoadImages(int folderid, int parentid) {
ProgressScreen tfrm = new ProgressScreen();
tfrm.Hide();
DataTable mtable = new DataTable();
List<FileInfo> lfile;
mtable = Requests.ProcessSQLCommand(sqlconn, "Select f.ID, f.FolderName,f.FolderPath,f.ParentID,f.Root from Folders f where f.ID = " + folderid);
DataTable ptable = Requests.ProcessSQLCommand(sqlconn, "Select Root from Folders where ID = " + parentid);
if (ptable != null && ptable.Rows.Count > 0) {
if (ptable.Rows[0]["Root"].ToString().ToLower() == "true") {
return false;
}
}
bool process = true;
DirectoryInfo di = new DirectoryInfo(mtable.Rows[0]["FolderPath"].ToString());
FileInfo[] smFiles = di.GetFiles("*.jpg", SearchOption.TopDirectoryOnly);
lfile = smFiles.ToList<FileInfo>();
if (lfile.Count <= 0) {
process = false;
}
if (process) {
tfrm.Show(this);
for (int c = 0; c < lfile.Count; c++) {
if (((FileInfo)lfile[c]).Extension == ".txt") {
lfile.RemoveAt(c);
}
if (((FileInfo)lfile[c]).FullName.ToLower().Contains("cover")) {
lfile.RemoveAt(c);
}
}
for (int b = 0; b < lfile.Count; b++) {
Cursor.Current = Cursors.WaitCursor;
this.Enabled = false;
try {
tfrm.Location = new Point((Screen.PrimaryScreen.WorkingArea.Width / 2) - (tfrm.Width / 2), (Screen.PrimaryScreen.WorkingArea.Height / 2) - (tfrm.Height / 2));
} catch {
}
tfrm.SetProgress((int)(((double)(b + 1) / (double)lfile.Count) * 100), "Loading Images", lfile[b].Name.ToString());
tfrm.Refresh();
int recid = 0;
DataTable ttable = Requests.ProcessSQLCommand(sqlconn, "Insert into Image (Name,FolderID,ParentID) VALUES ('" + lfile[b].Name + "'," + folderid + "," + parentid + ") Select SCOPE_IDENTITY()");
if (ttable != null && ttable.Rows.Count > 0) {
recid = int.Parse(ttable.Rows[0][0].ToString());
}
if (recid > 0) {
Image timg = null;
byte[] traw = new byte[0];
traw = File.ReadAllBytes(lfile[b].FullName);
MemoryStream tstream = new MemoryStream(traw);
timg = System.Drawing.Image.FromStream(tstream);
tstream.Dispose();
timg = Requests.FixedSize(timg, 600, 600);
tstream = new MemoryStream();
timg.Save(tstream, System.Drawing.Imaging.ImageFormat.Png);
timg.Dispose();
traw = new byte[0];
traw = tstream.ToArray();
tstream.Dispose();
System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(sqlconn);
con.Open();
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand("Update Image set [Thumb] = Convert(VarBinary(MAX),#Image) where ID = " + recid, con);
cmd.Parameters.AddWithValue("#Image", traw);
cmd.ExecuteNonQuery();
con.Dispose();
}
}
this.Enabled = true;
Cursor.Current = Cursors.Default;
tfrm.Close();
tfrm.Dispose();
System.Windows.Forms.Application.UseWaitCursor = false;
return true;
} else {
return false;
}
}
the Fixed size method:
public static Image FixedSize(Image imgPhoto, int Width, int Height) {
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)Width / (float)sourceWidth);
nPercentH = ((float)Height / (float)sourceHeight);
if (nPercentH < nPercentW) {
nPercent = nPercentH;
destX = System.Convert.ToInt16((Width - (sourceWidth * nPercent)) / 2);
} else {
nPercent = nPercentW;
destY = System.Convert.ToInt16((Height - (sourceHeight * nPercent)) / 2);
}
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.Clear(Color.Magenta);
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto, new Rectangle(destX, destY, destWidth, destHeight), new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;
}
the original images (before fixed size) range anywhere from 2MB to 20MB, the image returned (max(len(image)) in the table is around 750 KB. (Edit: Corrected files sizes)
Number of images per folder ~100-150
I've looked and debugged, but cannot find what is causing the OOM issues, could someone point me at the error, or offer a better optimization for what I am doing?

If this was a code review, there would be many things I'd suggest as improvements in this code...
But anyway, specifically to your question.. you memory leak is in following lines of code (please don't take it personally, but it was hard to spot, because the code is not as clean)
timg = System.Drawing.Image.FromStream(tstream);
tstream.Dispose();
timg = Requests.FixedSize(timg, 600, 600);
....
timg.Dispose();
You have 2 timg here.. one is original, and the second one is the one you get back from Requests.FixedSize. The timg you passed to Requests.FixedSize does not get disposed.

Related

Parameter is not valid while try to save image

I have this method in FileUtility Class to save my images.
public static void SaveImage(System.IO.Stream file, string savePath, Size size, bool enforceRatio, bool testReverse = false)
{
var image = Image.FromStream(file);
var imageEncoders = ImageCodecInfo.GetImageEncoders();
int enc = Path.GetExtension(savePath).ToLower().Contains("png") ? 4 : 1;
EncoderParameters encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 90L);
Size s = new Size(size.Width, size.Height);
if (testReverse)
{
if (image.Width <= image.Height)
{
if (size.Width <= size.Height)
{
s.Width = size.Width;
s.Height = size.Height;
}
else
{
s.Width = size.Height;
s.Height = size.Width;
}
}
else
{
if (size.Width <= size.Height)
{
s.Width = size.Height;
s.Height = size.Width;
}
else
{
s.Width = size.Width;
s.Height = size.Height;
}
}
}
var canvasWidth = s.Width;
var canvasHeight = s.Height;
var newImageWidth = s.Width;
var newImageHeight = s.Height;
var xPosition = 0;
var yPosition = 0;
if (enforceRatio)
{
var ratioX = s.Width / (double)image.Width;
var ratioY = s.Height / (double)image.Height;
var ratio = ratioX < ratioY ? ratioX : ratioY;
newImageHeight = (int)(image.Height * ratio);
newImageWidth = (int)(image.Width * ratio);
}
var thumbnail = new Bitmap(canvasWidth, canvasHeight);
var graphic = Graphics.FromImage(thumbnail);
if (enforceRatio)
{
graphic.Clear(Color.White);
}
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.HighQuality;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.CompositingQuality = CompositingQuality.HighQuality;
graphic.DrawImage(image, xPosition, yPosition, newImageWidth, newImageHeight);
thumbnail.Save(savePath, imageEncoders[enc], encoderParameters);
}
It work well. But for some images files (not every file) I get
Argument Exception : Parameter is not valid
in first line var image = Image.FromStream(file);
I call method like this:
FileUtility.SaveImage(add2.IconSquare.InputStream, Server.MapPath(program.IconSquare), new System.Drawing.Size { Width = 250, Height = 250 }, false);
That add2.IconSquare is a HttpPostedFileBase
public HttpPostedFileBase IconSquare { get; set; }
The only thing is that add2 come from another action with TempData.
var add2 = TempData["Create_Step2"] as AddStep2;
I mean I take files from user in Action Create_Step2 and save them in TempData then I try to save them in Action Create_Step3. Can anyone tell me what I doing wrong?

End of Stream Parsing Error

public static Image Crop(Image imgPhoto, int Width, int Height, AnchorPosition Anchor)
{
if (imgPhoto == null)
{
return null;
}
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)Width / (float)sourceWidth);
nPercentH = ((float)Height / (float)sourceHeight);
if (nPercentH < nPercentW)
{
nPercent = nPercentW;
switch (Anchor)
{
case AnchorPosition.Top:
destY = 0;
break;
case AnchorPosition.Bottom:
destY = (int)(Height - (sourceHeight * nPercent));
break;
default:
destY = (int)((Height - (sourceHeight * nPercent)) / 2);
break;
}
}
else
{
nPercent = nPercentH;
switch (Anchor)
{
case AnchorPosition.Left:
destX = 0;
break;
case AnchorPosition.Right:
destX = (int)(Width - (sourceWidth * nPercent));
break;
default:
destX = (int)((Width - (sourceWidth * nPercent)) / 2);
break;
}
}
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX, destY, destWidth, destHeight),
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;
}
public byte[] ImageToByteArray(string path)
{
FileInfo info = new FileInfo(path);
long sizeByte = info.Length;
FileStream fs = new FileStream(path,FileMode.Open,FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
byte[] data = br.ReadBytes((int) sizeByte);
return data;
}
public byte[] ImageToByteArray(Image img)
{
if (img == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, img);
return ms.ToArray();
}
public Image BrowseImage(Image image)
{
OpenFileDialog open = new OpenFileDialog();
open.FileName = string.Empty;
open.Filter = "Image Files(*.png; *.jpg; *.jpeg; *.gif; *.bmp)|*.png; *.jpg; *.jpeg; *.gif; *.bmp";
if (open.ShowDialog() == DialogResult.OK)
{
Image img = new Bitmap(open.FileName);
if ((img.Width < 200) || (img.Height < 200))
{
MessageBox.Show("Minimum size is 200x200.");
BrowseImage(image);
}
else
{
return img;
}
}
return image;
}
in saving image
picItem.Image = Crop(BrowseImage(picItem.Image), 200, 200, ImageUtil.AnchorPosition.Center);
//set Datatable row
erow["Image"] = img.ImageToByteArray(picItem.Image);
//Saving is ok
//When i View
picItem.Image = ByteArrayToImage((byte[])source.Image.binaryFromDB);
>Error: End of Stream encountered before parsing was completed?
this is all the method ive use. i crop the image so that it will have a minimum size..ive tried any convertion but no help.
i just want to save an image to database and when i view i can see the image in picture box.
#MarcGravell I found the problem. u right man.when i store the byte in datatable it stores a value System.Byte[] not the actual bytes.. when i get all the value in datatable and put it in a query "Insert into table values('System.Byte[]'). .it stores a string System.Byte" not the binary data..
You've loaded all the data into the MemoryStream and rewound the stream - all good (although new MemoryStream(byteArrayIn) would have been easier).
This leaves one simple possibility: the array truly does not contain all of the data that it should have.
Check how you got the array, and all intermediary steps. In particular, add some debug code to note the length of the array when you write it, and check that you got all of it. If the length is the same, check that the contents are identical byte-for-byte (comparing the output of Convert.ToBase64String is probably the most convenient way of doing that for ad-hoc usage).
If you are writing streams, check a few things:
if using a Stream.Read/Stream.Write loop, check you are using the return value from Read correctly; or easier - just use Stream.CopyTo instead (this has a correctly-implemented Read/Write loop)
if using MemoryStream, make sure you understand the difference between ToArray and GetBuffer, and the implications of each
if you are transferring the data at any point, make sure you are treating it as binary at all times - never text. No StreamReader / StreamWriter / Encoding / GetString / anything like that

Image Manipulation - auto resize / crop for thumbnails

I have hit a brick wall with this... I know my flaw is in the logic somehow but I'll explain where I'm at.
I'm (trying) to write code to dynamically create a square (75x75) pixel thumbnail for a navigation bar along the bottom of my Silverlight app.
When I debug my code below I keep getting an "Array index out of bounds" error during the scaling nested loops
(I've only debugged with srcWidth > srcHeight, one step at a time)
The source image I'm testing with is 307x162 (49734 pixels)
The dest size (per current logic) for this is 150x75 (11250 pixels)
Of course after this then I intend to crop the result down to 75x75
It's only getting about half through the source image before hitting 11251 as the index of the destination.
I know it's my logic,
I just don't know if I went wrong in the sizes I used to construct the destination,
or in the approximations used from casting the floats to ints,
or maybe it's neither
I don't know, which is why I'm posting here... anyhow, here's my source:
private void ResizeNavBarImage(Image src)
{
const int SizeOfRGB = 4;
WriteableBitmap bmpSource = new WriteableBitmap((BitmapSource)src.Source);
int[] iSourcePixels = bmpSource.Pixels;
int srcWidth = bmpSource.PixelWidth;
int srcHeight = bmpSource.PixelHeight;
int destWidth = 75;
int destHeight = 75;
float xFactor = srcWidth / destWidth;
float yFactor = srcHeight / destHeight;
float xSource, ySource;
int iApprox;
int iIndex = 0;
if (srcWidth > srcHeight)
{
WriteableBitmap bmpDest = new WriteableBitmap((int)(destWidth * yFactor), destHeight);
int[] iDestPixels = bmpDest.Pixels;
// Resize srcHeight to destHeight, srcWidth to same ratio
for (int i = 0; i < srcHeight; i++)
{
for (int j = 0; j < srcWidth; j++)
{
xSource = j * yFactor;
ySource = i * yFactor;
iApprox = (int)(ySource * srcWidth + xSource);
iDestPixels[iIndex++] = iSourcePixels[iApprox];
}
}
// Crop half of difference from each side of the width
srcWidth = bmpDest.PixelWidth;
srcHeight = bmpDest.PixelHeight;
int xLeftOffset = (srcWidth - srcHeight) / 2;
WriteableBitmap bmpFinalDest = new WriteableBitmap(destWidth, destHeight);
for (int iPixelRow = 0; iPixelRow < destHeight; iPixelRow++)
{
int srcOffset = (iPixelRow * srcWidth + xLeftOffset) * SizeOfRGB;
int destOffset = iPixelRow * destWidth * SizeOfRGB;
Buffer.BlockCopy(bmpDest.Pixels, srcOffset, bmpFinalDest.Pixels, destOffset, destWidth * SizeOfRGB);
}
src.Source = (ImageSource)bmpFinalDest;
}
else if (srcWidth < srcHeight)
{
WriteableBitmap bmpDest = new WriteableBitmap(destWidth, (int)(destHeight * xFactor));
int[] iDestPixels = bmpDest.Pixels;
// Resize srcWidth to destWidth, srcHeight to same ratio
for (int i = 0; i < srcHeight; i++)
{
for (int j = 0; j < srcWidth; j++)
{
xSource = j * xFactor;
ySource = i * xFactor;
iApprox = (int)(ySource * srcWidth + xSource);
iDestPixels[iIndex++] = iSourcePixels[iApprox];
}
}
// Crop half of difference from each side of the height
srcWidth = bmpDest.PixelWidth;
srcHeight = bmpDest.PixelHeight;
int yTopOffset = (srcHeight - srcWidth) / 2;
WriteableBitmap bmpFinalDest = new WriteableBitmap(destWidth, destHeight);
for (int iPixelRow = yTopOffset; iPixelRow < (destHeight - (yTopOffset * 2)); iPixelRow++)
{
int srcOffset = iPixelRow * srcWidth * SizeOfRGB;
int destOffset = iPixelRow * destWidth * SizeOfRGB;
Buffer.BlockCopy(bmpDest.Pixels, srcOffset, bmpFinalDest.Pixels, destOffset, destWidth * SizeOfRGB);
}
src.Source = (ImageSource)bmpFinalDest;
}
else // (srcWidth == srcHeight)
{
WriteableBitmap bmpDest = new WriteableBitmap(destWidth, destHeight);
int[] iDestPixels = bmpDest.Pixels;
// Resize and set source
for (var i = 0; i < srcHeight; i++)
{
for (var j = 0; j < srcWidth; j++)
{
xSource = j * xFactor;
ySource = i * yFactor;
iApprox = (int)(ySource * srcWidth + xSource);
iDestPixels[iIndex++] = iSourcePixels[iApprox];
}
}
src.Source = (ImageSource)bmpDest;
}
}
===============================================================================
Here's my working code (with WriteableBitmapEx) for posterity:
private void ResizeNavBarImage(Image src)
{
WriteableBitmap bmpSource = new WriteableBitmap((BitmapSource)src.Source);
int srcWidth = bmpSource.PixelWidth;
int srcHeight = bmpSource.PixelHeight;
int finalDestWidth = 75;
int finalDestHeight = 75;
// Resize
float xFactor = ((float)finalDestWidth / (float)srcWidth);
float yFactor = ((float)finalDestHeight / (float)srcHeight);
float Factor = 0;
if (xFactor < yFactor)
Factor = yFactor;
else
Factor = xFactor;
int destWidth = (int)(srcWidth * Factor);
int destHeight = (int)(srcHeight * Factor);
if (destWidth < destHeight && destWidth != finalDestWidth)
destWidth = finalDestWidth;
else if (destWidth > destHeight && destHeight != finalDestHeight)
destHeight = finalDestHeight;
WriteableBitmap bmpDest = bmpSource.Resize(destWidth, destHeight, WriteableBitmapExtensions.Interpolation.Bilinear);
// Crop
int Offset;
WriteableBitmap bmpFinalDest = new WriteableBitmap(finalDestWidth, finalDestHeight);
if (destWidth > destHeight)
{
Offset = (bmpDest.PixelWidth - bmpDest.PixelHeight) / 2;
if (finalDestWidth % 2 != 0 && Offset % 2 == 0)
Offset -= 1;
bmpFinalDest = bmpDest.Crop(Offset, 0, finalDestWidth, finalDestHeight);
}
else if (destWidth < destHeight)
{
Offset = (bmpDest.PixelHeight - bmpDest.PixelWidth) / 2;
if (finalDestHeight % 2 != 0 && Offset % 2 == 0)
Offset -= 1;
bmpFinalDest = bmpDest.Crop(0, Offset, finalDestWidth, finalDestHeight);
}
else
bmpFinalDest = bmpDest;
src.Source = (ImageSource)bmpFinalDest;
}
Your loops for i and j are going to srcHeight and srcWidth instead of destHeight and destWidth.
That's probably not the last bug in this code either.
I agree with Mark Ransom, the correct way to resize the image would be to draw into another image using a Graphics object.
http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing
This will allow you to use different, better filters to get good image quality, not to mention speed.
Why not use the built-in scale functionality of WriteableBitmap?
WriteableBitmap wb = new WriteableBitmap(src, new ScaleTransform() { ScaleX = 0.25, ScaleY = 0.25 });
wb.Invalidate();
src.Source = wb;

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.

Resizing image programmatically in C# [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Resize an Image C#
How can I programmatically resize an image in C# so that it'll fit in a winforms control?
Scaling an image into a PictureBox:
class ImageHandling
{
public static Rectangle GetScaledRectangle(Image img, Rectangle thumbRect)
{
if (img.Width < thumbRect.Width && img.Height < thumbRect.Height)
return new Rectangle(thumbRect.X + ((thumbRect.Width - img.Width) / 2), thumbRect.Y + ((thumbRect.Height - img.Height) / 2), img.Width, img.Height);
int sourceWidth = img.Width;
int sourceHeight = img.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)thumbRect.Width / (float)sourceWidth);
nPercentH = ((float)thumbRect.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
if (destWidth.Equals(0))
destWidth = 1;
if (destHeight.Equals(0))
destHeight = 1;
Rectangle retRect = new Rectangle(thumbRect.X, thumbRect.Y, destWidth, destHeight);
if (retRect.Height < thumbRect.Height)
retRect.Y = retRect.Y + Convert.ToInt32(((float)thumbRect.Height - (float)retRect.Height) / (float)2);
if (retRect.Width < thumbRect.Width)
retRect.X = retRect.X + Convert.ToInt32(((float)thumbRect.Width - (float)retRect.Width) / (float)2);
return retRect;
}
public static Image GetResizedImage(Image img, Rectangle rect)
{
Bitmap b = new Bitmap(rect.Width, rect.Height);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(img, 0, 0, rect.Width, rect.Height);
g.Dispose();
try
{
return (Image)b.Clone();
}
finally
{
b.Dispose();
b = null;
g = null;
}
}
}
And how to use it:
Image img = Image.FromFile(imageFilePath);
Rectangle newRect = GetScaledRectangle(img, pictureBox1.ClientRectangle);
pictureBox1.Image = ImageHandling.GetResizedImage(img, newRect);
Sacle and center an ImageBox:
private void LoadAndResizeImage(string sImagepath, int iMaxHeight, int iMaxWidth, int iMinX, int iMinY)
{
int wdt = iMaxWidth;
int hgt = iMaxHeight;
int partialX = iMinX;
int partialY = iMinY;
pictureBox1.ImageLocation = sImagepath;
if ((pictureBox1.Image.Height > iMaxHeight) || (pictureBox1.Image.Width > iMaxWidth))
{
if ((pictureBox1.Image.Width / iMaxWidth) > (pictureBox1.Image.Height / iMaxHeight))
{
wdt = iMaxWidth;
double ratio = (double)pictureBox1.Image.Height / (double)pictureBox1.Image.Width;
hgt = (int)(iMaxWidth * ratio);
}
else
{
hgt = iMaxHeight;
double ratio = (double)pictureBox1.Image.Width / (double)pictureBox1.Image.Height;
wdt = (int)(iMaxHeight * ratio);
}
}
else
{
hgt = pictureBox1.Image.Height;
wdt = pictureBox1.Image.Width;
}
if (wdt < iMaxWidth)
{
partialX = (iMaxWidth - wdt) / 2;
partialX += iMinX;
}
else
{
partialX = iMinX;
}
if (hgt < iMaxHeight)
{
partialY = (iMaxHeight - hgt) / 2;
partialY += iMinY;
}
else
{
partialY = iMinY;
}
//Set size
pictureBox1.Height = hgt;
pictureBox1.Width = wdt;
pictureBox1.Left = partialX;
pictureBox1.Top = partialY;
}

Categories