鸿蒙开发-想让图片放大不模糊?SamplingOptions采样选项
2026/6/5 19:28:50 网站建设 项目流程

你有没有注意到,有时候把一张小图放大显示,会变得很模糊或者有很多锯齿?而有时候放大后虽然也不够清晰,但至少边缘比较平滑?这背后的原因就是"采样方式"不同。

在 HarmonyOS 的 drawing 模块里,SamplingOptions就是用来控制图片缩放时的采样质量的。简单说,它决定了当你把一张图片放大或缩小显示时,系统用什么算法来计算每个像素的颜色。

什么是采样?

下面是两种采样模式的选择决策流程:

图片需要缩放显示

使用哪种采样模式?

FILTER_MODE_NEAREST 最近邻

FILTER_MODE_LINEAR 线性采样

直接复制最近像素颜色

速度快 保持锐利边缘

可能有锯齿和马赛克

周围像素加权平均

速度稍慢 效果平滑

可能有点模糊

打个比方:你有一张 100x100 的小图片,想把它显示在 200x200 的区域里。这时候图片需要"放大",多出来的那些像素该填什么颜色?这就是"采样"要解决的问题。

不同的采样算法会产生不同的效果:

  • 有的算法追求速度,放大会有很多锯齿
  • 有的算法追求质量,放大会比较平滑但可能有点模糊

创建 SamplingOptions

默认构造

import{RenderNode}from'@kit.ArkUI';import{common2D,drawing}from'@kit.ArkGraphics2D';classDrawingRenderNodeextendsRenderNode{draw(context:DrawContext){constcanvas=context.canvas;constpen=newdrawing.Pen();letsamplingOptions=newdrawing.SamplingOptions();}}

无参构造函数创建的 SamplingOptions,默认使用FILTER_MODE_NEAREST(最近邻采样)。

指定过滤模式构造

import{RenderNode}from'@kit.ArkUI';import{common2D,drawing}from'@kit.ArkGraphics2D';classDrawingRenderNodeextendsRenderNode{draw(context:DrawContext){constcanvas=context.canvas;letsamplingOptions=newdrawing.SamplingOptions(drawing.FilterMode.FILTER_MODE_NEAREST);}}

你也可以在构造时直接指定过滤模式。

FilterMode:过滤模式

FilterMode是一个枚举,目前有两个值:

FILTER_MODE_NEAREST(最近邻采样)

这是默认的模式。它的原理很简单:放大图片时,每个新像素直接复制离它最近的原始像素的颜色。

优点:速度最快,不会引入额外的模糊。
缺点:放大后会有明显的锯齿和"马赛克"效果,特别是放大倍数比较大的时候。

适用场景:

  • 像素风格的游戏(故意要那种"马赛克"效果)
  • 需要保持锐利边缘的图标放大
  • 对性能要求很高的实时渲染

FILTER_MODE_LINEAR(线性采样)

线性采样会考虑周围多个像素的颜色,然后做加权平均。

优点:放大后比较平滑,没有明显锯齿。
缺点:速度比最近邻稍慢,可能会让图片看起来有点"模糊"。

适用场景:

  • 照片类图片的缩放
  • 需要平滑效果的 UI 元素
  • 对画质要求比较高的场景

怎么使用 SamplingOptions?

SamplingOptions 通常是在绘制图片时配合 Canvas 的方法使用的。比如在调用canvas.drawImageRect之类的方法时,传入 SamplingOptions 来控制采样方式:

import{RenderNode}from'@kit.ArkUI';import{common2D,drawing}from'@kit.ArkGraphics2D';classDrawingRenderNodeextendsRenderNode{draw(context:DrawContext){constcanvas=context.canvas;// 创建采样选项,使用线性采样letsamplingOptions=newdrawing.SamplingOptions(drawing.FilterMode.FILTER_MODE_LINEAR);// 假设你有一个 pixelMap// canvas.drawImageRect(pixelMap, srcRect, dstRect, samplingOptions);}}

在绘制的时候,系统会根据你设置的 SamplingOptions 来决定用什么算法进行像素采样。

两种模式的视觉区别

让我用更具体的方式来说明两种模式的区别:

放大一个小图标(比如 16x16 放大到 64x64)

  • NEAREST:你会看到明显的"像素块",每个原始像素变成了 4x4 的方块。边缘是"阶梯状"的。
  • LINEAR:边缘会比较平滑,像素之间的过渡更自然,但整体可能看起来有点"糊"。

缩小一张大图片(比如 1000x1000 缩小到 100x100)

  • NEAREST:可能会出现"摩尔纹"(一种奇怪的波纹图案),因为很多像素被直接跳过了。
  • LINEAR:缩小后的图片比较平滑,不会有奇怪的纹路。

实际应用场景

根据应用场景选择采样模式:

像素风格游戏

照片查看器

地图渲染

头像裁剪预览

缩小

放大到像素级

应用场景

什么类型的图片?

使用 NEAREST

使用 LINEAR

缩放级别决定

使用 LINEAR

保持像素感和锐利边缘

缩放过程平滑自然

LINEAR 避免摩尔纹

NEAREST 保持清晰

预览效果更平滑

场景一:像素风格游戏

如果你在做一个复古风格的像素游戏,角色图片很小(比如 32x32),需要放大显示。这时候用 NEAREST 可以保持那种"像素感":

letsamplingOptions=newdrawing.SamplingOptions(drawing.FilterMode.FILTER_MODE_NEAREST);// 放大绘制像素风格的角色图片

场景二:照片查看器

做一个照片查看 APP,用户可以放大缩小查看照片。这时候用 LINEAR 可以让缩放过程更平滑:

letsamplingOptions=newdrawing.SamplingOptions(drawing.FilterMode.FILTER_MODE_LINEAR);// 缩放绘制照片

场景三:地图渲染

地图瓦片在不同缩放级别下需要不同的采样策略。缩小时用 LINEAR 避免摩尔纹,放大到一定程度切换到 NEAREST 保持清晰。

场景四:头像裁剪

用户裁剪头像时,预览区域需要放大显示。用 LINEAR 可以让预览看起来更平滑,用户体验更好。

性能考虑

NEAREST 模式的性能比 LINEAR 好,因为它的计算更简单。在以下情况建议用 NEAREST:

  • 需要高频绘制(比如游戏的每帧渲染)
  • 图片本身就是像素风格的
  • 对性能要求极高的场景

在以下情况建议用 LINEAR:

  • 绘制照片或自然图像
  • 用户可以看到缩放过程(比如手势缩放)
  • 对画质要求高于性能

注意事项

  1. API 版本:SamplingOptions 从 API version 12 开始支持。

  2. 物理像素:和其他 drawing 对象一样,使用物理像素单位。

  3. 线程安全:单线程模型,需要自己管理线程安全。

  4. 默认值:无参构造默认使用 NEAREST 模式。

  5. 和 BitmapShader 配合:SamplingOptions 也可以在创建 BitmapShader 时使用,控制纹理采样的质量。

小结

SamplingOptions 是一个简单但重要的工具,专门控制图片缩放时的采样质量。它只有两个选择:

  • NEAREST:速度快,保持锐利,但可能有锯齿
  • LINEAR:速度稍慢,效果平滑,但可能有点模糊

根据你的具体需求选择合适的模式就好。大多数情况下,LINEAR 是更安全的选择,除非你特别需要那种"像素风"的效果或者对性能有极致要求。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询