使用C#读取图片时出现宽高值颠倒的异常问题
图片宽高读取颠倒问题排查与解决
问题现象
有一张JPG图片,在Windows属性中显示尺寸为宽度3000px,高度4000px(竖版比例),但使用C#的System.Drawing.Image.FromStream读取时,得到的宽高值却颠倒了。
测试代码如下:
private static void TestImage() { using (FileStream file1 = new FileStream("DSC_2446.JPG", FileMode.Open)) { Console.WriteLine("DSC_2446.JPG :"); using (var img1 = System.Drawing.Image.FromStream(file1)) { Console.WriteLine($" Width = {img1.Width}"); Console.WriteLine($" Height = {img1.Height}"); } } Console.Read(); }
问题原因
核心原因是JPG图片包含EXIF方向标签(Orientation):
- Windows属性会读取这个标签,自动旋转图片以展示视觉上的正确方向,所以显示的是调整后的宽高。
System.Drawing.Image.FromStream默认仅读取图片原始像素的宽高,不会自动应用EXIF的方向信息,导致读取的是相机拍摄时存储的原始像素尺寸,和视觉上的宽高出现颠倒。
比如竖拍的照片,相机常以横版像素存储,同时用EXIF Orientation标签标记需要旋转90度才能正确显示。
检测方法
通过读取图片的EXIF元数据,获取Orientation值即可判断是否存在方向旋转:
using System.Drawing.Imaging; private static int GetExifOrientation(Image image) { if (image.PropertyIdList.Contains(0x0112)) // Orientation属性的ID为0x0112 { PropertyItem propItem = image.GetPropertyItem(0x0112); return BitConverter.ToInt16(propItem.Value, 0); } return 1; // 默认无旋转 }
Orientation常见取值对应场景:
- 1:正常(无旋转)
- 6:顺时针旋转90度(视觉宽高为原始高、宽)
- 8:逆时针旋转90度
- 3:旋转180度
修复方法
方法1:基于EXIF方向手动修正图片
读取图片后,根据Orientation值旋转图片,得到正确的视觉尺寸:
private static Image FixImageOrientation(Image image) { int orientation = GetExifOrientation(image); switch (orientation) { case 1: return image; case 6: image.RotateFlip(RotateFlipType.Rotate90FlipNone); break; case 8: image.RotateFlip(RotateFlipType.Rotate270FlipNone); break; case 3: image.RotateFlip(RotateFlipType.Rotate180FlipNone); break; } // 旋转后移除EXIF方向标签,避免后续重复处理 image.RemovePropertyItem(0x0112); return image; }
修改原测试代码调用即可:
using (var img1 = FixImageOrientation(System.Drawing.Image.FromStream(file1))) { Console.WriteLine($" Width = {img1.Width}"); Console.WriteLine($" Height = {img1.Height}"); }
方法2:使用自动处理EXIF的现代图片库
如果System.Drawing的限制较多,可以改用ImageSharp这类现代库,它会自动识别并应用EXIF方向:
using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; private static void TestImageWithImageSharp() { using (var image = Image.Load("DSC_2446.JPG")) { Console.WriteLine($" Width = {image.Width}"); Console.WriteLine($" Height = {image.Height}"); } }
内容的提问来源于stack exchange,提问作者Ivan Kozlov
相关产品推荐
相关产品推荐

