HarmonyOS 应用开发-根据icon自适应背景颜色

介绍

本示例将介绍如何根据图片设置自适应的背景色。

效果图预览

使用说明

  1. 转换图片为PixelMap,取出所有像素值
  2. 遍历所有像素值,查找到出现次数最多的像素,即为图片的主要颜色
  3. 适当修改图片的主要颜色,作为自适应的背景色

实现思路

实现步骤

  1. 解码图片,转换为PixelMap对象,便于提取像素值
  2. 提取所有像素值,转换为整数,放入数组中
  3. 遍历数组,将所有像素值放入一个Map中,key为像素值,value为个数
  4. 遍历Map,找出出现次数最多的像素值
  5. 将整数格式的像素值转换为RGB格式,再转换为HSV格式,参考hue(色调)修改saturation(饱和度)和value(明度)
  6. 将HSV格式转换为RGB格式,就得到了背景色

具体实现

  1. 将图片转换为PixelMap
    ...
    let pixelMap: image.PixelMap = await image2PixelMap(item.icon);
    ...
    export async function image2PixelMap(icon: string): Promise<image.PixelMap> {
      let rawFileDescriptor: resourceManager.RawFileDescriptor = resourceMgs.getRawFdSync(icon);
      let imageSource: image.ImageSource = image.createImageSource(rawFileDescriptor);
      let pixelMap: image.PixelMap = await imageSource.createPixelMap({
        editable: false,
        desiredPixelFormat: image.PixelMapFormat.BGRA_8888,
        desiredSize: { width: 40, height: 40 }
      })
      return pixelMap;
    }
  1. 遍历PixelMap中的所有像素,放到一个数组中
    ...
    let allPixels: number[] = await traverseAllPixel(pixelMap);
    ...
    export async function traverseAllPixel(pixelMap: image.PixelMap): Promise<number[]> {
      const pixelArrayBuffer: ArrayBuffer = new ArrayBuffer(40 * 40 * 4);
      await pixelMap.readPixelsToBuffer(pixelArrayBuffer);
      const allPixels: number[] = [];
      const unit8Pixels: Uint8Array = new Uint8Array(pixelArrayBuffer);
      for (let i = 0; i < unit8Pixels.length; i += 4) {
        const rgb: ColorRgb = {
          red: unit8Pixels[i+2],
          green: unit8Pixels[i+1],
          blue: unit8Pixels[i],
          alpha:unit8Pixels[i+3]
      }
      if (rgb.red === 0 && rgb.green === 0 && rgb.blue === 0 && rgb.alpha === 0) {
        continue;
      }
      allPixels.push(ColorUtils.rgbToNumber(rgb));
      }
      return allPixels;
    }
  1. 遍历数组,找到出现次数最多的像素
    ...
    let maxPixel: number = findMaxPixel(allPixels);
    ...
    export function findMaxPixel(allPixels: number[]): number {
      let map: Map<number, number> = new Map();
      allPixels.forEach((pixel: number) => {
        if (map.has(pixel)) {
          map.set(pixel, map.get(pixel)! + 1);
        } else {
          map.set(pixel, 1);
        }
      })
      let maxPixel: number = 0;
      let maxTimes: number = 0;
      map.forEach((value: number, key: number) => {
        if (value >= maxTimes) {
          maxTimes = value;
          maxPixel = key;
        }
      })
      return maxPixel;
    }
  1. 将出现次数最多的像素值转换为RGB颜色格式
   ...
   let rgb: ColorRgb = ColorUtils.numberToRgb(maxPixel);
   ...
   public static numberToRgb(color: number): ColorRgb {
     return {
       red: (color & 0xFF0000) >> 16,
       green: (color & 0xFF00) >> 8,
       blue: (color & 0xFF),
       alpha:(color & 0xFF000000)>>24
     }
   }
  1. 将RGB颜色格式转换为HSV格式,转换公式如图所示。

    ...
    let hsv: ColorHsv = ColorUtils.rgb2hsv(rgb);
    ...
    public static rgb2hsv(color: ColorRgb): ColorHsv {
      const red: number = color.red / MAX_RGB_VALUE;
      const green: number = color.green / MAX_RGB_VALUE;
      const blue: number = color.blue / MAX_RGB_VALUE;

      const max: number = Math.max(red, green, blue);
      const min: number = Math.min(red, green, blue);
      const delta: number = max - min;

      let hue: number = 0;
      let saturation: number = 0;
      let value: number = 0;
      if (max === min) {
        hue = 0;
      } else if (max === red) {
        hue = (green >= blue ? ((green - blue) / delta) * 60 : ((green - blue) / delta) * 60 + 360);
      } else if (max === green) {
        hue = (((blue - red) / delta) + 2) * 60;
      } else if (max === blue) {
        hue = (((red - green) / delta) + 4) * 60;
      }
      saturation = (max === 0 ? 0 : delta / max);
      value = max;

      return {
        hue: hue,
        saturation: saturation,
        value: value,
        alpha:color.alpha
      }
    }
  1. 修改HSV格式中的S和V值,使背景色和图标颜色有明显区分
    ...
    modifySVValue(hsv);
    ...
    export function modifySVValue(color: ColorHsv): void {
      if (color.hue > 20 && color.hue <= 60) {
        color.saturation = 0.12;
        color.value = 0.93;
      } else if (color.hue > 60 && color.hue <= 190) {
        color.saturation = 0.08;
        color.value = 0.91;
      } else if (color.hue > 190 && color.hue <= 270) {
        color.saturation = 0.1;
        color.value = 0.93;
      } else {
        color.saturation = 0.08;
        color.value = 0.93;
      }
    }
  1. 将HSV格式转换为RGB格式,转换公式如图所示。

    ...
    rgb = ColorUtils.hsv2rgb(hsv);
    ...
    public static hsv2rgb(color: ColorHsv): ColorRgb {
      const h60: number = color.hue / 60;
      const h60f: number = Math.floor(h60);
      const hi: number = h60f % 6;
      const f: number = h60 - h60f;
      const p: number = color.value * (1 - color.saturation);
      const q: number = color.value * (1 - f * color.saturation);
      const t: number = color.value * (1 - (1 - f) * color.saturation);

      let red: number = 0.0;
      let green: number = 0.0;
      let blue: number = 0.0;
      if (hi === 0) {
        red = color.value;
        green = t;
        blue = p;
      } else if (hi === 1) {
        red = q;
        green = color.value;
        blue = p;
      } else if (hi === 2) {
        red = p;
        green = color.value;
        blue = t;
      } else if (hi === 3) {
        red = p;
        green = q;
        blue = color.value;
      } else if (hi === 4) {
        red = t;
        green = p;
        blue = color.value;
      } else if (hi === 5) {
        red = color.value;
        green = p;
        blue = q;
      }
      return {
        red: Math.floor(red * MAX_RGB_VALUE),
        green: Math.floor(green * MAX_RGB_VALUE),
        blue: Math.floor(blue * MAX_RGB_VALUE),
        alpha:color.alpha
      }
    }
  1. 将rgb转换为数字,放入AppInfo对象中
    ...
    item.backgroundColor = ColorUtils.rgbToNumber(rgb);
    ...
    public static rgbToNumber(color: ColorRgb): number {
      return ((0xFF << 24) | (color.red << 16) | (color.green << 8) | color.blue);
    }
  1. 通过组件的backgroundColor属性设置背景色
    Row() {
    ...
    }
    .backgroundColor(this.item.backgroundColor === '' ? Color.White : this.item.backgroundColor)

高性能知识点

  1. 解码图片时,分辨率设为40*40,既可以加快计算背景颜色的速度,又可以保证准确性
  2. 提取像素时,由于鸿蒙中的颜色是用{red,green,blue,alpha}来表示,直接放入数组或者Map中会影响计算出现次数最多的像素的速度,所以需要使用rgbToNumber方法转换为整数

工程结构&模块类型

   iconmaincolor                                   // har类型
   |---mainpage
   |   |---MainPage.ets                            // 视图层,主要页面
   |---utils
   |   |---ColorUtils.ets                          // 颜色处理工具类
   |   |---ImageUtils.ets                          // 图片处理工具类

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/527573.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

云岚到家项目

一.项目介绍 云岚到家项目是一个家政服务o2o平台&#xff0c;互联网家政是继打车、外卖后的又一个风口&#xff0c;创业者众多&#xff0c;比如&#xff1a;58到家&#xff0c;天鹅到家等&#xff0c;o2o&#xff08;Online To Offline&#xff09;是将线下商务的机会与互联网…

负荷预测 | Matlab基于TCN-BiGRU-Attention单输入单输出时间序列多步预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于TCN-BiGRU-Attention单输入单输出时间序列多步预测&#xff1b; 2.单变量时间序列数据集&#xff0c;采用前12个时刻预测未来96个时刻的数据&#xff1b; 3.excel数据方便替换&#xff0c;运行环境matlab…

高端大气自适应全屏酷炫渐变卡片html源码图片切换特效html5源码导航引导网站源码

源码特点&#xff1a; 1&#xff1a;手工书写DIVCSS、代码精简无冗余。 2&#xff1a;自适应结构&#xff0c;全球先进技术&#xff0c;高端视觉体验。 3&#xff1a;SEO框架布局&#xff0c;栏目及文章页均可独立设置标题/关键词/描述。 4&#xff1a;附带测试数据、安装教程、…

说说对WebSocket的理解?应用场景?

一、是什么 WebSocket&#xff0c;是一种网络传输协议&#xff0c;位于OSI模型的应用层。可在单个TCP连接上进行全双工通信&#xff0c;能更好的节省服务器资源和带宽并达到实时通迅 客户端和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c…

flutter组件_AlertDialog

官方说明&#xff1a;A Material Design alert dialog. 翻译&#xff1a;一个材料设计警告对话框。 作者释义&#xff1a;显示弹窗&#xff0c;类似于element ui中的Dialog组件。 AlertDialog的定义 const AlertDialog({super.key,this.icon,this.iconPadding,this.iconColor,t…

c++的学习之路:18、容器适配器与反向迭代器

摘要 本文有可能讲的不是特别清楚&#xff0c;我也是初学者有的理解可能有偏差欢迎指出&#xff0c;文章末附上导图。 目录 摘要 一、什么是适配器 二、STL标准库中stack和queue的底层结构 三、deque 1、deque的原理介绍 2、deque的缺陷 四、反向迭代器 五、思维导图…

政安晨:【Keras机器学习实践要点】(二十一)—— MobileViT:基于变换器的移动友好图像分类模型

目录 简介 导入 超参数 MobileViT 实用程序 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; …

kafka(四)——生产者流程分析(c++)

前言 kafka生产者负责将数据发布到kafka集群的主题&#xff1b;kafka生产者消息发送方式有两种&#xff1a; 同步发送异步回调发送 流程 流程说明&#xff1a; Kafka Producer整体可看作是一个异步处理操作&#xff1b;消息发送过程中涉及两个线程&#xff1a;main线程和se…

JetBrains IDE(IDEA/WebStorm)配置GitHub Copilot

关于 GitHub Copilot 和 JetBrains IDE GitHub Copilot 在编写代码时提供 AI 对程序员的自动完成样式的建议。 有关详细信息&#xff0c;请参阅“关于 GitHub Copilot Individual”。 如果使用 JetBrains IDE&#xff0c;可以直接在编辑器中查看并合并来自 GitHub Copilot 的…

DXP学习002-PCB编辑器的环境参数及电路板参数相关设置

目录 一&#xff0c;dxp的pcb编辑器环境 1&#xff0c;创建新的PCB设计文档 2&#xff0c;PCB编辑器界面 1&#xff09;布线工具栏 2&#xff09;公用工具栏 3&#xff09;层标签栏 ​编辑 3&#xff0c;PCB设计面板 1&#xff09;打开pcb设计面板 4&#xff0c;PCB观…

线程的666种状态

文章目录 在Java中&#xff0c;线程有以下六种状态&#xff1a; NEW&#xff1a;新建状态&#xff0c;表示线程对象已经被创建但还未启动。RUNNABLE&#xff1a;可运行状态&#xff0c;表示线程处于就绪状态&#xff0c;等待系统分配CPU资源执行。BLOCKED&#xff1a;阻塞状态…

抖音在线点赞任务发布接单运营平台PHP网站源码 多个支付通道+分级会员制度

源码介绍 1、三级代理裂变&#xff0c;静态返佣/动态返佣均可设置。&#xff08;烧伤制度&#xff09;。 2、邀请二维码接入防红跳转。 3、自动机器人做任务&#xff0c;任务时间可设置&#xff0c;机器人价格时间可设置。 4、后台可设置注册即送X天机器人。 5、不同级别会…

LLM大语言模型助力DataEase小助手,新增气泡地图,DataEase开源数据可视化分析平台v2.5.0发布

2024年4月8日&#xff0c;DataEase开源数据可视化分析平台正式发布v2.5.0版本。 这一版本的功能升级包括&#xff1a;新增DataEase小助手支持&#xff0c;通过结合智能算法和LLM&#xff08;即Large Language Model&#xff0c;大语言模型&#xff09;能力&#xff0c;DataEas…

Servlet(一)

文章目录 1.Servlet整体框架2.Servlet快速入门1.创建项目配置基本环境2.添加jar包1.在WEB-INF下创建目录lib&#xff0c;添加文件2.添加到项目中3.配置代码提示 3.src下创建文件4.实现Servlet接口5.在web.xml配置HelloServlet6.通过浏览器访问HelloServlet 3.浏览器访问Servlet…

axios是什么?axios使用axios和ajax

Axios 是一个基于 Promise 的 HTTP 客户端&#xff0c;用于浏览器和 Node.js 环境。它是由 GitHub 用户 mzabriskie 开发的&#xff0c;并且得到了广泛的社区支持。Axios 的设计目标是提供一种简洁、易用且功能强大的 HTTP 请求方式&#xff0c;以替代传统的 Ajax&#xff08;A…

ssm031社区管理与服务的设计与实现+jsp

社区管理与服务系统的设计与实现 摘 要 Abstract 第一章 绪论 1.1研究背景 1.2 研究现状 1.3 研究内容 第二章 系统关键技术 2.1 Java简介 2.2 MySql数据库 2.3 B/S结构 2.4 Tomcat服务器 第三章 系统分析 3.1可行性分析 3.1.1技术可行性 3.1.2经济可行性 3.1.…

usbserial驱动流程解析_Part3_write_read数据流分析

usb转串口设备需要进行收发&#xff0c;主机接到uart rx线上的数据&#xff0c;把主机数据发送到 uart tx线上&#xff0c;对应的就是read函数和write函数&#xff0c;以上两个Part提到了tty有关的函数&#xff0c;在以下结构体被定义&#xff0c;write被指定为serial_write&a…

在 VS Code 中使用 GitHub Copilot

Code 结合使用。 GitHub Copilot 是什么 GitHub Copilot 是一个可以帮助你更简单、更快速地编写代码的工具&#xff0c;由 GPT-3 提供支持。你只需编写所需代码的描述——例如&#xff0c;编写一个函数来生成一个随机数&#xff0c;或对一个数组进行排序——Copilot 就会为你…

ATM04-6P 安费诺汽车连接器6芯压线端子胶壳

ATM04-6P是一款压线端子胶壳&#xff0c;属于Amphenol&#xff08;安费诺&#xff09;品牌 ATM04-6P 规格信息&#xff1a; 制造商:Amphenol 产品种类:汽车连接器 RoHS:是 产品:Connectors 位置数量:6 Position 型式:Receptacle (Female) 线规量程:22 AWG to 16 AWG 系列:ATM 颜…

蓝桥杯真题Day48 倒计时7天 练了几道真题小程序+回溯剪枝应用一个小程序

[蓝桥杯 2023 省 A] 更小的数 题目描述 小蓝有一个长度均为 n 且仅由数字字符 0∼9 组成的字符串&#xff0c;下标从0到 n−1&#xff0c;你可以将其视作是一个具有n位的十进制数字num&#xff0c;小蓝可以从num 中选出一段连续的子串并将子串进行反转&#xff0c;最多反转一次…