You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将TIFF图像转换为SkiaSharp的SKBitmap对象?

解决SkiaSharp中TIFF转SKBitmap的问题

我来帮你梳理下SkiaSharp处理TIFF转SKBitmap的可行方案,结合你提到的思路,给你详细拆解并补充实用的实现方式:

方案1:借助System.Drawing中转(简单易实现,注意平台限制)

System.Drawing确实能完成TIFF转PNG的操作,对于常规尺寸的图片来说效率完全够用,不过要注意它的平台局限性:在.NET Core/.NET 5+的非Windows平台(比如Linux、macOS)上,需要额外安装libgdiplus依赖,而且从.NET 6开始它被标记为Windows-only的库了。

如果你的场景是Windows环境,或者能接受非Windows平台的依赖安装,这个方案最省事。代码示例:

using System.Drawing;
using System.Drawing.Imaging;
using SkiaSharp;
using System.IO;

public static SKBitmap TiffToSkBitmapViaSystemDrawing(Stream tiffStream)
{
    // 加载TIFF流
    using var tiffImage = Image.FromStream(tiffStream);
    // 转为PNG内存流
    using var pngStream = new MemoryStream();
    tiffImage.Save(pngStream, ImageFormat.Png);
    pngStream.Seek(0, SeekOrigin.Begin);
    // 用SkiaSharp解码PNG得到SKBitmap
    return SKBitmap.Decode(pngStream);
}

⚠️ 注意:这个方法默认只处理TIFF的第一页,如果是多页TIFF,需要遍历FrameDimensions来获取每一页的图像。

方案2:使用LibTiff.Net(专业TIFF处理,跨平台可靠)

LibTiff.Net是专门针对TIFF格式的处理库,跨平台支持,能应对各种复杂的TIFF场景(多页、不同压缩格式、特殊色彩空间等),比System.Drawing更稳定。下面给你TIFF流转SKBitmap的直接实现(也可以中转PNG流,不过直接转像素更高效):

首先需要安装对应的NuGet包BitMiracle.LibTiff.NET,然后看代码:

using BitMiracle.LibTiff.Classic;
using SkiaSharp;
using System.IO;

public static SKBitmap TiffToSkBitmapViaLibTiff(Stream tiffStream)
{
    // 打开内存中的TIFF流
    using var tiff = Tiff.ClientOpen("memory-tiff", "r", tiffStream, new TiffStream());
    if (tiff == null)
        throw new InvalidOperationException("无法读取TIFF流");

    // 获取TIFF的基本参数
    int width = tiff.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
    int height = tiff.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
    int stride = tiff.ScanlineSize();

    // 读取所有扫描线的像素数据
    byte[] pixelBuffer = new byte[stride * height];
    for (int y = 0; y < height; y++)
    {
        tiff.ReadScanline(pixelBuffer, y);
    }

    // 创建SKBitmap并写入像素
    var imageInfo = new SKImageInfo(width, height, SKColorType.Rgb888, SKAlphaType.Opaque);
    var skBitmap = new SKBitmap(imageInfo);
    skBitmap.WritePixels(imageInfo, pixelBuffer, stride, 0, 0);

    return skBitmap;
}

如果一定要中转成PNG流,也可以在得到SKBitmap后做编码:

// 将SKBitmap编码为PNG流
using var pngStream = new MemoryStream();
skBitmap.Encode(pngStream, SKEncodedImageFormat.Png, 100);
pngStream.Seek(0, SeekOrigin.Begin);
// 后续可以用这个PNG流做其他操作,或者重新解码为SKBitmap
var reDecodedBitmap = SKBitmap.Decode(pngStream);

这个方案的优势是能完美处理多页TIFF,通过调用tiff.ReadDirectory()可以遍历每一页图像,适合专业的TIFF处理场景。

方案3:直接读取TIFF像素绘制到SKCanvas

这个思路本质和方案2类似,都是直接操作像素数据。但TIFF的格式非常复杂,包含多种压缩算法、色彩空间,自己写解析逻辑成本极高,除非你只需要处理特定格式的无压缩TIFF,否则不建议自己造轮子,直接用LibTiff.Net或者ImageSharp会更高效。

额外推荐:使用ImageSharp中转(跨平台友好,API简洁)

ImageSharp是一款现代跨平台图像处理库,原生支持TIFF格式,而且和SkiaSharp的兼容性很好,没有System.Drawing的平台限制,API也更简洁。

先安装NuGet包SixLabors.ImageSharpSixLabors.ImageSharp.Formats.Tiff,然后看代码:

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SkiaSharp;
using System.IO;

public static SKBitmap TiffToSkBitmapViaImageSharp(Stream tiffStream)
{
    // 加载TIFF流
    using var tiffImage = Image.Load<Rgba32>(tiffStream);
    // 转为PNG内存流
    using var pngStream = new MemoryStream();
    tiffImage.Save(pngStream, new PngEncoder());
    pngStream.Seek(0, SeekOrigin.Begin);
    // 解码为SKBitmap
    return SKBitmap.Decode(pngStream);
}

这个方案处理多页TIFF也很方便,通过tiffImage.Frames可以遍历每一页,非常适合跨平台的项目场景。


总结一下:

  • 简单场景+Windows环境:选System.Drawing
  • 跨平台+常规TIFF处理:选ImageSharp
  • 专业TIFF需求(多页、特殊压缩):选LibTiff.Net
  • 自己解析TIFF:仅在处理特定极简TIFF时考虑,否则不推荐

内容的提问来源于stack exchange,提问作者Doug S

火山引擎 最新活动