- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
目前,SkiaSharp 不支持 tiff 图像。 (它支持 jpg、gif、bmp、png 和其他一些格式。)
如何将 tiff 图像转换为 SKBitmap 对象?
一个想法:也许有一种有效的方法来转换 tiff 流 > png 流 > SKBitmap 对象?我不确定 System.Drawing
能否有效处理 tiff>png 流。另一个可能的选项是 LibTiff.Net ,尽管需要一个示例来说明如何将 tiff 流转换为 png 流。
另一个想法:访问 tiff 像素并将其直接绘制到 SKCanvas 上?
其他想法?
最佳答案
@DougS
您的实现大部分是正确的,但由于多次内存分配和复制,性能不是很好。
我注意到您正在创建 3 个内存块,每个内存块的总大小为(w*h*4 字节):
// the int[]
raster = new int[width * height];
// the SKColor[]
pixels = new SKColor[width * height];
// the bitmap
bitmap = new SKBitmap(width, height)
您也在多次复制内存之间的像素:
// decode the TIFF (first copy)
tifImg.ReadRGBAImageOriented(width, height, raster, Orientation.TOPLEFT)
// convert to SKColor (second copy)
pixels[arrayOffset] = new SKColor(...);
// set bitmap pixels (third copy)
bitmap.Pixels = pixels;
我想我设法创建了一个类似的解码流的方法,只有一个副本和内存分配:
public static SKBitmap OpenTiff(Stream tiffStream)
{
// open a TIFF stored in the stream
using (var tifImg = Tiff.ClientOpen("in-memory", "r", tiffStream, new TiffStream()))
{
// read the dimensions
var width = tifImg.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
var height = tifImg.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
// create the bitmap
var bitmap = new SKBitmap();
var info = new SKImageInfo(width, height);
// create the buffer that will hold the pixels
var raster = new int[width * height];
// get a pointer to the buffer, and give it to the bitmap
var ptr = GCHandle.Alloc(raster, GCHandleType.Pinned);
bitmap.InstallPixels(info, ptr.AddrOfPinnedObject(), info.RowBytes, null, (addr, ctx) => ptr.Free(), null);
// read the image into the memory buffer
if (!tifImg.ReadRGBAImageOriented(width, height, raster, Orientation.TOPLEFT))
{
// not a valid TIF image.
return null;
}
// swap the red and blue because SkiaSharp may differ from the tiff
if (SKImageInfo.PlatformColorType == SKColorType.Bgra8888)
{
SKSwizzle.SwapRedBlue(ptr.AddrOfPinnedObject(), raster.Length);
}
return bitmap;
}
}
要点住在这里:https://gist.github.com/mattleibow/0a09babdf0dc9d2bc3deedf85f9b57d6
让我解释一下代码...我基本上是像您一样创建 int[]
,然后将其传递给 SKBitmap
并让它接管。我固定它是因为 SKBitmap
位于非托管内存中,GC 可能会移动它,但我肯定会在处理位图时取消固定它。
下面是更详细的步骤:
// this does not actually allocate anything
// - the size is 0x0 / 0 bytes of pixels
var bitmap = new SKBitmap();
// I create the only buffer for pixel data
var raster = new int[width * height];
// pin the managed array so it can be passed to unmanaged memory
var ptr = GCHandle.Alloc(raster, GCHandleType.Pinned);
// pass the pointer of the array to the bitmap
// making sure to free the pinned memory in the dispose delegate
// - this is also not an allocation, as the memory already exists
bitmap.InstallPixels(info, ptr.AddrOfPinnedObject(), info.RowBytes, null, (addr, ctx) => ptr.Free(), null);
// the first and only copy from the TIFF stream into memory
tifImg.ReadRGBAImageOriented(width, height, raster, Orientation.TOPLEFT)
// an unfortunate extra memory operation for some platforms
// - this is usually just for Windows as it uses a BGR color format
// - Linux, macOS, iOS, Android all are RGB, so no swizzle is needed
SKSwizzle.SwapRedBlue(ptr.AddrOfPinnedObject(), raster.Length);
仅对于调试 session 中的一些原始统计数据,您的代码对我的一张图像大约需要 500 毫秒,但我的代码只需要 20 毫秒。
我希望我对您的代码听起来不会太苛刻/太消极,我绝不是那个意思。
关于c# - SkiaSharp Tiff 支持,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50312937/
我试图找出由字节数组加载到 SKBitmap 的图像的格式。我只想知道它是 JPEG 还是 PNG 等。 // Was the decoding done by a JPEG decoder or P
SkiaSharp 是一个跨平台的 2D 图形 API,用于 .NET 平台,基于 Google 的 Skia 图形库。它提供了全面的 2D API,可以在移动、服务器和桌面模型上渲染图像。SkiaS
我正在使用 SkiaSharp 将标签打印为 PDF(和其他内容)。 PDF 的每一页都可以有多个行和列。我需要将每个标签剪裁到正确的大小,这样它就不会破坏相邻的标签。 为了测试,每个标签都有一个延伸
我正在尝试使用以下代码在 SkiaSharp Canvas View 上绘制圆弧。 path3.ArcTo(new SKPoint(0, h/2), 1.57f, SKPathArcSize.Larg
我正在尝试使用以下代码在 SkiaSharp Canvas View 上绘制圆弧。 path3.ArcTo(new SKPoint(0, h/2), 1.57f, SKPathArcSize.Larg
我正在尝试创建一个 Remote ,但不确定如何使用如下图所示的圆弧绘制路径。 我考虑过使用 SKPath.DrawArc 来绘制那个按钮。当用户点击屏幕时,我可以比较触摸点在 SKPath 内部。目
我想镜像一个位图,这样我就可以让一个图像和它的镜像彼此相邻。我正在使用 SkiaSharp,我的位图是 SKBitmap,我正在 Canvas 上绘制它们。 canvas.Translate( -im
我正在尝试使用 Xamarin SkiaSharp 实现流畅的动画。核心问题是调用 canvasView.InvalidateSurface(); 之间的时间。并点击 mathod OnCanvasV
我正在使用 SkiaSharp 对一些图像进行切片,一些图片没有覆盖整个位图,看起来有些图片上有随机噪声。 最简单的复制方法就是创建新的空位图并将它们保存在一个循环中。像这样: // imgSize
当文本在前缀或后缀中包含空格时,SkiaSharp 不考虑空格。它仅返回文本宽度并忽略空格。我正在使用以下代码片段来测量字符串。 SKPaint paint = new SKPaint
如何在 SkiaSharp 中绘制旋转文本。 目前我正在旋转 SKCanvas,绘制文本,然后将其旋转回来。但我认为可能有一种更有效的方法来做到这一点。 canvas.RotateDegrees(45
我尝试使用 SkiaSharp 将照片旋转到 90 度,代码如下: public SKBitmap Rotate() { var bitmap = SKBitmap.D
目前,SkiaSharp 不支持 tiff 图像。 (它支持 jpg、gif、bmp、png 和其他一些格式。) 如何将 tiff 图像转换为 SKBitmap 对象? 一个想法:也许有一种有效的方法
如何在 iOS 中使用 Skia Sharp 添加矩形或任何形状并将填充颜色和描边颜色应用于该对象 最佳答案 要同时绘制填充和描边,您必须执行两个绘制操作: // the rectangle var
使用 GDI 时,我能够设置 Pen::Alignment to Inset , 它在路径的内侧绘制了笔划。 SkiaSharp 是否有类似的概念?我已经搜索了所有 SKPaint 文档,但没有找到我
我从未在编程中使用过 SkiaSharp 或处理过 SVG 和旋转点。我对矩阵的工作原理感到困惑;研究时看起来很复杂。我知道我可以将我的 pivotX/Y 点移动到中心,这样我就可以说我想将图像旋转
我正在尝试绘制和填充一个三角形。我提到了一个 android - 问题 How to draw filled triangle on android Canvas并做了以下事情。它绘制了三角形,但没有
我知道 SkiaSharp Canvas 可以放置在 Xamarin 应用程序的 Grid 中。这是一些示例(工作)代码: xmlns:skia="clr-namespace:SkiaSharp.Vi
有人知道如何在 SkiaSharp.Views.UWP 命名空间中使用 SKXamlCanvas 吗? 我找到了关于 SkiaSharp.Views.Forms 和 SKCanvasView 的信息。
我知道 SkiaSharp Canvas 可以放置在 Xamarin 应用程序的 Grid 中。这是一些示例(工作)代码: xmlns:skia="clr-namespace:SkiaSharp.Vi
我是一名优秀的程序员,十分优秀!