我有同样的问题。当直接从 WIC 位图创建 Texture2D 而不像 GetPixelDataAsync 那样通过 byte[] 时,我无法想出让 WIC 或 DirectX 自动应用 EXIF 方向指令的方法。因此,我改为阅读 EXIF 属性 0x112 并按照Problem reading JPEG Metadata (Orientation)的答案之一中的建议确定要应用的方向。然后我在上面代码中的 IWICFormatConverter 顶部插入一个 IWICBitmapFlipRotator,并指定 BitmapTransformOptions 以匹配 EXIF 指令。
我正在使用 SharpDX 用 C# 编写代码,因此语法与上面的 C++ 略有不同。但翻译起来应该很简单:
获取元数据:
using (MetadataQueryReader metadata = bitmapObjects.frame.MetadataQueryReader)
{
EXIForientation = (Nullable<UInt16>)metadata.TryGetMetadataByName("/app1/{ushort=0}/{ushort=274}"); //0x0112
}
将 EXIF 方向信息转换为我需要的变量(复制/粘贴并从我链接到的另一篇文章中稍作修改。我在另一篇文章的代码中发现了一个错误 - 对于案例“5”):
// If the EXIF orientation specifies that the image needs to be flipped or rotated before display, set that up to happen
BitmapTransformOptions bitmapTransformationOptions = BitmapTransformOptions.Rotate0;
bool flipHeightWidth = false;
if (EXIForientation != null)
{
switch (EXIForientation)
{
case 1:
// No rotation required.
break;
case 2:
bitmapTransformationOptions = BitmapTransformOptions.Rotate0 | BitmapTransformOptions.FlipHorizontal;
break;
case 3:
bitmapTransformationOptions = BitmapTransformOptions.Rotate180;
break;
case 4:
bitmapTransformationOptions = BitmapTransformOptions.Rotate180 | BitmapTransformOptions.FlipHorizontal;
break;
case 5:
bitmapTransformationOptions = BitmapTransformOptions.Rotate270 | BitmapTransformOptions.FlipHorizontal;
flipHeightWidth = true;
break;
case 6:
bitmapTransformationOptions = BitmapTransformOptions.Rotate90;
flipHeightWidth = true;
break;
case 7:
bitmapTransformationOptions = BitmapTransformOptions.Rotate90 | BitmapTransformOptions.FlipHorizontal;
flipHeightWidth = true;
break;
case 8:
bitmapTransformationOptions = BitmapTransformOptions.Rotate270;
flipHeightWidth = true;
break;
}
if (flipHeightWidth)
{
originalWidth = bitmapObjects.frame.Size.Height;
originalHeight = bitmapObjects.frame.Size.Width;
}
}
我所做的位图创建(与您插入该管道的转换略有不同):
bitmapObjects.scaler.Initialize(bitmapObjects.frame, (int)bitmapRectangle.Width, (int)bitmapRectangle.Height, SharpDX.WIC.BitmapInterpolationMode.Linear);
bitmapObjects.pixelFormatConverter.Initialize(bitmapObjects.scaler, SharpDX.WIC.PixelFormat.Format32bppPBGRA);
bitmapObjects.bitmapFlipRotator.Initialize(bitmapObjects.pixelFormatConverter, bitmapTransformationOptions);
bitmapObjects.bitmap = SharpDX.Direct2D1.Bitmap1.FromWicBitmap(D2DObjectCollection.D2Dcontext2,
bitmapObjects.bitmapFlipRotator,
new BitmapProperties1(
new SharpDX.Direct2D1.PixelFormat(
Format.B8G8R8A8_UNorm,
SharpDX.Direct2D1.AlphaMode.Ignore),
96,
96,
BitmapOptions.Target));
顺便说一句,我将所有用于渲染位图的对象都保存在“bitmapObjects”集合中,这样我就可以按照它们初始化的相反顺序来处理它们。我发现如果我不这样做,我会从 Windows Codecs DLL 的深处得到非常罕见的奇怪的内存访问冲突实例。
编辑
自从实现了这个,我意识到这个解决方案需要注意一些事情:当缩放器首先进入管道时,它(在我的应用程序场景中)显着减小了当今大多数来自现代相机的大型 jpg 图像的解码位图的大小. 这对性能非常有用。但是,为了正确应用旋转和翻转(与我上面共享的代码段中的内容不同),我必须将其放在管道的开头,这会导致解码为图像文件中分辨率大小的位图。为了尽可能解决这个问题,我将代码更改为仅在特定文件实际上包含方向说明时才应用 bitmapFlipRotator。否则,不使用 bitmapFlipRotator。