Search code examples
c#imagerotationimage-resizing

what is the reason of increasing image size in rotation?


I have a c# application that contains an image gallery where I display some pictures. This gallery have some features including left and right rotation. everything is perfect but when I choose a picture from gallery and press rotation button (regardless left or right rotation), size of the picture increase significantly. It should be mentioned that the picture's format is JPEG.

Size of picture before rotation : 278 kb

Size of picture after rotation : 780 kb

My code for rotation is like bellow :

 public Image apply(Image img)
    {  
        Image im = img;
        if (rotate == 1) im.RotateFlip(RotateFlipType.Rotate90FlipNone);
        if (rotate == 2) im.RotateFlip(RotateFlipType.Rotate180FlipNone);
        if (rotate == 3) im.RotateFlip(RotateFlipType.Rotate270FlipNone);

        //file size is increasing after RotateFlip method

        if (brigh != DEFAULT_BRIGH ||
            contr != DEFAULT_CONTR ||
            gamma != DEFAULT_GAMMA)
        {
            using (Graphics g = Graphics.FromImage(im))
            {
                float b = _brigh;
                float c = _contr;
                ImageAttributes derp = new ImageAttributes();
                derp.SetColorMatrix(new ColorMatrix(new float[][]{
                        new float[]{c, 0, 0, 0, 0},
                        new float[]{0, c, 0, 0, 0},
                        new float[]{0, 0, c, 0, 0},
                        new float[]{0, 0, 0, 1, 0},
                        new float[]{b, b, b, 0, 1}}));
                derp.SetGamma(_gamma);
                g.DrawImage(img, new Rectangle(Point.Empty, img.Size),
                    0, 0, img.Width, img.Height, GraphicsUnit.Pixel, derp);
            }
        }
        return im; 
    }

What is the problem?


Solution

  • In your case applying RotateFlip on im is changing the ImageFormat from Jpeg to MemoryBmp. By Default when you save the image it is going to make use of the default ImageFormat. This will be the format returned by im.RawFormat

    if you check the GUID im.RawFormat.Guid

    Before RotateFlip

    {b96b3cae-0728-11d3-9d7b-0000f81ef32e} which is same as ImageFormat.Jpeg.Guid

    After RotateFlip

    {b96b3caa-0728-11d3-9d7b-0000f81ef32e} which is same as ImageFormat.MemoryBmp.Guid

    At the time of saving the image pass the ImageFormat as the second parameter which will ensure that it uses the correct format. If not mentioned it is going to be the one in im.RawFormat

    So If you want to save as jpeg at the time of saving call

    im.Save("filename.jpg", ImageFormat.Jpeg);
    

    This time the file size should be less than the original size.

    Also note ImageFormat is in System.Drawing.Imaging namespace

    NOTE

    To control the quality of the jpeg make use of the overloaded Save method as mentioned in this MSDN Link


    EDIT Based On Comment

    OK assuming you are using SQL Server you must be having a image datatype column (it is recommended to use varbinary(max) instead of image as in future it is going to be obselete (Read MSDN Post)

    Now to the steps

    1) read the contents as a stream / byte[] array
    
    2) convert this to Image
    
    3) perform rotate operation on the Image
    
    4) convert this Image back to stream / byte[] array
    
    5) Update the database column with the new value