
图形学图像处理跨平台【免费下载链接】SkiaSharpSkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Googles Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.项目地址https://gitcode.com/gh_mirrors/sk/SkiaSharp点击查看免费下载导读SkiaSharp 2.88.0 对 Tizen 平台的视图层SkiaSharp.Views.Tizen进行了一轮聚焦于表面尺寸信息的 API 升级为绘制事件参数引入Info/RawInfo双信息模型新增GetRawSurfaceSize()表面尺寸查询钩子并开放ScalingInfo.SetScalingFactor()让开发者可以接管屏幕密度换算。本文以 SkiaSharp.Views.Tizen.dll 的 2.88.0 API 差异文档 为骨架结合 Tizen 平台源码 逐项解读这些变更的设计意图、底层调用链与迁移方法帮助 Tizen 应用开发者完成 2.80 → 2.88 的平滑升级并学会在高 DPI 设备上精确控制绘图画布尺寸。程序集级变更版本号从 2.80.0 升级到 2.88.0差异文档开篇首先记录了程序集版本的变化Assembly Version Changed: 2.88.0.0 vs 2.80.0.0这意味着本次 diff 实际比较的是 2.80.0 与 2.88.0 两个版本之间SkiaSharp.Views.Tizen.dll的公开 API 差异涉及命名空间SkiaSharp.Views.Tizen下的 5 个类型。所有变更围绕同一个主题让绘制事件携带逻辑画布尺寸与原始像素尺寸两套信息并让这两套尺寸的产生过程对开发者可见、可控制。RawInfo 机制区分逻辑画布与原始像素表面2.88.0 之前绘制事件只携带一份表面信息在开启像素缩放Pixel Scaling的场景下开发者无法区分视图对应的逻辑尺寸与底层真实分配的像素尺寸。2.88.0 通过给事件参数增加RawInfo属性与对应构造函数建立了双信息模型。SKPaintSurfaceEventArgs新增 RawInfo 属性与三参数构造函数SKPaintSurfaceEventArgs软渲染画布视图SKCanvasView的绘制事件参数新增public SKPaintSurfaceEventArgs (SkiaSharp.SKSurface surface, SkiaSharp.SKImageInfo info, SkiaSharp.SKImageInfo rawInfo); public SkiaSharp.SKImageInfo RawInfo { get; }该类型由共享源码编译而来在 SkiaSharp.Views.Shared/SKPaintSurfaceEventArgs.cs 中可以看到三参数构造函数是核心实现原有的两参数构造函数只是它的便捷重载public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info) : this(surface, info, info) // 默认 rawInfo info { } public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info, SKImageInfo rawInfo) { Surface surface; Info info; RawInfo rawInfo; }三个属性的语义在源码注释中界定得很清楚Surface当前正在绘制的SKSurfaceInfo逻辑画布的信息即开发者绘图时使用的尺寸与色彩类型RawInfo底层表面的原始图像信息包含底层表面实际的尺寸与色彩类型the actual dimensions and color type of the underlying surface。SKPaintGLSurfaceEventArgs废弃 glInfo 构造器全面切换到 SKImageInfoGL 硬件加速路径的事件参数SKPaintGLSurfaceEventArgs变化更大分为废弃与新增两部分。废弃的构造函数带有[Obsolete]特性提示改用新签名[Obsolete (Use SKPaintGLSurfaceEventArgs(SKSurface, GRBackendRenderTarget, GRSurfaceOrigin, SKColorType) instead.)] public SKPaintGLSurfaceEventArgs (SkiaSharp.SKSurface surface, SkiaSharp.GRBackendRenderTarget renderTarget, SkiaSharp.GRSurfaceOrigin origin, SkiaSharp.SKColorType colorType, SkiaSharp.GRGlFramebufferInfo glInfo);新增的两个构造函数public SKPaintGLSurfaceEventArgs (SkiaSharp.SKSurface surface, SkiaSharp.GRBackendRenderTarget renderTarget, SkiaSharp.GRSurfaceOrigin origin, SkiaSharp.SKImageInfo info); public SKPaintGLSurfaceEventArgs (SkiaSharp.SKSurface surface, SkiaSharp.GRBackendRenderTarget renderTarget, SkiaSharp.GRSurfaceOrigin origin, SkiaSharp.SKImageInfo info, SkiaSharp.SKImageInfo rawInfo);新增的两个属性public SkiaSharp.SKImageInfo Info { get; } public SkiaSharp.SKImageInfo RawInfo { get; }在共享源码 SKPaintGLSurfaceEventArgs.cs 中可以看到这组构造器的完整实现逻辑// 以 SKColorType 为参数的旧式构造未废弃版本 public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTarget renderTarget, GRSurfaceOrigin origin, SKColorType colorType) { Surface surface; BackendRenderTarget renderTarget; ColorType colorType; Origin origin; Info new SKImageInfo(renderTarget.Width, renderTarget.Height, ColorType); // Info 由 renderTarget 推导 RawInfo Info; // 默认 RawInfo Info } // 新增显式传入 SKImageInfo 的构造函数 public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTarget renderTarget, GRSurfaceOrigin origin, SKImageInfo info) : this(surface, renderTarget, origin, info, info) { } // 新增完整双信息构造函数 public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTarget renderTarget, GRSurfaceOrigin origin, SKImageInfo info, SKImageInfo rawInfo) { Surface surface; BackendRenderTarget renderTarget; ColorType info.ColorType; // ColorType 改由 info 提供 Origin origin; Info info; RawInfo rawInfo; }这次重构的要点在于旧的GRGlFramebufferInfo参数不再需要由调用方显式传入事件参数内部直接以SKImageInfo承载表面信息。ColorType属性现在统一取自info.ColorTypeInfo也不再从renderTarget隐式推导而是由调用方显式指定——这为逻辑尺寸与像素尺寸不一致的场景如IgnorePixelScaling true提供了表达空间。GetRawSurfaceSize让原始像素尺寸的获取可被重写CustomRenderingView新增可重写的虚方法CustomRenderingView是所有 Tizen 渲染视图的抽象基类继承自 ElmSharp 的Widget2.88.0 为其新增了protected virtual SkiaSharp.SKSizeI GetRawSurfaceSize ();从 CustomRenderingView.cs 的源码看基类实现直接委托给GetSurfaceSize()/// summaryGets the raw pixel size of the drawing surface./summary protected virtual SKSizeI GetRawSurfaceSize() GetSurfaceSize();而GetSurfaceSize()本身是抽象方法由派生类返回当前绘制表面尺寸因此基类的默认行为是在没有特殊处理的情况下原始像素尺寸等于表面尺寸。新增GetRawSurfaceSize的意义在于给派生类一个在表面尺寸之外另行报告像素尺寸的扩展点。它的调用位置在OnResized()中——当视图几何尺寸变化时基类会走更新尺寸 → 销毁旧表面 → 用原始像素尺寸重设 EFL 图像大小 → 重建绘制表面 → 重绘的完整流程protected void OnResized() { var geometry Geometry; // control is not yet fully initialized if (geometry.Width 0 || geometry.Height 0) return; if (UpdateSurfaceSize(geometry)) { // disconnect the callback Evas.evas_object_image_native_surface_set(evasImage, IntPtr.Zero); // recreate the drawing surface to match the new size DestroyDrawingSurface(); var size GetRawSurfaceSize(); Evas.evas_object_image_size_set(evasImage, size.Width, size.Height); CreateDrawingSurface(); // set the image callback; will be invoked when image is marked as dirty Evas.evas_object_image_pixels_get_callback_set(evasImage, redrawCallback, IntPtr.Zero); // repaint Invalidate(); } }也就是说GetRawSurfaceSize()返回的值会直接决定底层 EFLevas_object_image的真实像素尺寸是原始像素表面的尺寸来源。SKCanvasView重写并返回底层图像信息SKCanvasView基于 CPU 的软件渲染画布视图重写了该方法protected override SkiaSharp.SKSizeI GetRawSurfaceSize ();其实现位于 SKCanvasView.cs直接返回内部维护的info.Sizeprotected override SKSizeI GetSurfaceSize() canvasSize; protected override SKSizeI GetRawSurfaceSize() info.Size;结合UpdateSurfaceSize的实现可以看到两套尺寸的完整分工protected sealed override bool UpdateSurfaceSize(Rect geometry) { var w info.Width; var h info.Height; info.Width geometry.Width; // 底层像素尺寸 视图几何尺寸 info.Height geometry.Height; if (IgnorePixelScaling) { // 逻辑画布尺寸 像素尺寸 ÷ 缩放因子device-independent pixels canvasSize.Width (int)Math.Round(ScalingInfo.FromPixel(geometry.Width)); canvasSize.Height (int)Math.Round(ScalingInfo.FromPixel(geometry.Height)); } else { // 默认1 画布像素 1 显示像素 canvasSize.Width geometry.Width; canvasSize.Height geometry.Height; } return (w ! info.Width || h ! info.Height); }info原始像素信息始终等于视图的物理像素尺寸canvasSize逻辑画布尺寸默认等于物理像素当IgnorePixelScaling true时换算为设备无关像素。在OnDrawFrame中事件参数正是用这两套尺寸构造的// draw directly into the EFL image data using var surface SKSurface.Create(info, Evas.evas_object_image_data_get(evasImage, true), info.RowBytes); if (IgnorePixelScaling) { var skiaCanvas surface.Canvas; skiaCanvas.Scale((float)ScalingInfo.ScalingFactor); skiaCanvas.Save(); } // draw using SkiaSharp OnDrawFrame(new SKPaintSurfaceEventArgs(surface, info.WithSize(canvasSize), info)); surface.Canvas.Flush();这里info.WithSize(canvasSize)生成的就是Info逻辑画布信息原样传入的info就是RawInfo。事件处理代码中e.Info.Width/Height给出的是设备无关的绘图坐标e.RawInfo则给出真实的像素信息。GL 路径RawInfo 与渲染目标的对应关系硬件加速视图SKGLSurfaceView走的是另一条链路见 SKGLSurfaceView.cs它通过 EFL 的 Evas GL 接口创建 OpenGL ES 上下文用GRGlInterface.CreateEvas获取 GL 函数指针、创建GRContext与GRBackendRenderTarget最终调用OnDrawFrame(new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType));在 GL 路径下事件参数内部会用renderTarget.Width/Height推导出Info并让RawInfo Info见共享源码中SKColorType构造器的实现。2.88.0 新增的SKImageInfo重载则允许调用方显式指定这两份信息与软渲染路径保持一致的表达能力。ScalingInfo.SetScalingFactor屏幕密度换算的可控化默认缩放因子的计算逻辑ScalingInfo是 Tizen 平台用于屏幕密度换算的静态工具类见 ScalingInfo.cs。2.88.0 之前缩放因子完全由设备自动推导public static class ScalingInfo { private static readonly Lazystring profile new Lazystring(() Elementary.GetProfile()); private static readonly Lazyint dpi new Lazyint(() { // TV has fixed DPI value (72) if (Profile tv) return 72; SystemInfo.TryGetValue(http://tizen.org/feature/screen.dpi, out int dpi); return dpi; }); // allows to convert pixels to Android-style device-independent pixels private static readonly Lazydouble scalingFactor new Lazydouble(() dpi.Value / 160.0); public static double ScalingFactor scalingFactorOverride ?? scalingFactor.Value; ... }默认算法要点通过Elementary.GetProfile()获取设备 profile通过 Tizen 系统特性http://tizen.org/feature/screen.dpi查询屏幕 DPITV 设备固定按 72 DPI 处理TV 场景的 UI 距离通常更远固定 DPI 是 Tizen 平台的既有约定缩放因子按 Android 风格的基准值计算ScalingFactor DPI / 160.0160 DPI 为 mdpi 基准即 320 DPI 设备上缩放因子为 2.0。新增的 SetScalingFactor 覆盖机制2.88.0 新增了静态方法public static void SetScalingFactor (double? scalingFactor);其实现非常简单private static double? scalingFactorOverride; public static void SetScalingFactor(double? scalingFactor) { scalingFactorOverride scalingFactor; }结合ScalingFactor属性scalingFactorOverride ?? scalingFactor.Value可以看出行为语义传入非null值用自定义缩放因子覆盖设备自动推导值传入null清除覆盖恢复为按设备 DPI 自动计算的默认值。配套的换算方法FromPixel/ToPixel均基于当前生效的ScalingFactor/// summaryConvert from raw pixels into device-independent pixels./summary public static double FromPixel(double v) v / ScalingFactor; /// summaryConvert from device-independent pixels into raw pixels./summary public static double ToPixel(double v) v * ScalingFactor;这个 API 的意义在于在某些设备上尤其是 DPI 上报不准确或需要统一 UI 密度的场景自动计算的缩放因子可能不符合应用的实际设计预期开发者现在可以在应用启动时主动设定例如// 固定按 2.0 倍缩放绘制逻辑画布 物理像素 / 2 ScalingInfo.SetScalingFactor(2.0); // 后续若需恢复设备自动值 ScalingInfo.SetScalingFactor(null);迁移指南从 2.80 升级到 2.88 的实操要点需要修改的代码位置自定义渲染视图的派生类如果直接继承CustomRenderingView或SKCanvasView并重写了尺寸相关逻辑2.88.0 新增的GetRawSurfaceSize()是protected虚方法不会破坏二进制兼容但值得利用它来精确控制底层像素分配例如为高 DPI 屏幕分配 2 倍像素缓冲。GL 绘制事件如果代码中显式构造了SKPaintGLSurfaceEventArgs(surface, renderTarget, origin, colorType, glInfo)编译器会给出[Obsolete]警告。新代码应改用SKImageInfo重载。注意旧colorType glInfo组合携带的信息已由SKImageInfo统一承载GRGlFramebufferInfo不再需要手动传入。事件处理中读取尺寸绘图代码如果依赖e.Info在开启IgnorePixelScaling时其语义是设备无关像素需要真实像素尺寸时应读取新增的e.RawInfo。完整的软渲染示例var myView new SKCanvasView(parent) { IgnorePixelScaling true, // 使用设备无关像素作为逻辑画布 }; myView.PaintSurface (sender, e) { var surface e.Surface; var canvas surface.Canvas; // e.Info逻辑画布设备无关像素绘图坐标以此为准 var logicalWidth e.Info.Width; var logicalHeight e.Info.Height; // e.RawInfo底层表面的真实像素信息 var pixelWidth e.RawInfo.Width; var pixelHeight e.RawInfo.Height; // 在逻辑画布上绘制 canvas.Clear(SKColors.White); using var paint new SKPaint { Color SKColors.Red, IsAntialias true }; canvas.DrawCircle(logicalWidth / 2f, logicalHeight / 2f, 50f, paint); canvas.Flush(); };注意如果通过重写OnDrawFrame(SKPaintSurfaceEventArgs e)的方式绘制必须调用base.OnDrawFrame(e)否则PaintSurface事件不会触发该约定在 SKCanvasView.cs 的 XML 文档中有明确标注。GL 路径的新式事件参数// 2.88.0 推荐用法以 SKImageInfo 描述表面 var args new SKPaintGLSurfaceEventArgs( surface, renderTarget, GRSurfaceOrigin.BottomLeft, info, rawInfo); // 可选不传时 RawInfo Info // 在事件中读取 var w e.Info.Width; // 逻辑画布宽 var rawW e.RawInfo.Width; // 原始像素宽小结SkiaSharp 2.88.0 对 SkiaSharp.Views.Tizen 的 API 调整本质上是把逻辑画布尺寸与原始像素尺寸从隐式推导变为显式建模事件参数层SKPaintSurfaceEventArgs/SKPaintGLSurfaceEventArgs新增RawInfo并配套提供显式传参的构造函数GL 路径同步废弃了GRGlFramebufferInfo旧构造器视图基类层CustomRenderingView新增GetRawSurfaceSize()虚方法SKCanvasView重写后以底层图像信息为准使OnResized()重建表面时能按真实像素尺寸分配 EFL 图像缓冲密度换算层ScalingInfo.SetScalingFactor(double?)让开发者可以覆盖设备 DPI 自动推导值并在需要时传null恢复默认。这些能力共同服务于高 DPI Tizen 设备上画质与性能的平衡默认 1 画布像素 1 显示像素保证清晰度IgnorePixelScaling配合SetScalingFactor则提供以设备无关像素绘图的轻量路径。延伸阅读仓库内相关源码事件参数共享实现SKPaintSurfaceEventArgs.cs、SKPaintGLSurfaceEventArgs.csTizen 视图基类与软渲染视图CustomRenderingView.cs、SKCanvasView.csTizen GL 硬件加速视图SKGLSurfaceView.cs屏幕密度工具ScalingInfo.cs渲染模式枚举WhenDirty/ContinuouslyRenderingMode.cs类型互转扩展TizenExtensions.cs本次差异原始文档SkiaSharp.Views.Tizen.dll API diff2.80 → 2.88赞分享图形学图像处理跨平台【免费下载链接】SkiaSharpSkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Googles Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.项目地址https://gitcode.com/gh_mirrors/sk/SkiaSharp点击查看免费下载相关推荐SkiaSharp 2.88.0 SkiaSharp.Views.iOS API 变更详解PaintSurface 事件参数引入 Info/RawInfo 双图像信息模型SkiaSharp 2.88.0 SkiaSharp.Views.iOS API 变更详解PaintSurface 事件参数引入 Info/RawInfo 双图形学图像处理跨平台SkiaSharp 2.88.0 中 SkiaSharp.Views.Forms 的 API 变更解读RawInfo 新增与过时构造函数清理SkiaSharp 2.88.0 中 SkiaSharp.Views.Forms 的 API 变更解读RawInfo 新增与过时构造函数清理 本篇技术指南以图形学图像处理跨平台SkiaSharp 2.88.0 桌面端 API 变更解析SkiaSharp.Views.Desktop.Common 中 Info 与 RawInfo 的分离设计SkiaSharp 2.88.0 桌面端 API 变更解析SkiaSharp.Views.Desktop.Common 中 Info 与 RawInfo 的分图形学图像处理跨平台创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考