Search code examples
c#imageasp.net-mvc-4asp.net-web-apiimage-scaling

Getting bigger size image while scaling C#


I am trying to scale the original image to 50% and 25% and try to download the scaled image in MVC. I am using the below code which was taken from Google search.

public byte[] ScaleImageByPercent(byte[] imageBuffer, int Percent)
    {

        using (Stream imageStream = new MemoryStream(imageBuffer))
        {
            using (Image scaleImage = Image.FromStream(imageStream))
            {
                float scalePercent = ((float)Percent / 100);

                int originalWidth = scaleImage.Width;
                int originalHeight = scaleImage.Height;
                int originalXPoint = 0;
                int originalYPoint = 0;

                int scaleXPoint = 0;
                int scaleYPoint = 0;
                int scaleWidth = (int)(originalWidth * scalePercent);
                int scaleHeight = (int)(originalHeight * scalePercent);

                using (Bitmap scaleBitmapImage = new Bitmap(scaleWidth, scaleHeight, PixelFormat.Format24bppRgb))
                {
                    scaleBitmapImage.SetResolution(scaleImage.HorizontalResolution, scaleImage.VerticalResolution);
                    Graphics graphicImage = Graphics.FromImage(scaleBitmapImage);
                    graphicImage.CompositingMode = CompositingMode.SourceCopy;
                    graphicImage.InterpolationMode = InterpolationMode.NearestNeighbor;
                    graphicImage.DrawImage(scaleImage,
                        new Rectangle(scaleXPoint, scaleYPoint, scaleWidth, scaleHeight),
                        new Rectangle(originalXPoint, originalYPoint, originalWidth, originalHeight),
                        GraphicsUnit.Pixel);
                    graphicImage.Dispose();

                    ImageConverter converter = new ImageConverter();
                    return (byte[])converter.ConvertTo(scaleBitmapImage, typeof(byte[]));
                }
            }
        }
    }

When i use 3.4MB image its returning 4.7MB in 50% and even worst in 100% its returning 18 MB.

EDIT: After getting the byte array i am downloading the image using below code. After downloading while i check the file size in disk its showing bigger size.

        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        result.Content = new StreamContent(new MemoryStream(scaledBytes));
        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        return result;

Am i doing the scaling correctly?. Which one i need to change get the lower size image while scaling using above functionality.


Solution

  • Your code works, I believe it's just a matter of image compression, basically you are pushing your byte array to your output stream as is, while you should save it as a jpeg. In my example I use a FileStream for simplicity, in your case you should use your output stream. Give this a try (just drop any Jpg file on the compiled executable):

    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication3
    {
        class Program
        {
            static void Main(string[] args)
            {
                string filePath = System.IO.Path.GetFullPath(args[0]);
                byte[] originalImage = System.IO.File.ReadAllBytes(filePath);
                byte[] resizedImage = ScaleImageByPercent(originalImage, 50);
                using (Stream imageStream = new MemoryStream(resizedImage))
                {
                    using (Image scaleImage = Image.FromStream(imageStream))
                    {
                        string outputPath = System.IO.Path.GetDirectoryName(filePath);
                    outputPath = System.IO.Path.Combine(outputPath, $"{System.IO.Path.GetFileNameWithoutExtension(filePath)}_resized.jpg");
                    using (FileStream outputFile = System.IO.File.Open(outputPath, FileMode.Create, FileAccess.Write))
                    {
                        scaleImage.Save(outputFile, ImageFormat.Jpeg);
                    }
                }
            }
        }
        public static byte[] ScaleImageByPercent(byte[] imageBuffer, int Percent)
        {
    
            using (Stream imageStream = new MemoryStream(imageBuffer))
            {
                using (Image scaleImage = Image.FromStream(imageStream))
                {
                    float scalePercent = ((float)Percent / 100);
    
                    int originalWidth = scaleImage.Width;
                    int originalHeight = scaleImage.Height;
                    int originalXPoint = 0;
                    int originalYPoint = 0;
    
                    int scaleXPoint = 0;
                    int scaleYPoint = 0;
                    int scaleWidth = (int)(originalWidth * scalePercent);
                    int scaleHeight = (int)(originalHeight * scalePercent);
    
                    using (Bitmap scaleBitmapImage = new Bitmap(scaleWidth, scaleHeight, PixelFormat.Format24bppRgb))
                    {
                        scaleBitmapImage.SetResolution(scaleImage.HorizontalResolution, scaleImage.VerticalResolution);
                        Graphics graphicImage = Graphics.FromImage(scaleBitmapImage);
                        graphicImage.CompositingMode = CompositingMode.SourceCopy;
                        graphicImage.InterpolationMode = InterpolationMode.NearestNeighbor;
                        graphicImage.DrawImage(scaleImage,
                            new Rectangle(scaleXPoint, scaleYPoint, scaleWidth, scaleHeight),
                            new Rectangle(originalXPoint, originalYPoint, originalWidth, originalHeight),
                            GraphicsUnit.Pixel);
                        graphicImage.Dispose();
    
                        ImageConverter converter = new ImageConverter();
                        return (byte[])converter.ConvertTo(scaleBitmapImage, typeof(byte[]));
                    }
                }
            }
        }
    }
    }
    

    Here it is the result:

    enter image description here

    EDIT: Ok for the webapi interface try doing like this:

                HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    
            using (Stream imageStream = new MemoryStream(resizedImage))
            {
                using (Image scaleImage = Image.FromStream(imageStream))
                {
                    using (MemoryStream ms = new MemoryStream())
                    {
                        scaleImage.Save(ms, ImageFormat.Jpeg);
                        result.Content = new StreamContent(ms);
                        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                        result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
                    }
                }
            }
            return result;