Tuesday, June 1, 2010

Image Resizing Extension

Sharing my Image Resizing Extension. Aspect ratio maintained



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

using System.IO;


namespace MycImageExtension
{
    public static class Helper
    {

        public static Image Clip(this Image imgPhoto, int width, int height)
        {
            return Clip(imgPhoto, width, height, false);
        }

        public static Image ToImage(this byte[] ba)
        {
            var ms = new MemoryStream(ba);
            return Image.FromStream(ms);
        }

        public static byte[] ToArray(this Image imgPhoto)
        {
            var ms = new MemoryStream();
            imgPhoto.Save(ms, ici, eps);
            imgPhoto.Save(ms, ImageFormat.Jpeg);
            return ms.ToArray();
        }


        static ImageCodecInfo GetImageCodec(string mimetype)
        {
            foreach (ImageCodecInfo ici in ImageCodecInfo.GetImageEncoders())
            {
                if (ici.MimeType == mimetype) return ici;
            }
            return null;
        }





        public static Image Clip(this Image imgPhoto, int width, int height, bool stretch)
        {
            if (!stretch && (imgPhoto.Width <= width && imgPhoto.Height <= height))
                return imgPhoto;


            var d = new Dimension(imgPhoto.Width, imgPhoto.Height);
            double scale = d.NewSizeScaleFactor(new Dimension(width, height), stretch);

            var newD = scale * d;




            if (stretch)
            {

                if (!(newD.Width == width || newD.Height == height))
                    throw new Exception("Stretching algo has some error");
            }



            var bmPhoto = new Bitmap(imgPhoto, new Size(newD.Width, newD.Height));

                        

            return bmPhoto;
        }




        // just for crystal report
        public static Image PadImage(this Image imgPhoto, int width, int height)
        {
            var d = new Dimension(imgPhoto.Width, imgPhoto.Height);
            double scale = d.NewSizeScaleFactor(new Dimension(width, height), true);

            Dimension newSize = scale * d;


            PadAt padAt;
            int padNeeded;
            newSize.GetPadNeeded(new Dimension(width, height), out padAt, out padNeeded);


            int padLeft = 0, padTop = 0;

            if (padAt == PadAt.Width)
                padLeft = padNeeded;
            else if (padAt == PadAt.Height)
                padTop = padNeeded;



            var bmPhoto = new Bitmap(width, height, PixelFormat.Format24bppRgb);



            var grPhoto = Graphics.FromImage(bmPhoto);
            grPhoto.Clear(Color.White);

            grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;

            grPhoto.DrawImage(imgPhoto,
                new Rectangle(padLeft, padTop, newSize.Width, newSize.Height),
                new Rectangle(0, 0, imgPhoto.Width, imgPhoto.Height),
                GraphicsUnit.Pixel);

            grPhoto.Dispose();

            return bmPhoto;

        }


    }







    public enum PadAt { None = 0, Width = 1, Height }


    public struct Dimension
    {
        public int Width { set; get; }
        public int Height { set; get; }



        public Dimension(int width, int height)
            : this()
        {
            this.Width = width;
            this.Height = height;
        }

        public override string ToString()
        {
            return string.Format("Width: {0} Height: {1}", Width, Height);
        }


        public static Dimension operator *(Dimension src, double scale)
        {
            return new Dimension((int)Math.Ceiling((scale * src.Width)), (int)Math.Ceiling((scale * src.Height)));
        }


        public static Dimension operator *(double scale, Dimension src)
        {
            return new Dimension((int)Math.Ceiling((scale * src.Width)), (int)Math.Ceiling((scale * src.Height)));
        }


        public double NewSizeScaleFactor(Dimension newSize, bool stretch)
        {
            

            if (!stretch
                &&

                (this.Width <= newSize.Width && this.Height <= newSize.Height))

                return 1;


            double widthScaleFactor = (double)newSize.Width / this.Width;
            double heightScaleFactor = (double)newSize.Height / this.Height;



            // return the lowest scale factor

            if (widthScaleFactor < heightScaleFactor)
                return widthScaleFactor;
            else if (heightScaleFactor < widthScaleFactor)
                return heightScaleFactor;
            else
                return widthScaleFactor; // can even use heightscalefactor
        }


        public Dimension Clip(Dimension newSize, bool stretch)
        {
            if (!stretch
                &&

                (this.Width <= newSize.Width && this.Height <= newSize.Height))

                return new Dimension(this.Width, this.Height);



            double smallestScaleFactor = NewSizeScaleFactor(newSize, stretch);


            return new Dimension((int)(this.Width * smallestScaleFactor), (int)(this.Height * smallestScaleFactor));
        }




        // so crystal report would have exact dimension
        public void GetPadNeeded(Dimension newSize, out PadAt padAt, out int padNeeded)
        {

            if (this.Width == newSize.Width && this.Height == newSize.Height)
            {
                padAt = PadAt.None;
                padNeeded = 0;
                return;
            }



            if (this.Width > newSize.Width || this.Height > newSize.Height)
                throw new Exception("Source cannot be bigger than the new size");


            if (this.Width != newSize.Width && this.Height != newSize.Height)
                throw new Exception("At least one side should be equal");


            if (newSize.Width != this.Width)
            {
                padAt = PadAt.Width;
                padNeeded = (newSize.Width - this.Width) / 2;
            }
            else if (newSize.Height != this.Height)
            {
                padAt = PadAt.Height;
                padNeeded = (newSize.Height - this.Height) / 2;
            }
            else
            {
                throw new Exception("Some anomaly occured, contact the programmer");
            }

        }






        public static void Main()
        {
            var ls = new Dimension[]
            {
                new Dimension(400, 400),
                new Dimension(640, 480),
                new Dimension(600, 480),
                new Dimension(800, 600),
                new Dimension(800, 400),
                new Dimension(1280, 960),
                new Dimension(1280, 961),
                new Dimension(1281, 960),
                new Dimension(1280, 900),
                new Dimension(1000, 960),
                new Dimension(1000, 970),
                new Dimension(1000, 900),

                new Dimension(1380, 960),
                new Dimension(1280, 1000),

                new Dimension(1380, 1300),
                
                new Dimension(1600, 1200),
                new Dimension(1600, 1000),
                new Dimension(1800, 1200),
                new Dimension(1800, 1000),
                new Dimension(1400, 1200),
                new Dimension(1400, 1000),
                new Dimension(960, 1280), 
                new Dimension(960, 1300), 
                new Dimension(970, 1280)
            };





            foreach (var l in ls)
            {
                // display to crystal report...
                double scaleA = l.NewSizeScaleFactor(new Dimension(800, 600), true);
                Dimension newSizeA = scaleA * l;

                Console.WriteLine("Old: {0}    New: {1} Same: {2}", l, newSizeA, l == newSizeA);

                PadAt padAt;
                int padNeeded;
                newSizeA.GetPadNeeded(new Dimension(800, 600), out padAt, out padNeeded);

                // ...display to crystal report

                Console.WriteLine("Pad {0} {1}", padAt, padNeeded);

                
            }

            Console.ReadLine();
        }//Main Test

      
        

    }




}


Sample Output:
Old: Width: 400 Height: 400    New: Width: 600 Height: 600 Same: False Pad Width 100
Old: Width: 640 Height: 480    New: Width: 800 Height: 600 Same: False Pad None 0
Old: Width: 600 Height: 480    New: Width: 750 Height: 600 Same: False Pad Width 25
Old: Width: 800 Height: 600    New: Width: 800 Height: 600 Same: True Pad None 0
Old: Width: 800 Height: 400    New: Width: 800 Height: 400 Same: True Pad Height 100
Old: Width: 1280 Height: 960    New: Width: 800 Height: 600 Same: False Pad None 0
Old: Width: 1280 Height: 961    New: Width: 800 Height: 600 Same: False Pad None 0
Old: Width: 1281 Height: 960    New: Width: 800 Height: 600 Same: False Pad None 0
Old: Width: 1280 Height: 900    New: Width: 800 Height: 563 Same: False Pad Height 18
Old: Width: 1000 Height: 960    New: Width: 625 Height: 600 Same: False Pad Width 87
Old: Width: 1000 Height: 970    New: Width: 619 Height: 600 Same: False Pad Width 90
Old: Width: 1000 Height: 900    New: Width: 667 Height: 600 Same: False Pad Width 66
Old: Width: 1380 Height: 960    New: Width: 800 Height: 557 Same: False Pad Height 21
Old: Width: 1280 Height: 1000    New: Width: 768 Height: 600 Same: False Pad Width 16
Old: Width: 1380 Height: 1300    New: Width: 637 Height: 600 Same: False Pad Width 81
Old: Width: 1600 Height: 1200    New: Width: 800 Height: 600 Same: False Pad None 0
Old: Width: 1600 Height: 1000    New: Width: 800 Height: 500 Same: False Pad Height 50
Old: Width: 1800 Height: 1200    New: Width: 800 Height: 534 Same: False Pad Height 33
Old: Width: 1800 Height: 1000    New: Width: 800 Height: 445 Same: False Pad Height 77
Old: Width: 1400 Height: 1200    New: Width: 700 Height: 600 Same: False Pad Width 50
Old: Width: 1400 Height: 1000    New: Width: 800 Height: 572 Same: False Pad Height 14
Old: Width: 960 Height: 1280    New: Width: 450 Height: 600 Same: False Pad Width 175
Old: Width: 960 Height: 1300    New: Width: 444 Height: 600 Same: False Pad Width 178
Old: Width: 970 Height: 1280    New: Width: 455 Height: 600 Same: False Pad Width 172

No comments:

Post a Comment