My program processes some images in batch.I currently need to read the exif orientation tag of the image,rotate it to proper orientation,do some processing and save the image without any EXIF Orientation Tag,but with proper Rotation.(or with EXIF tag with Proper Orientation)
I am reading 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
}
}
This works. but when saving this image, the exif rotation tag still exists which makes the image to be in wrong orientation. 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 around 50%.Is there a alternative way? May be code to counter rotate the image after applying the rotation,will that work?
Update:
@Hans Passant Your answer works, but the result it produce is same as the ones produced by the library. When i use bitmap.save(),both library and your code works.But when i use the following code to save my image depending on the format selected by the user. Imgformat can be imgformat = "image/png";,imgformat = "image/jpeg";
etc some images still get saved with wrong exif orientation tag. ie: i see the wrong image preview in windows explorer,When i open the image with MS Paint,the image is having correct orientation.What im 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;
}
var exif = new EXIFextractor(ref bmp, "n")
Using a library to implement a feature can save you a lot of time. Or you'll get stuck for days when the library is poorly designed or difficult to use. ref bmp
is the first loud alert, you fell it the pit of despair by trying to specify the value as a string. Which was attractive because you did not have to consider what "type" might mean in the correct setTag() overload. It is type 3 and requires a byte[] with two elements. This is not discoverable at all, you can only use the library correctly when you don't need it.
Ditch the library, it is not helpful. The EXIF tag that stores the orientation has id 0x112 and is encoded as a 16-bit value. Just use System.Drawing directly to read the value and force it back to 1. Like this:
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...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With