通过 Javascript 获取图像的平均颜色
不确定这是否可行,但希望编写一个脚本来返回图像的平均 hex
或 rgb
值。我知道可以在 AS 中完成,但希望在 JavaScript 中完成。
Not sure this is possible, but looking to write a script that would return the average hex
or rgb
value for an image. I know it can be done in AS but looking to do it in JavaScript.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
AFAIK,执行此操作的唯一方法是使用
...
DEMO V2:http://jsfiddle.net/xLF38/818/
注意,这仅适用于同一域中的图像以及支持 HTML5 画布的浏览器:
请 IE,查看 excanvas。
AFAIK, the only way to do this is with
<canvas/>
...DEMO V2: http://jsfiddle.net/xLF38/818/
Note, this will only work with images on the same domain and in browsers that support HTML5 canvas:
For IE, check out excanvas.
我想我会发布一个我最近遇到的项目来获得主色:
Color Thief
其他提到和建议主色的解决方案从未在正确的上下文中(“在 javascript 中”)真正回答问题。希望这个项目能够帮助那些想要这样做的人。
Figured I'd post a project I recently came across to get dominant color:
Color Thief
The other solutions mentioning and suggesting dominant color never really answer the question in proper context ("in javascript"). Hopefully this project will help those who want to do just that.
“主色”很棘手。您要做的就是比较颜色空间中每个像素与其他每个像素之间的距离(欧几里德距离),然后找到颜色与其他所有颜色最接近的像素。该像素是主色。平均颜色通常是泥色。
我希望这里有 MathML 来向您展示欧几里得距离。谷歌一下。
我已经使用 PHP/GD 在 RGB 颜色空间中完成了上述执行: https://gist.github.com/cf23f8bddb307ad4abd8
然而,这在计算上非常昂贵。它会使您的系统在处理大图像时崩溃,并且如果您在客户端中尝试它,肯定会使您的浏览器崩溃。我一直致力于将我的执行重构为:
- 将结果存储在查找表中以供将来在每个像素的迭代中使用。
- 将大图像划分为 20px 20px 的网格,以实现局部主导。
- 使用 x1y1 和 x1y2 之间的欧氏距离来计算 x1y1 和 x1y3 之间的距离。
如果您在这方面取得进展,请告诉我。我会很高兴看到它。我也会这样做。
Canvas 绝对是在客户端实现此目的的最佳方式。 SVG 不是,SVG 是基于矢量的。执行完毕后,我想做的下一件事是在画布中运行它(可能使用网络工作者来计算每个像素的总距离)。
另一件需要考虑的事情是,RGB 并不是一个很好的颜色空间,因为 RGB 空间中颜色之间的欧氏距离与视觉距离不是很接近。一个更好的颜色空间可能是 LUV,但我还没有找到一个好的库,或者任何将 RGB 转换为 LUV 的算法。
一种完全不同的方法是对彩虹中的颜色进行排序,并构建一个具有公差的直方图,以考虑颜色的不同深浅。我没有尝试过这个,因为对彩虹中的颜色进行排序很困难,颜色直方图也很困难。接下来我可能会尝试这个。再次,如果您在这里取得任何进展,请告诉我。
"Dominant Color" is tricky. What you want to do is compare the distance between each pixel and every other pixel in color space (Euclidean Distance), and then find the pixel whose color is closest to every other color. That pixel is the dominant color. The average color will usually be mud.
I wish I had MathML in here to show you Euclidean Distance. Google it.
I have accomplished the above execution in RGB color space using PHP/GD here: https://gist.github.com/cf23f8bddb307ad4abd8
This however is very computationally expensive. It will crash your system on large images, and will definitely crash your browser if you try it in the client. I have been working on refactoring my execution to:
- store results in a lookup table for future use in the iteration over each pixel.
- to divide large images into grids of 20px 20px for localized dominance.
- to use the euclidean distance between x1y1 and x1y2 to figure out the distance between x1y1 and x1y3.
Please let me know if you make progress on this front. I would be happy to see it. I will do the same.
Canvas is definitely the best way to do this in the client. SVG is not, SVG is vector based. After I get the execution down, the next thing I want to do is get this running in the canvas (maybe with a webworker for each pixel's overall distance calculation).
Another thing to think about is that RGB is not a good color space for doing this in, because the euclidean distance between colors in RGB space is not very close to the visual distance. A better color space for doing this might be LUV, but I have not found a good library for this, or any algorythims for converting RGB to LUV.
An entirely different approach would be to sort your colors in a rainbow, and build a histogram with tolerance to account for varying shades of a color. I have not tried this, because sorting colors in a rainbow is hard, and so are color histograms. I might try this next. Again, let me know if you make any progress here.
通过
datauri
支持获取图像平均颜色的方法不太准确,但最快。Less accurate but fastest way to get average color of the image with
datauri
support.第一:无需 HTML5 Canvas 或 SVG 即可完成。
实际上,有人刚刚设法生成客户端-使用 JavaScript 的侧 PNG 文件,没有画布或 SVG,使用 数据 URI 方案。
编辑:您可以简单地创建一个 PNG
document.getElementById("canvas").toDataURL("image/png", 1.0)
第二:您可能实际上不需要 Canvas 、SVG 或以上任何一个。
如果您只需要在客户端处理图像,而不修改它们,那么这一切都是不需要的。
您可以从页面的img标签中获取源地址,并对其发出XHR请求- 它很可能来自浏览器缓存 - 并将其作为来自 Javascript 的字节流进行处理。
您需要充分了解图像格式。 (上面的生成器部分基于 libpng 源,可能提供一个很好的起点。)
First: it can be done without HTML5 Canvas or SVG.
Actually, someone just managed to generate client-side PNG files using JavaScript, without canvas or SVG, using the data URI scheme.
Edit: You can simply create a PNG with
document.getElementById("canvas").toDataURL("image/png", 1.0)
Second: you might actually not need Canvas, SVG or any of the above at all.
If you only need to process images on the client side, without modifying them, all this is not needed.
You can get the source address from the img tag on the page, make an XHR request for it - it will most probably come from the browser cache - and process it as a byte stream from Javascript.
You will need a good understanding of the image format. (The above generator is partially based on libpng sources and might provide a good starting point.)
令人惊讶的是,这只需 4 行代码即可完成:
示例:
工作原理:
创建画布上下文
这会将图像仅绘制到一个画布像素上,使浏览器为您找到主色。
之后,只需获取像素的图像数据即可:
最后,转换为
rgba
或HEX
:不过,这种方法有一个问题,那就是
getImageData有时会抛出错误
无法从canvas获取图像数据,因为canvas已被跨源数据污染。
,这就是demo中需要上传图像而不是上传图像的原因例如输入 URL。该方法还可以用于通过增加宽度和高度来绘制图像来对图像进行像素化。
这适用于 Chrome,但可能不适用于其他浏览器。
Surprisingly, this can be done in just 4 lines of code:
Example:
How it works:
Create the canvas context
This will draw the image to only one canvas pixel, making the browser find the dominant color for you.
After that, just get the image data for the pixel:
Finally, convert to
rgba
orHEX
:There is one problem with this method though, and that is that
getImageData
will sometimes throw errorsUnable to get image data from canvas because the canvas has been tainted by cross-origin data.
, which is the reason you need to upload images in the demo instead of inputting a URL for example.This method can also be used for pixelating images by increasing the width and height to draw the image.
This works on chrome but may not on other browsers.
我想说的是通过 HTML canvas 标签。
此处找到 @Georg 发表的一篇文章,讨论 Opera 开发人员的一小段代码:
您可以在 使用每个像素的 R、G 和 B 值反转图像。您可以轻松存储 RGB 值,然后将红色、绿色和蓝色数组四舍五入,最后将它们转换回十六进制代码。
I would say via the HTML canvas tag.
You can find here a post by @Georg talking about a small code by the Opera dev :
This invert the image by using the R, G and B value of each pixel. You could easily store the RGB values, then round up the Red, Green and Blue arrays, and finally converting them back into an HEX code.
这是@350D的答案,但异步(因为某些图像可能需要时间加载)并且在打字稿中
This is @350D's answer but async (as some images may take time to load) and in typescript
我最近遇到了一个 jQuery 插件,它可以实现我最初想要的 https://github.com/ briangonzalez/jquery.adaptive-backgrounds.js 关于从图像中获取主导颜色。
I recently came across a jQuery plugin which does what I originally wanted https://github.com/briangonzalez/jquery.adaptive-backgrounds.js in regards to getting a dominiate color from an image.
一体化解决方案
我个人会结合Color Thief以及修改后的版本命名该颜色 获得足够多的图像主色结果。
示例:
考虑以下图像:
您可以使用以下代码提取与主色相关的图像数据:
All-In-One Solution
I would personally combine Color Thief along with this modified version of Name that Color to obtain a more-than-sufficient array of dominant color results for images.
Example:
Consider the following image:
You can use the following code to extract image data relating to the dominant color:
JavaScript 无法访问图像的各个像素颜色数据。至少,可能要到 html5 为止……届时您将能够将图像绘制到画布上,然后检查画布(也许,我自己从未这样做过)。
Javascript does not have access to an image's individual pixel color data. At least, not maybe until html5 ... at which point it stands to reason that you'll be able to draw an image to a canvas, and then inspect the canvas (maybe, I've never done it myself).
这是关于“颜色量化”,它有多种方法,例如 MMCQ (修改中值剪切量化)或 OQ(八叉树量化)。不同的方法使用 K-Means 来获取颜色簇。
我已经将所有内容放在一起,因为我正在寻找
tvOS
的解决方案,其中有一个 XHTML 子集,没有元素:
使用 XMLHttpRequest 生成 RGB 图像的主色
This is about "Color Quantization" that has several approachs like MMCQ (Modified Median Cut Quantization) or OQ (Octree Quantization). Different approach use K-Means to obtain clusters of colors.
I have putted all together here, since I was finding a solution for
tvOS
where there is a subset of XHTML, that has no<canvas/>
element:Generate the Dominant Colors for an RGB image with XMLHttpRequest
要获得图像的平均(不是主)颜色,请创建一个按比例缩小的原始图像的小画布(最大尺寸,即:10 像素)。然后循环画布区域imageData来构造平均RGB:
To get the average (not the dominant) color of an image, create a tiny canvas of the scaled-down original image (of max size i.e: 10 px). Then loop the canvas area imageData to construct the average RGB:
正如其他答案中指出的那样,通常您真正想要的主色而不是通常为棕色的平均颜色。我编写了一个获取最常见颜色的脚本,并将其发布在此 gist
As pointed out in other answers, often what you really want the dominant color as opposed to the average color which tends to be brown. I wrote a script that gets the most common color and posted it on this gist
Colortheif 是一个非常好的软件包。我曾经使用过它并且效果很好。与画布结合,我可以创建一个提取颜色的调色板图像。但是转向打字稿,colortheif 没有打字,所以这对我来说是一个问题。
Colortheif is a very good package. I used to use it and it works fine. Combined with canvas I can create a palette image with the colors extracted. But moving to typescript, colortheif is not typed so that's a problem for me.
有一个在线工具 pickimagecolor.com 可以帮助您找到平均值或主导值图像的颜色。您只需从计算机上传图像,然后单击该图像。它给出了 HEX、RGB 和 HSV 的平均颜色。它还会找到与该颜色相匹配的色调以供选择。我已经用过很多次了。
There is a online tool pickimagecolor.com that helps you to find the average or the dominant color of image.You just have to upload a image from your computer and then click on the image. It gives the average color in HEX , RGB and HSV. It also find the color shades matching that color to choose from. I have used it multiple times.