如何使用 SkiaSharp 查找解码位图的 PixelFormat

Posted

技术标签:

【中文标题】如何使用 SkiaSharp 查找解码位图的 PixelFormat【英文标题】:How to find PixelFormat for decoded bitmap using SkiaSharp 【发布时间】:2017-12-26 10:07:28 【问题描述】:

在 System.Drawing 中,我们从 Image 对象中检索 PixelFormat,但 SkiaSharp.SkImage 没有提供 API 来查找解码图像的 PixelFormat。是否有任何其他解决方法来查找解码图像的 PixelFormat,以及我们如何创建具有 PixelFormat 值的图像作为等效于 System.Drawing.Image

【问题讨论】:

【参考方案1】:

简答

有这个方面,不过分为两种:SKColorTypeSKAlphaType。这些属性位于SKImageInfo 类型中。

SKImageSKBitmap

在我分享真正的答案之前,先简单介绍一下这两种图像类型之间的区别。

SKBitmap (仅限光栅)

SKBitmap仅光栅图形,这意味着颜色和 alpha 类型信息很容易获得。这是在Info 属性中。

SKBitmap bitmap = ...;
SKColorType colorType = bitmap.Info.ColorType;
SKAlphaType alphaType = bitmap.Info.AlphaType;

SKImage (光栅或纹理)

SKImage 有点不同,因为它实际上可能不是光栅位图。 SKImage 可以是 GPU 对象,例如 OpenGL 纹理。因此,此颜色类型不适用。因此,在您使用光栅位图的情况下,请使用 SKBitmap 而不是 SKImage

但是,SKImage 仍有希望,因为基于光栅的SKImage 实际上在底层使用了SKBitmap。如果您知道您的SKImage 是光栅图像,那么您可以使用PeekPixels() 方法获取SKPixmap 对象,该对象也将具有Info 属性。 SKPixmap 是一个瘦类型,包含对图像数据、信息和一些其他属性的引用。

要检查某个SKImage 是纹理图像还是光栅图像,可以使用IsTextureBacked 属性。

SKImage image = ...;
if (!image.IsTextureBacked) 
    using (SKPixmap pixmap = image.PeekPixels()) 
        SKColorType colorType = pixmap.ColorType;
        SKAlphaType alphaType = pixmap.AlphaType;
    
 else 
    // this is a texture on the GPU and can't be determined easily

更长的答案

所以现在更长的答案...SKColorTypeSKAlphaType 类型一起形成了 PixelFormat 的等价物。

例如:

PixelFormat.Format16bppRgb565 相当于:SKColorType.Rgb565SKAlphaType.Opaque PixelFormat.Format32bppArgb 相当于:SKColorType.Rgba8888(或在 Windows 上为 SKColorType.Bgra8888)和 SKAlphaType.Unpremul PixelFormat.Format32bppPArgb 相当于:SKColorType.Rgba8888(或在 Windows 上为 SKColorType.Bgra8888)和 SKAlphaType.Premul

Rgba8888Bgra8888 之间的主要区别在于应用运行的平台。通常,您会根据SKImageInfo.PlatformColorType 检查颜色类型,因为这将知道本机颜色类型应该是什么。

【讨论】:

以上是关于如何使用 SkiaSharp 查找解码位图的 PixelFormat的主要内容,如果未能解决你的问题,请参考以下文章

为啥 SkiaSharp.SKBitmap.Resize 返回 null?

如何获取位图信息,然后从 internet-inputStream 解码位图?

解码后的位图字节大小?

Android位图解码A

使用 Raspberry Pi 将图像发送到 Python 中的 QL-800 打印机时如何解码此错误?

在 Android 中以正确的大小解码位图