3 回复
先来看真机效果:

有以下两种方式使图片产生灰度效果:
1、直接使用组件的通用属性grayscale
Image($r('app.media.yd')).grayscale(1) //1置灰,0无变化
2、通过读取图片的像素数据结合TaskGroup将其以rgba的格式分为四份在代码里面处理:
- TaskGroup:表示任务组,一次执行一组任务,适用于执行一组有关联的任务。如果所有任务正常执行,异步执行完毕后返回所有任务结果的数组,数组中元素的顺序与addTask的顺序相同;如果任意任务失败,则会抛出对应异常。如果任务组中存在多个任务失败的情况,则会抛出第一个失败任务的异常。任务组可以多次执行,但执行后不能新增任务。
资源图片转为pixelMap
// 通过media目录下的文件名称创建pixelMap。
getPixmapFromMediaSync(resource: Resource): image.PixelMap {
const context = this.getUIContext().getHostContext() as common.UIAbilityContext;
const resourceMgr = context.resourceManager;
const fileData = resourceMgr.getMediaContentSync(resource.id);
const imageSource = image.createImageSource(fileData.buffer);
const pixelMap = imageSource.createPixelMapSync();
imageSource.release();
return pixelMap;
}
pixelMap分成四段并发调度
// 读取pixelMap的像素数据
let width = pixelMap.getImageInfoSync().size.width;
let height = pixelMap.getImageInfoSync().size.height;
let readBuffer: ArrayBuffer = new ArrayBuffer(width * height * 4);
pixelMap.readPixelsToBufferSync(readBuffer);
// 分成四段并发调度
let number: number = 4 * Math.ceil(width * height / 4);
let buffer1: ArrayBuffer = readBuffer.slice(0, number);
let buffer2: ArrayBuffer = readBuffer.slice(number, number * 2);
let buffer3: ArrayBuffer = readBuffer.slice(number * 2, number * 3);
let buffer4: ArrayBuffer = readBuffer.slice(number * 3);
装填TaskGroup
let group: taskpool.TaskGroup = new taskpool.TaskGroup();
group.addTask(imageProcessing, buffer1);
group.addTask(imageProcessing, buffer2);
group.addTask(imageProcessing, buffer3);
group.addTask(imageProcessing, buffer4);
function imageProcessing(dataSlice: ArrayBuffer): Uint8Array {
// 图像灰度化处理操作
let byteBuffer: Uint32Array = new Uint32Array(dataSlice);
let byteBufferTemp: Uint8Array = new Uint8Array(new ArrayBuffer(byteBuffer.length * 4));
for (let index = 0; index < byteBuffer.length; index++) {
// 通过移位方式获取RGBA各通道的值。
let rgb = byteBuffer[index];
let red = (rgb >> 0) & 0x000000ff;
let green = (rgb >> 8) & 0x000000ff;
let blue = (rgb >> 16) & 0x000000ff;
let alpha = (rgb >> 24) & 0x000000ff;
// 加权平均算法,获取灰度值。
let gray = (0.299 * red + 0.587 * green + 0.114 * blue);
byteBufferTemp[index * 4] = gray;
byteBufferTemp[index * 4 + 1] = gray;
byteBufferTemp[index * 4 + 2] = gray;
byteBufferTemp[index * 4 + 3] = alpha;
}
return byteBufferTemp;
}
开启图片处理线程,将像素做灰度化。
taskpool.execute(group, taskpool.Priority.HIGH).then((res: Array<Object>) => {
// 结果数组汇总处理,重新编码为图片。
console.info('execute res success', res.length);
let byteBufferTemp: Uint8Array = new Uint8Array(new ArrayBuffer(width * height * 4));
let offset: number = 0;
for (let index = 0; index < res.length; index++) {
const element = res[index] as Uint8Array;
byteBufferTemp.set(element, offset);
offset += element.length;
}
let color: ArrayBuffer = byteBufferTemp.buffer as ArrayBuffer;
let opts: image.InitializationOptions =
{
editable: true,
pixelFormat: pixelMap.getImageInfoSync().pixelFormat,
size: { height: height, width: width }
};
this.pixelMapTemp = image.createPixelMapSync(color, opts);
console.info('execute group success');
});
})
完整代码:
组件引用
import { GrayView } from 'xx';
@Entry
@Component
struct Index {
build() {
Column() {
GrayView2()
}
.height('100%')
.width('100%')
}
}
GrayView & GrayView2
import { taskpool } from '@kit.ArkTS';
import { image } from '@kit.ImageKit';
import { common } from '@kit.AbilityKit';
@Component
export struct GrayView2 {
@State isGray: boolean = false;
build() {
Column(){
Button('grayscale:开启灰度效果').onClick(()=>{
this.isGray = true
}).margin({bottom:10})
Image($r('app.media.yd')).backgroundColor(Color.Pink).width('50%').grayscale(this.isGray?1:0)
GrayView()
}.justifyContent(FlexAlign.Center)
.height('100%')
.width('100%')
}
}
@Concurrent
function imageProcessing(dataSlice: ArrayBuffer): Uint8Array {
// 图像灰度化处理操作
let byteBuffer: Uint32Array = new Uint32Array(dataSlice);
let byteBufferTemp: Uint8Array = new Uint8Array(new ArrayBuffer(byteBuffer.length * 4));
for (let index = 0; index < byteBuffer.length; index++) {
// 通过移位方式获取RGBA各通道的值。
let rgb = byteBuffer[index];
let red = (rgb >> 0) & 0x000000ff;
let green = (rgb >> 8) & 0x000000ff;
let blue = (rgb >> 16) & 0x000000ff;
let alpha = (rgb >> 24) & 0x000000ff;
// 加权平均算法,获取灰度值。
let gray = (0.299 * red + 0.587 * green + 0.114 * blue);
byteBufferTemp[index * 4] = gray;
byteBufferTemp[index * 4 + 1] = gray;
byteBufferTemp[index * 4 + 2] = gray;
byteBufferTemp[index * 4 + 3] = alpha;
}
return byteBufferTemp;
}
@Component
export struct GrayView {
@State pixelMap: image.PixelMap | undefined = undefined;
@State pixelMapTemp: image.PixelMap | undefined = undefined;
pixelMapGrayScale(pixelMap: PixelMap) {
// 读取pixelMap的像素数据
let width = pixelMap.getImageInfoSync().size.width;
let height = pixelMap.getImageInfoSync().size.height;
let readBuffer: ArrayBuffer = new ArrayBuffer(width * height * 4);
pixelMap.readPixelsToBufferSync(readBuffer);
// 分成四段并发调度
let number: number = 4 * Math.ceil(width * height / 4);
let buffer1: ArrayBuffer = readBuffer.slice(0, number);
let buffer2: ArrayBuffer = readBuffer.slice(number, number * 2);
let buffer3: ArrayBuffer = readBuffer.slice(number * 2, number * 3);
let buffer4: ArrayBuffer = readBuffer.slice(number * 3);
let group: taskpool.TaskGroup = new taskpool.TaskGroup();
group.addTask(imageProcessing, buffer1);
group.addTask(imageProcessing, buffer2);
group.addTask(imageProcessing, buffer3);
group.addTask(imageProcessing, buffer4);
taskpool.execute(group, taskpool.Priority.HIGH).then((res: Array<Object>) => {
// 结果数组汇总处理,重新编码为图片。
console.info('execute res success', res.length);
let byteBufferTemp: Uint8Array = new Uint8Array(new ArrayBuffer(width * height * 4));
let offset: number = 0;
for (let index = 0; index < res.length; index++) {
const element = res[index] as Uint8Array;
byteBufferTemp.set(element, offset);
offset += element.length;
}
let color: ArrayBuffer = byteBufferTemp.buffer as ArrayBuffer;
let opts: image.InitializationOptions =
{
editable: true,
pixelFormat: pixelMap.getImageInfoSync().pixelFormat,
size: { height: height, width: width }
};
this.pixelMapTemp = image.createPixelMapSync(color, opts);
console.info('execute group success');
});
}
aboutToAppear(): void {
//测试:资源图片转为pixelMap
this.pixelMap = this.getPixmapFromMediaSync($r('app.media.yd'));
}
// 通过media目录下的文件名称创建pixelMap。
getPixmapFromMediaSync(resource: Resource): image.PixelMap {
const context = this.getUIContext().getHostContext() as common.UIAbilityContext;
const resourceMgr = context.resourceManager;
const fileData = resourceMgr.getMediaContentSync(resource.id);
const imageSource = image.createImageSource(fileData.buffer);
const pixelMap = imageSource.createPixelMapSync();
imageSource.release();
return pixelMap;
}
build() {
Row() {
Column() {
Text('原图')
Image(this.pixelMap)
.objectFit(ImageFit.Contain)
.width('50%')
.margin({
bottom: 10,
left: 5,
right: 5
})
Text('灰度图')
Image(this.pixelMapTemp)
.objectFit(ImageFit.Contain)
.width('50%')
.margin({
top: 10,
left: 5,
right: 5
})
Button('TaskGroup:像素数据开启灰度效果')
.backgroundColor('#0D9FFB')
.margin({
top: 10,
bottom: 10,
left: 5,
right: 5
})
.onClick(() => {
this.pixelMapGrayScale(this.pixelMap as image.PixelMap);
})
}
.width('100%')
}
.height('100%')
}
}
相关文档:
更多关于HarmonyOS鸿蒙Next中如何给图片设置灰度效果?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,可通过PixelMap的createPixelMapWithFilter方法,使用Filter类中的GRAYSCALE滤镜直接为图片设置灰度效果。具体步骤包括:先获取图片资源,转换为PixelMap对象,然后应用灰度滤镜处理。
在HarmonyOS Next中,可以通过ArkUI的图片处理能力,使用ImageFilter轻松实现图片灰度效果。
核心方法是使用ImageFilter.grayscale()滤镜。具体实现有两种常用方式:
1. 在Image组件中直接应用滤镜:
Image($r('app.media.myImage'))
.width(200)
.height(200)
.imageFilter(ImageFilter.grayscale()) // 应用灰度滤镜
2. 使用自定义组件封装滤镜效果:
@Component
struct GrayImage {
@Prop src: Resource
@State filter: ImageFilter = ImageFilter.grayscale()
build() {
Image(this.src)
.imageFilter(this.filter)
}
}
关键说明:
ImageFilter.grayscale()会将彩色图像转换为灰度图像,转换系数遵循标准的亮度公式- 滤镜效果会实时渲染,支持动画过渡效果
- 可与其他滤镜链式组合,如模糊、色彩调整等
- 性能经过优化,适合列表等高频渲染场景
此方法适用于所有Image组件支持的图片资源类型,包括网络图片和本地资源。


