Search code examples
c#.netbitmapexifsystem.drawing

Removing EXIF Does not work when using Different Encoders to Choose Format


Im using the following code to fix the orientation of image taking into account the EXIF Orientation Tag

 static void FixImageOrientation(Image srce)
        {
            const int ExifOrientationId = 0x112;
            // Read orientation tag
            if (!srce.PropertyIdList.Contains(ExifOrientationId)) return;
            var prop = srce.GetPropertyItem(ExifOrientationId);
            var orient = BitConverter.ToInt16(prop.Value, 0);
            // Force value to 1
            prop.Value = BitConverter.GetBytes((short)1);
            srce.SetPropertyItem(prop);

            // Rotate/flip image according to <orient>
            switch (orient)
            {
                case 1:
                 srce.RotateFlip(RotateFlipType.RotateNoneFlipNone);
                 break;

                case 2:
                    srce.RotateFlip(RotateFlipType.RotateNoneFlipX);
                    break;

                case 3:
                     srce.RotateFlip(RotateFlipType.Rotate180FlipNone);
                     break;

                case 4:
                    srce.RotateFlip( RotateFlipType.Rotate180FlipX);
                    break;

                case 5:
                     srce.RotateFlip(RotateFlipType.Rotate90FlipX);
                     break;

                case 6:
                    srce.RotateFlip(RotateFlipType.Rotate90FlipNone);
                    break;

                case 7:
                    srce.RotateFlip(RotateFlipType.Rotate270FlipX);
                    break;

                case 8:
                     srce.RotateFlip(RotateFlipType.Rotate270FlipNone);
                     break;

                default:
                    srce.RotateFlip(RotateFlipType.RotateNoneFlipNone);
                    break;
            }
        }

This code removes the EXIF Orientation Tag properly. And saving the image works is i simply use img.save

But the app provides user the ability to select the format of the image.For that i use the following code

 private void saveJpeg(string path, Bitmap img, long quality)
        {


            EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);


            ImageCodecInfo Codec = this.getEncoderInfo(imgformat);

            if (Codec == null)
                return;

            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = qualityParam;

            img.Save(path + ext, Codec, encoderParams);
        }
        public string getimgext(string ccodec)
        {
            if (ccodec.Equals("image/png"))
            {
                return ".png";
            }
            else if (ccodec.Equals("image/jpeg"))
            {
                return ".jpg";
            }
            else if (ccodec.Equals("image/tiff"))
            {
                return ".tif";
            }
            else if (ccodec.Equals("image/bmp"))
            {
                return ".bmp";
            }

            else if (ccodec.Equals("image/gif"))
            {
                return ".gif";
            }
            else
            {
                return null;
            }

        }
        private ImageCodecInfo getEncoderInfo(string mimeType)
        {
            // Get image codecs for all image formats
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

            // Find the correct image codec
            for (int i = 0; i < codecs.Length; i++)
                if (codecs[i].MimeType == mimeType)
                    return codecs[i];
            return null;
        }

When i save the image with SaveJpeg the image gets saved with wrong orientation.What im i doing wrong? Please help.

UPDATE:

I have modified the method so that i dont need to create a new instance of the bitmap as the loop processes many files.But this does not work unless i create a new instance of the bitmap.This process consumes an additional of 10+ seconds of the processing time when compared to the old version. Im using the code like this

image = (Bitmap)FixImageOrientation(Bitmap.FromFile(path));


Image FixImageOrientation(Image srce)
        {
            const int ExifOrientationId = 0x112;
            // Read orientation tag
            if (!srce.PropertyIdList.Contains(ExifOrientationId)) return srce;
            var prop = srce.GetPropertyItem(ExifOrientationId);
            var orient = BitConverter.ToInt16(prop.Value, 0);
            // Force value to 1
            prop.Value = BitConverter.GetBytes((short)1);
            srce.SetPropertyItem(prop);

            // Rotate/flip image according to <orient>
            switch (orient)
            {
                case 1:
                    srce.RotateFlip(RotateFlipType.RotateNoneFlipNone);
                    return srce;
                    

                case 2:
                    srce.RotateFlip(RotateFlipType.RotateNoneFlipX);
                    return srce;

                case 3:
                    srce.RotateFlip(RotateFlipType.Rotate180FlipNone);
                    return srce;

                case 4:
                    srce.RotateFlip(RotateFlipType.Rotate180FlipX);
                    return srce;

                case 5:
                    srce.RotateFlip(RotateFlipType.Rotate90FlipX);
                    return srce;

                case 6:
                    srce.RotateFlip(RotateFlipType.Rotate90FlipNone);
                    return srce;

                case 7:
                    srce.RotateFlip(RotateFlipType.Rotate270FlipX);
                    return srce;

                case 8:
                    srce.RotateFlip(RotateFlipType.Rotate270FlipNone);
                    return srce;

                default:
                    srce.RotateFlip(RotateFlipType.RotateNoneFlipNone);
                    return srce;
            }
        }

Solution

  • In one method you have argument of type Image but in other Bitmap. So I'm guessing that you convert source JPEG image to Bitmap before call FixImageOrientation.

    This will work:

     var jpeg = Image.FromFile("original.jpg");
     FixImageOrientation(jpeg);
     var bitmap = new Bitmap(jpeg);
     saveJpeg("new",bitmap,1);
    

    This won't:

    var jpeg = Image.FromFile("original.jpg");
    var bitmap = new Bitmap(jpeg);
    FixImageOrientation(bitmap);
    saveJpeg("new", bitmap, 1);