我在Forms应用程序中使用Xam.Plugin.Media拍照。 我将图像流(GetStream)转换为byte []并存储在数据库中。 然后,我将其用作图像源。 在Android和UWP上,其工作正常。 在iOS上,如果以人像模式拍摄照片,则所选的图像始终旋转90度。 稍后,我将其上传到服务器,该图像可以在其他设备上使用。 为此,我还尝试了GetStreamWithImageRotatedForExternalStorage,但在这种情况下,我根本看不到该图像。 流中有字节(我的DisplayAlert长度),但是图像不显示。
知道我可能在做什么错吗?
我的代码:-
private async Task TakePicture(WineDetails details)
{
await CrossMedia.Current.Initialize();
if (CrossMedia.Current.IsCameraAvailable && CrossMedia.Current.IsTakePhotoSupported)
{
var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
AllowCropping = true,
PhotoSize = Plugin.Media.Abstractions.PhotoSize.Medium,
SaveToAlbum = false,
RotateImage = true
});
if (file == null)
return;
using (var ms = new MemoryStream())
{
var stream = file.GetStreamWithImageRotatedForExternalStorage();
stream.CopyTo(ms);
details.LabelImage = ms.ToArray();
details.NotifyChange("ImageSource");
}
}
}
图像通过NotifyChange在页面中更新,看起来像这样: ImageSource.FromStream(()=>新的MemoryStream(this.LabelImage))
这在Android和UWP上的所有情况下均能正常工作,在iOS上使用GetStream可以正常工作(除非图像旋转不正确),但在iOS上不能使用GetStreamWithImageRotatedForExternalStorage来工作。
还有其他人使用此插件吗? 知道为什么GetStream返回旋转的图像吗? 知道为什么GetStreamWithImageRotatedForExternalStorage无法正常工作吗?
谢谢
更新:-
Changed SaveToAlbum = true,当我打开图库时,图像旋转了90度。 RotateImage = true会导致问题吗?我将尝试将其设置为false。 我仍然无法使用GetStreamWithImageRotatedForExternalStorage将图像源设置为图像的字节数组。
using (var ms = new MemoryStream())
{
file.GetStreamWithImageRotatedForExternalStorage().CopyTo(ms);
details.LabelImage = ms.ToArray();
}
使用字节数组获取图像
return ImageSource.FromStream(() => new MemoryStream(this.LabelImage));
这对我不起作用,GetStream可以正常工作。
更新:-
好的,RotateImage = false + GetStreamWithImageRotatedForExternalStorage允许我显示图像,但是在我的应用程序和图库中图像仍未正确旋转。
答案 0 :(得分:2)
我正在使用this插件,该插件是相似的(如果不是同一件事-我知道James Montemagno最近将他的作品与Xamarin打包/捆绑在一起)。
如果您查看那里的问题面板,您会发现很多人遇到类似的问题(iOS上的图像旋转)。几乎每个“解决方案”都使用GetStreamWithImageRotatedForExternalStorage
提及。
我的问题很相似-我无法在iOS模式下以人像模式拍摄照片,而没有其他(非iOS设备)旋转图像。我已经尝试了数周的时间来解决此问题,但是对插件的支持似乎非常有限。
最终,我不得不使用巨大解决方法来解决此问题-使用自FFImageLoading扩展的自定义渲染器来显示我们的图像和MetadataExtractor。然后,我们能够从流中提取EXIF数据,并将旋转变换应用于FFImageLoding图像控件。
旋转信息以一种奇怪的方式存储为字符串。这是我用来提取旋转信息,并以整数形式返回需要旋转的量的方法。请注意,对我而言,iOS能够正确正确显示图像,因此它仅返回Android设备的旋转更改。
public static int GetImageRotationCorrection(byte[] image)
{
try
{
var directories = ImageMetadataReader.ReadMetadata(new MemoryStream(image));
if (Device.Android == "Android")
{
foreach (var directory in directories)
{
foreach (var tag in directory.Tags)
{
if (tag.Name == "Orientation")
{
if (tag.Description == "Top, left side(Horizontal / normal)")
return 0;
else if (tag.Description == "Left side, bottom (Rotate 270 CW)")
return 270;
else if (tag.Description == "Right side, top (Rotate 90 CW")
return 90;
}
}
}
}
return 0;
}
catch (Exception ex)
{
return 0;
}
}
请注意,还有用于FFImage加载的图像的自定义渲染器。
public class RotatedImage : CachedImage
{
public static BindableProperty MyRotationProperty = BindableProperty.Create(nameof(MyRotation), typeof(int), typeof(RotatedImage), 0, propertyChanged: UpdateRotation);
public int MyRotation
{
get { return (int)GetValue(MyRotationProperty); }
set { SetValue(MyRotationProperty, value); }
}
private static void UpdateRotation(BindableObject bindable, object oldRotation, object newRotation)
{
var _oldRotation = (int)oldRotation;
var _newRotation = (int)newRotation;
if (!_oldRotation.Equals(_newRotation))
{
var view = (RotatedImage)bindable;
var transformations = new System.Collections.Generic.List<ITransformation>() {
new RotateTransformation(_newRotation)
};
view.Transformations = transformations;
}
}
}
因此,在我的XAML中-我声明了RotatedImage而不是标准Image。使用自定义渲染器,我能够做到这一点,并使图像显示旋转正确的数量。
image.MyRotation = GetImageRotationCorrection(imageAsBytes)
这是完全不必要的解决方法-但这是我必须解决的长度。
我肯定会跟随这个问题,社区中可能有人可以帮助我们两个人!
答案 1 :(得分:2)
SaveMetaData标志导致旋转问题。 现在将其设置为false(默认为true)可以正确显示照片。
这是一个副作用,如果SaveToAlbum = true,则图像不再显示在图库中。
在使用GetStreamWithImageRotatedForExternalStorage时,即使使用FFImageLoading,仍然无法使用图像拍摄。