获取图片主题色

news/2024/12/28 9:46:06/

获取图片主题色

  • 一、问题描述
  • 二、具体实现
    • 1. 图片读取
    • 2. 使用Canvas提取图片的像素数据
  • 3. 聚合处理
  • 三、全部代码

一、问题描述

当我们遇到根据背景图片来修改页面样式的时候,可能就需要去实现获取图片主题色的功能。比如深色背景配白色导航栏,浅色背景配黑色导航栏这种。

二、具体实现

1. 图片读取

根据url将图片读取到dom中,方便后续操作

  const imageUrl = 'home_bg.png' // 你的图片地址const sourceImage = document.createElement("img");sourceImage.addEventListener('load' , () => {console.log(111);// TODO});sourceImage.src = imageUrl

2. 使用Canvas提取图片的像素数据

我们可以利用Canvas来获取图片的全部像素数据
基于上面TODO部分:

    const canvas  = document.createElement('canvas');const context = canvas.getContext('2d');const width  = canvas.width  = sourceImage.naturalWidth;const height = canvas.height = sourceImage.naturalHeight;context.drawImage(sourceImage, 0, 0, width, height);const imageData = context.getImageData(0, 0, width, height)console.log(imageData)

在这里插入图片描述
得到的数据是很多像素点RGBA数据依次排列组成的数组:
R - 红色(0-255)
G - 绿色(0-255)
B - 蓝色(0-255)
A - alpha 通道(0-255; 0 是透明的,255 是完全可见的)
所以我们要对数据进行处理,得到每个像素点的数据

    const pixelCount = width * height;const pixels = imageData.data;const pixelArray = [];const quality = 10 // 间隔,如果图片很大时每个像素值都取可能会对性能有所影响,所以按自己需求设置间隔多少像素点取一个值for (let i = 0, offset, r, g, b, a; i < pixelCount; i = i + quality) {offset = i * 4;r = pixels[offset + 0];g = pixels[offset + 1];b = pixels[offset + 2];a = pixels[offset + 3];// 如果像素点透明则不取值if (typeof a === 'undefined' || a >= 125) {pixelArray.push([r, g, b]);}}console.log(pixelArray);

在这里插入图片描述

3. 聚合处理

这里的数据我们可以自己做聚合、分析等等处理方式进行操作,最后得到我们自己想要的值。有兴趣可以自行去了解,我这里就使用了一个现成的库 quantize.js。https://www.npmjs.com/package/quantize。插件源码我已经附在文档上了。
具体实现:
首先引入quantize.js(模块化的项目中可以使用import或者require,这里只是方便演示)

    <script src="quantize.js"></script>
    const quantize = MMCQ.quantizeconst colorCount = 5 // 需要聚合出前五的颜色const cMap = quantize(pixelArray, colorCount);console.log(cMap)console.log(cMap ? cMap.palette() : []);

在这里插入图片描述
最后可以选择对前五的颜色进行加权处理,也可以直接取排第一的颜色(根据业务要求自行判断)

三、全部代码

记得首先引入quantize.js

    <script src="quantize.js"></script>
const quantize = MMCQ.quantize
// canvas实例,方便获取图片像素数据
class CanvasImage {canvas  = document.createElement('canvas')context = this.canvas.getContext('2d')constructor(image) {this.width  = this.canvas.width  = image.naturalWidth;this.height = this.canvas.height = image.naturalHeight;this.context.drawImage(image, 0, 0, this.width, this.height);}getImageData() {return this.context.getImageData(0, 0, this.width, this.height);};
}class ColorStat {quality = 10/**** @param quality 间隔多少个像素点取一个数据*/constructor(quality = 10) {this.quality = quality}/*** @description 提取图片像素点函数* @param imgData 图片像素数据 多组 r、g、b、a 数据组成的一维数组* @param pixelCount 一共多少个像素点* @param quality 间隔多少个像素点取一个数据* @returns {number[][]}*/createPixelArray(imgData, pixelCount, quality) {const pixels = imgData;const pixelArray = [];// 间隔取对应的像素值for (let i = 0, offset, r, g, b, a; i < pixelCount; i = i + quality) {offset = i * 4;r = pixels[offset];g = pixels[offset + 1];b = pixels[offset + 2];a = pixels[offset + 3];// 如果像素点透明则不取值(透明点不影响主题色)if (typeof a === 'undefined' || a >= 125) {pixelArray.push([r, g, b]);}}return pixelArray;}/*** 获取聚合后的像素值* @param sourceImage 图片dom* @param colorCount 要取的聚合后前几个像素值* @returns {*|*[]}*/getPalette(sourceImage, colorCount) {// 创建canvas实例const image = new CanvasImage(sourceImage);const imageData = image.getImageData();const pixelCount = image.width * image.height;const pixelArray = this.createPixelArray(imageData.data, pixelCount, this.quality);// 使用 quantize.js 聚合统计数据const cmap = quantize(pixelArray, colorCount);return cmap ? cmap.palette() : [];}/*** 通过图片地址获取图片主题色* @param imageUrl 图片地址(模块化项目本地图片需要使用 require(url)* @param colorCount 要取的聚合后前几个像素值* @returns {Promise<number[][] | string>}*/getColorFromUrl(imageUrl, colorCount = 5) {return new Promise((resolve, reject) => {// 创建img dom实例const sourceImage = document.createElement("img");sourceImage.addEventListener('load' , () => {const palette = this.getPalette(sourceImage, colorCount);if (palette) {resolve(palette)} else {reject('图片异常!')}});sourceImage.src = imageUrl})}
}
const colorStat = new ColorStat()
colorStat.getColorFromUrl('./home_bg.png', 5).then(data => {console.log(data);
})

http://www.ppmy.cn/news/851701.html

相关文章

java读取摄像头视屏流,Java 摄像头视频获取

Rate this post 背景介绍 作为一门强大的语言&#xff0c;Java所展现给编程人员的不仅仅是来自于发上的便利&#xff0c;更是这题开发过程中的的可扩展性。通过添加jar包即可扩展和使用开源的架构和方法。这是Java给程序员带来的最直观的体验。但是请不要忘记Java也是多平台支持…

摄像头录像容量计算

存储空间&#xff08;码流*3600*24&#xff09; /&#xff08;8*1024*1024&#xff09; 计算结果单位是 G/天 例如&#xff1a;一个 720P 的摄像头&#xff0c;码流值设定为 2048Kb/S 时&#xff0c;存储一天的容量为&#xff08;2048*3600*24&#xff09; /&#xff08;8*10…

ubuntu 下使用usb摄像头

ubuntu 下使用usb摄像头_米格鲁的博客-CSDN博客_ubuntu usb摄像头

JS调用本地摄像头

JS调用本地USB摄像头&获取截图 <!doctype html> <html lang"en"> <head><title>GET VIDEO</title><meta charset"utf-8"> </head> <body> <input type"button" title"开启摄像头&q…

Python3使用opencv调用摄像头录制高清视频

安装依赖 Windows10Python3.7环境 pip3 install opencv-python示例代码 import cv2 from datetime import datetimeFILENAME myvideo.avi WIDTH 1280 HEIGHT 720 FPS 24.0# 必须指定CAP_DSHOW(Direct Show)参数初始化摄像头,否则无法使用更高分辨率 cap cv2.VideoCaptu…

IDEA+SpringBoot + Mybatis + Shiro+Bootstrap+Mysql智慧仓库系统

IDEASpringBoot Mybatis ShiroBootstrapMysql智慧仓库系统 一、系统介绍1.环境配置 二、系统展示1. 管理员登录2.主页3.货位一览4.入库单5. 库存明细6. 呆滞过期报表7. 转库记录8.入库记录9.出库记录10.出库单11.物料信息12.仓库设置13.用户管理14.操作员管理15.角色管理16.账…

SpringBoot 开启事务的常用方式

前言&#xff0c;有时候统一异常处理不太好&#xff0c;因为范围太广了&#xff0c;很多没必要回滚的地方&#xff0c;因为抛了个异常都没办法继续执行别的代码&#xff0c;所以&#xff0c;可以在需要开事务的地方添加 Transation 注解开启事务就行了。 springboot 项目中&…

iPhone 13发布会,苹果不想让你知道的三个细节

文|智能相对论&#xff08;ID&#xff1a;aixdlun&#xff09; 作者|宋文远 9月15日凌晨&#xff0c;随着库克标志性“Good morning&#xff01;”开场白&#xff0c;苹果今年最重要的秋季发布会如期而至。 简单总结一下&#xff0c;此次发布会苹果共发布了四款新产品&#x…