如何将文件 .png 转换为位图?什么都不适合我。错误“'Failed to decode image. The provided image must be a Bitmap.'”Xamarin.forms
How can i convert a file .png to a Bitmap? Nothing works for me. Error "'Failed to decode image. The provided image must be a Bitmap.'" Xamarin.forms
我在 Xamarin.Forms 部分使用 Xamarin 我需要将文件 ("image.png") 转换为位图,因为当项目 运行 进入“中断模式”并显示此消息“Java.Lang.IllegalArgumentException:'Failed to decode image. The provided image must be a Bitmap.'”。所以我尝试以多种方式转换文件,例如:
1_ 使用 System.Drawing.Bitmap 中的方法,但显示此异常“此平台不支持此操作”
2_ 无法使用 Android.Graphics,因为我在 xamarin.forms 工作,而不是 xamarin.android。
3_ 我尝试将“image.png”转换为 base64 或 byte[] 数组,然后转换为位图,但问题与第一个问题相同,因为要从 byte[] 数组或base64 到 Bitmap 我使用了 System.Drawing.Bitmap.
中的方法
4_ 我尝试使用库 SkiaSharp 但我没有成功,因为我没有找到太多关于如何将 .png 转换为 SKBitmap 然后将 SKBitmap 转换为位图的信息(即使我不知道是否这是可能的)。
5_ 最后,我使用应用程序将“image.png”转换为“image.bmp”,并在我的项目中使用了 .bmp 文件,但它也不起作用。
我必须将“image.png”保存在一个字符串变量中,这就是我的想法。
如果你有 SkiaSharp 的解决方案,我会很高兴
编辑
这是我的代码的一部分,我只是将图像保存在一个变量中
Icon = "pin_blue.png";
//i can't use a path because in xamarin you have many size from the same
//image for the different size of the screen
编辑 2 这是我在 google 地图
中显示图钉的方法
private void ShowPins(List<PointsOfInterest> resultPointsOfInterest)
{
if (resultPointsOfInterest != null && resultPointsOfInterest.Any())
{
var location = Geolocation.GetLastKnownLocationAsync();
PointsOfInterest position = new PointsOfInterest();
if (location != null)
{
position.ccsm0166latitud = location.Result.Latitude;
position.ccsm0166longitud = location.Result.Longitude;
}
else {
position = resultPointsOfInterest.First();
}
//Distance = Distance.FromKilometers(new Random().Next(23,35));
Distance = Distance.FromKilometers(3);
Position = new Position(position.ccsm0166latitud, position.ccsm0166longitud);
PinsFiltered= Pins = new List<PinCustom>(resultPointsOfInterest.Select(
x => new PinCustom()
{
Position =
new Position(x.ccsm0166latitud, x.ccsm0166longitud),
Address = x.ccsm0166direccion,
Label = x.ccsm0166nombre,
Type = PinType.Place,
TypePointOfInterest = x.ccsm0166tipositio,
IconBM = Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branch ? PinCustom.ConvertToBitmap("pin_blue.png") :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branch ? "pin_blue.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branchWithExtendedHours ? "pin_black.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branchWithExtendedHours2 ? "pin_black.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branchWithExtendedHours3 ? "pin_black.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.selfServiceTerminal ? "pin_green.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.atmServBox ? "pin_yellow.png" : string.Empty
}).ToList());
}
else
{
Pins = new List<PinCustom>();
}
}
这是我保存图像的 class Pin 图
public class PinCustom : Pin
{
public string TypePointOfInterest { get; set; }
public string Icon { get; set; }
public Bitmap { get; set; }
//Here i create this variable to save a bitmap but i don't know if i do the things well
}
这是我要在google地图
中显示的图标.png
Pin Blue Image
使用ffmpeg
为此命令:ffmpeg -i image.png image.bmp
打开文件并将其转换为字节数组:
string directory = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
// or your image directory, just replace it
var stream = File.OpenWrite(Path.Combine(directory, "image.png"));
byte[] buff = ConvertStreamToByteArray(stream);
stream.Close();
public static byte[] ConvertStreamToByteArray(Stream stream)
{
byte[] byteArray = new byte[16 * 1024];
using (MemoryStream mStream = new MemoryStream())
{
int bit;
while ((bit = stream.Read(byteArray, 0, byteArray.Length)) > 0)
{
mStream.Write(byteArray, 0, bit);
}
return mStream.ToArray();
}
}
然后,将此字节数组传递给 SKBitmap:
SKBitmap bmp = SKBitmap.Decode(buff);
编辑:
如果你想在没有ConvertStreamToByteArray()
的情况下尝试:
byte[] buff = null;
stream.Write(buff, 0, buff.Length);
这 Write
将取决于您的 stream
的类型。在这个例子中,我使用 FileStream
.
编辑 2:
string resourceID = "image.png";
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream(resourceID))
{
resourceBitmap = SKBitmap.Decode(stream);
SKBitmap bmp = SKImage.FromBitmap(resourceBitmap);
}
然后你可以使用这个位图来绘制和填充你的 SKCanvas:
canvas.DrawBitmap(bmp, 0, 0);
i have 5 types of pins (pins are the image .png) when i put the pins
in format .png
如果您想自定义地图中的图钉,只需使用 Custom Renderers 即可。
可以通过调用MarkerOptions.SetIcon
方法自定义用于表示标记的图标。这可以通过覆盖 CreateMarker
方法来实现,该方法会为添加到地图的每个 Pin 调用:
protected override MarkerOptions CreateMarker(Pin pin)
{
var marker = new MarkerOptions();
marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
marker.SetTitle(pin.Label);
marker.SetSnippet(pin.Address);
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
return marker;
}
如果想显示不同的图标,可以参考下面的代码:
protected override MarkerOptions CreateMarker(Pin pin)
{
var marker = new MarkerOptions();
marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
marker.SetTitle(pin.Label);
marker.SetSnippet(pin.Address);
var customPin = (Element as CustomMap).CustomPins.FirstOrDefault(p => p.Position == pin.Position);
if (customPin != null)
{
if (customPin.IconType == "corporate")
{
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.corporate));
}
else if (customPin.IconType == "pickup")
{
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.bus));
}
}
return marker;
}
更多信息,请查看:Customizing the Marker。
我在 Xamarin.Forms 部分使用 Xamarin 我需要将文件 ("image.png") 转换为位图,因为当项目 运行 进入“中断模式”并显示此消息“Java.Lang.IllegalArgumentException:'Failed to decode image. The provided image must be a Bitmap.'”。所以我尝试以多种方式转换文件,例如:
1_ 使用 System.Drawing.Bitmap 中的方法,但显示此异常“此平台不支持此操作”
2_ 无法使用 Android.Graphics,因为我在 xamarin.forms 工作,而不是 xamarin.android。
3_ 我尝试将“image.png”转换为 base64 或 byte[] 数组,然后转换为位图,但问题与第一个问题相同,因为要从 byte[] 数组或base64 到 Bitmap 我使用了 System.Drawing.Bitmap.
中的方法4_ 我尝试使用库 SkiaSharp 但我没有成功,因为我没有找到太多关于如何将 .png 转换为 SKBitmap 然后将 SKBitmap 转换为位图的信息(即使我不知道是否这是可能的)。
5_ 最后,我使用应用程序将“image.png”转换为“image.bmp”,并在我的项目中使用了 .bmp 文件,但它也不起作用。
我必须将“image.png”保存在一个字符串变量中,这就是我的想法。
如果你有 SkiaSharp 的解决方案,我会很高兴
编辑
这是我的代码的一部分,我只是将图像保存在一个变量中
Icon = "pin_blue.png";
//i can't use a path because in xamarin you have many size from the same
//image for the different size of the screen
编辑 2 这是我在 google 地图
中显示图钉的方法private void ShowPins(List<PointsOfInterest> resultPointsOfInterest)
{
if (resultPointsOfInterest != null && resultPointsOfInterest.Any())
{
var location = Geolocation.GetLastKnownLocationAsync();
PointsOfInterest position = new PointsOfInterest();
if (location != null)
{
position.ccsm0166latitud = location.Result.Latitude;
position.ccsm0166longitud = location.Result.Longitude;
}
else {
position = resultPointsOfInterest.First();
}
//Distance = Distance.FromKilometers(new Random().Next(23,35));
Distance = Distance.FromKilometers(3);
Position = new Position(position.ccsm0166latitud, position.ccsm0166longitud);
PinsFiltered= Pins = new List<PinCustom>(resultPointsOfInterest.Select(
x => new PinCustom()
{
Position =
new Position(x.ccsm0166latitud, x.ccsm0166longitud),
Address = x.ccsm0166direccion,
Label = x.ccsm0166nombre,
Type = PinType.Place,
TypePointOfInterest = x.ccsm0166tipositio,
IconBM = Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branch ? PinCustom.ConvertToBitmap("pin_blue.png") :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branch ? "pin_blue.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branchWithExtendedHours ? "pin_black.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branchWithExtendedHours2 ? "pin_black.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.branchWithExtendedHours3 ? "pin_black.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.selfServiceTerminal ? "pin_green.png" :
Int32.Parse(x.ccsm0166tipositio) == (int)PointOfInterestType.atmServBox ? "pin_yellow.png" : string.Empty
}).ToList());
}
else
{
Pins = new List<PinCustom>();
}
}
这是我保存图像的 class Pin 图
public class PinCustom : Pin
{
public string TypePointOfInterest { get; set; }
public string Icon { get; set; }
public Bitmap { get; set; }
//Here i create this variable to save a bitmap but i don't know if i do the things well
}
这是我要在google地图
中显示的图标.pngPin Blue Image
使用ffmpeg 为此命令:ffmpeg -i image.png image.bmp
打开文件并将其转换为字节数组:
string directory = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
// or your image directory, just replace it
var stream = File.OpenWrite(Path.Combine(directory, "image.png"));
byte[] buff = ConvertStreamToByteArray(stream);
stream.Close();
public static byte[] ConvertStreamToByteArray(Stream stream)
{
byte[] byteArray = new byte[16 * 1024];
using (MemoryStream mStream = new MemoryStream())
{
int bit;
while ((bit = stream.Read(byteArray, 0, byteArray.Length)) > 0)
{
mStream.Write(byteArray, 0, bit);
}
return mStream.ToArray();
}
}
然后,将此字节数组传递给 SKBitmap:
SKBitmap bmp = SKBitmap.Decode(buff);
编辑:
如果你想在没有ConvertStreamToByteArray()
的情况下尝试:
byte[] buff = null;
stream.Write(buff, 0, buff.Length);
这 Write
将取决于您的 stream
的类型。在这个例子中,我使用 FileStream
.
编辑 2:
string resourceID = "image.png";
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream(resourceID))
{
resourceBitmap = SKBitmap.Decode(stream);
SKBitmap bmp = SKImage.FromBitmap(resourceBitmap);
}
然后你可以使用这个位图来绘制和填充你的 SKCanvas:
canvas.DrawBitmap(bmp, 0, 0);
i have 5 types of pins (pins are the image .png) when i put the pins in format .png
如果您想自定义地图中的图钉,只需使用 Custom Renderers 即可。
可以通过调用MarkerOptions.SetIcon
方法自定义用于表示标记的图标。这可以通过覆盖 CreateMarker
方法来实现,该方法会为添加到地图的每个 Pin 调用:
protected override MarkerOptions CreateMarker(Pin pin)
{
var marker = new MarkerOptions();
marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
marker.SetTitle(pin.Label);
marker.SetSnippet(pin.Address);
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
return marker;
}
如果想显示不同的图标,可以参考下面的代码:
protected override MarkerOptions CreateMarker(Pin pin)
{
var marker = new MarkerOptions();
marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
marker.SetTitle(pin.Label);
marker.SetSnippet(pin.Address);
var customPin = (Element as CustomMap).CustomPins.FirstOrDefault(p => p.Position == pin.Position);
if (customPin != null)
{
if (customPin.IconType == "corporate")
{
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.corporate));
}
else if (customPin.IconType == "pickup")
{
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.bus));
}
}
return marker;
}
更多信息,请查看:Customizing the Marker。