Get the EXIF ​​orientation tag, rotate to the appropriate orientation, process the image and save the image with the correct orientation

My program processes some images in batch mode. I now need to read the exif orientation tag of the image, rotate it to the desired orientation, do some processing and save the image without any EXIF ​​orientation tag, but with the right rotation. (or with an EXIF ​​tag with the appropriate orientation)

I read EXIF ​​and Rotating using this library :

var bmp = new Bitmap(pathToImageFile); var exif = new EXIFextractor(ref bmp, "n"); // get source from http://www.codeproject.com/KB/graphics/exifextractor.aspx?fid=207371 if (exif["Orientation"] != null) { RotateFlipType flip = OrientationToFlipType(exif["Orientation"].ToString()); if (flip != RotateFlipType.RotateNoneFlipNone) // don't flip of orientation is correct { bmp.RotateFlip(flip); bmp.Save(pathToImageFile, ImageFormat.Jpeg); } // Match the orientation code to the correct rotation: private static RotateFlipType OrientationToFlipType(string orientation) { switch (int.Parse(orientation)) { case 1: return RotateFlipType.RotateNoneFlipNone; case 2: return RotateFlipType.RotateNoneFlipX; case 3: return RotateFlipType.Rotate180FlipNone; case 4: return RotateFlipType.Rotate180FlipX; break; case 5: return RotateFlipType.Rotate90FlipX; break; case 6: return RotateFlipType.Rotate90FlipNone; case 7: return RotateFlipType.Rotate270FlipX; case 8: return RotateFlipType.Rotate270FlipNone; default: return } } 

It works. but when you save this image, there is still an exif rotation tag that makes the image incorrect. What i can do is

  var bmp = new Bitmap(OS.FileName); var exif = new EXIFextractor(ref bmp, "n"); exif.setTag(0x112, "1"); bmp.save("strippedexifimage"); 

But this code when used in a loop slows down my program by about 50%. Is there an alternative way? Maybe a code to resist image rotation after applying rotation, will this work?

Update:

@Hans Passant. Your answer works, but the result it produces is the same as those created by the library. When I use bitmap.save (), both the library and your code work. But when I use the following code to save my image depending on the format chosen by the user. Imgformat can be imgformat = "image/png";,imgformat = "image/jpeg"; etc. Some images are still saved with the wrong exif orientation tag. i.e.: I see an incorrect image view in Windows Explorer. When I open an image using MS Paint, the image has the correct orientation. What am I doing wrong? Please, help.

 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); } 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; } 
+5
source share
1 answer
  var exif = new EXIFextractor(ref bmp, "n") 

Using a library to implement a function can save you a lot of time. Or you are stuck for several days when the library is poorly designed or difficult to use. ref bmp is the first loud warning, you fell into a hole of despair, trying to indicate the value as a string. This was attractive because you did not have to consider what “type” could mean in the correct overload of setTag (). It is type 3 and requires a byte [] with two elements. It is impossible to detect, you can use the library only when you do not need it.

Immerse the library, this will not help. An EXIF ​​tag that preserves orientation has an id of 0x112 and is encoded as a 16-bit value. Just use System.Drawing directly to read the value and force it back to 1. For example:

 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) { // etc... } } 
+5
source

Source: https://habr.com/ru/post/1240424/


All Articles