Please help me correct the small bugs in this image editor

Posted by Alex on Stack Overflow See other posts from Stack Overflow or by Alex
Published on 2010-12-21T05:19:24Z Indexed on 2010/12/21 5:31 UTC
Read the original article Hit count: 491

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:

alt text

© Stack Overflow or respective owner

Related posts about c#

Related posts about ASP.NET