工作时遇到一个需求:提取图片的主题色,通过一定的映射关系选择ui给定的对应颜色。如果只是单纯的前端,怎么可能在我心目中实现呢?一、思路和准备工作使用canvas获取图像像素信息,然后通过一定的算法提取主题色。1.1理解CanvasCanvasRealPixel原理MDN:其实可以直接通过getImageData返回一个imageData对象来获取场景像素数据。imageData对象包含以下只读属性:width:图像宽度,以像素为单位height:图像高度,以像素为单位data:Uint8ClampedArray类型的一维数组,包含RGBA格式的整数数据,范围为0到255间(包括255个)。data属性返回一个Uint8ClampedArray,可用作查看的初始像素数据。每个像素由4个1字节的值表示(按照红、绿、蓝和透明值的顺序,“RGBA”格式)。每个颜色值部分由0到255表示。每个部分在数组中分配一个连续的索引,左上角像素的红色部分位于数组的索引0处。像素从左到右处理,然后向下处理,遍历整个数组。Uint8ClampedArray包含高×宽×4字节数据,索引值从0到(高×宽×4)-11.2理解中值切割法(Mediancut)中值切割法在图像处理中通常会降低图像的位深度该算法可用于将高位图像转换为低位图像,例如将24位图像转换为8位图像。我们也可以用它来提取图片的主题色。其原理是将图像的每个像素点的颜色看成是三维空间中以R、G、B为坐标轴的一个点。由于三种颜色的取值范围是0~255,所以图像中的颜色都分布在这个颜色立方体中。如图:之后,将RGB的最长边从颜色统计的中位数一分为二,使得得到的两个长方体包含的像素个数相同,重复这个过程,直到剪出的长方体个数为如下图等于主题色的个数,最后取每个长方体的中点。在实际使用中,如果只按中点切,会出现某些长方体体积大但像素数少的情况。解决方法是在切割前先对长方体进行优先排序,排序系数为体积*像素数。这样就可以基本解决这类问题。其中,color-thief库是基于中值分割方法实现的。参考:PixelsandPalettes:ExtractingColorPalettesFromImagesPixel_manipulation_with_canvas_ByMDN
