Please help me correct the small bugs in this image editor
- by Alex
Hi, I'm working on a website that will sell hand made jewelry and I'm finishing the image editor, but it's not behaving quite right.
Basically, the user uploads an image which will be saved as a source and then it will be resized to fit the user's screen and saved as a temp. The user will then go to a screen that will allow them to crop the image and then save it to it's final versions.
All of that works fine, except, the final versions have 3 bugs. First is some black horizontal line on the very bottom of the image. Second is an outline of sorts that follows the edges. I thought it was because I was reducing the quality, but even at 100% it still shows up... And lastly, I've noticed that the cropped image is always a couple of pixels lower than what I'm specifying...
Anyway, I'm hoping someone whose got experience in editing images with C# can maybe take a look at the code and see where I might be going off the right path.
Oh, by the way, this in an ASP.NET MVC application.
Here's the code:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web;
namespace Website.Models.Providers {
public class ImageProvider {
private readonly ProductProvider ProductProvider = null;
private readonly EncoderParameters HighQualityEncoder = new EncoderParameters();
private readonly ImageCodecInfo JpegCodecInfo = ImageCodecInfo.GetImageEncoders().Single(
c =>
(c.MimeType == "image/jpeg"));
private readonly string Path = HttpContext.Current.Server.MapPath("~/Resources/Images/Products");
private readonly short[][] Dimensions = new short[3][] {
new short[2] {
640,
480
},
new short[2] {
240,
0
},
new short[2] {
80,
60
}
};
//////////////////////////////////////////////////////////
// Constructor //////////////////////////////////////////
//////////////////////////////////////////////////////////
public ImageProvider(
ProductProvider ProductProvider) {
this.ProductProvider = ProductProvider;
HighQualityEncoder.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
}
//////////////////////////////////////////////////////////
// Crop //////////////////////////////////////////////
//////////////////////////////////////////////////////////
public void Crop(
string FileName,
Image Image,
Crop Crop) {
using (Bitmap Source = new Bitmap(Image)) {
using (Bitmap Target = new Bitmap(Crop.Width, Crop.Height)) {
using (Graphics Graphics = Graphics.FromImage(Target)) {
Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
Graphics.SmoothingMode = SmoothingMode.HighQuality;
Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
Graphics.CompositingQuality = CompositingQuality.HighQuality;
Graphics.DrawImage(Source, new Rectangle(0, 0, Target.Width, Target.Height), new Rectangle(Crop.Left, Crop.Top, Crop.Width, Crop.Height), GraphicsUnit.Pixel);
};
Target.Save(FileName, JpegCodecInfo, HighQualityEncoder);
};
};
}
//////////////////////////////////////////////////////////
// Crop & Resize //////////////////////////////////////
//////////////////////////////////////////////////////////
public void CropAndResize(
Product Product,
Crop Crop) {
using (Image Source = Image.FromFile(String.Format("{0}/{1}.source", Path, Product.ProductId))) {
using (Image Temp = Image.FromFile(String.Format("{0}/{1}.temp", Path, Product.ProductId))) {
float Percent = ((float)Source.Width / (float)Temp.Width);
short Width = (short)(Temp.Width * Percent);
short Height = (short)(Temp.Height * Percent);
Crop.Height = (short)(Crop.Height * Percent);
Crop.Left = (short)(Crop.Left * Percent);
Crop.Top = (short)(Crop.Top * Percent);
Crop.Width = (short)(Crop.Width * Percent);
Img Img = new Img();
this.ProductProvider.AddImageAndSave(Product, Img);
this.Crop(String.Format("{0}/{1}.cropped", Path, Img.ImageId), Source, Crop);
using (Image Cropped = Image.FromFile(String.Format("{0}/{1}.cropped", Path, Img.ImageId))) {
this.Resize(this.Dimensions[0], String.Format("{0}/{1}-L.jpg", Path, Img.ImageId), Cropped, HighQualityEncoder);
this.Resize(this.Dimensions[1], String.Format("{0}/{1}-T.jpg", Path, Img.ImageId), Cropped, HighQualityEncoder);
this.Resize(this.Dimensions[2], String.Format("{0}/{1}-S.jpg", Path, Img.ImageId), Cropped, HighQualityEncoder);
};
};
};
this.Purge(Product);
}
//////////////////////////////////////////////////////////
// Queue //////////////////////////////////////////////
//////////////////////////////////////////////////////////
public void QueueFor(
Product Product,
HttpPostedFileBase PostedFile) {
using (Image Image = Image.FromStream(PostedFile.InputStream)) {
this.Resize(new short[2] {
1152,
0
}, String.Format("{0}/{1}.temp", Path, Product.ProductId), Image, HighQualityEncoder);
};
PostedFile.SaveAs(String.Format("{0}/{1}.source", Path, Product.ProductId));
}
//////////////////////////////////////////////////////////
// Purge //////////////////////////////////////////////
//////////////////////////////////////////////////////////
private void Purge(
Product Product) {
string Source = String.Format("{0}/{1}.source", Path, Product.ProductId);
string Temp = String.Format("{0}/{1}.temp", Path, Product.ProductId);
if (File.Exists(Source)) {
File.Delete(Source);
};
if (File.Exists(Temp)) {
File.Delete(Temp);
};
foreach (Img Img in Product.Imgs) {
string Cropped = String.Format("{0}/{1}.cropped", Path, Img.ImageId);
if (File.Exists(Cropped)) {
File.Delete(Cropped);
};
};
}
//////////////////////////////////////////////////////////
// Resize //////////////////////////////////////////////
//////////////////////////////////////////////////////////
public void Resize(
short[] Dimensions,
string FileName,
Image Image,
EncoderParameters EncoderParameters) {
if (Dimensions[1] == 0) {
Dimensions[1] = (short)(Image.Height / ((float)Image.Width / (float)Dimensions[0]));
};
using (Bitmap Bitmap = new Bitmap(Dimensions[0], Dimensions[1])) {
using (Graphics Graphics = Graphics.FromImage(Bitmap)) {
Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
Graphics.SmoothingMode = SmoothingMode.HighQuality;
Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
Graphics.CompositingQuality = CompositingQuality.HighQuality;
Graphics.DrawImage(Image, 0, 0, Dimensions[0], Dimensions[1]);
};
Bitmap.Save(FileName, JpegCodecInfo, EncoderParameters);
};
}
}
}
Here's one of the images this produces: