了解使用 ColorMatrix 和 ColorMatrixColorFilter 修改 Drawable 的色调
我正在为一个应用程序开发用户界面,我正在尝试使用灰度图标,并允许用户将主题更改为他们选择的颜色。为此,我尝试仅应用某种 ColorFilter 将颜色覆盖在可绘制对象的顶部。我尝试过使用 PorterDuff.Mode.MULTIPLY,它的工作原理几乎完全符合我的需要,只是白色也被颜色覆盖。我理想中寻找的是类似 Photoshop 中的“颜色”混合模式,其中图形保留其透明度和亮度,并且仅修改图像的颜色。例如:
变为
经过一些研究,似乎 ColorMatrixColorFilter 类可以满足我的需要,但我似乎找不到任何指向如何使用矩阵的资源。这是一个 4x5 矩阵,但我需要知道的是如何设计该矩阵。有什么想法吗?
编辑:好吧,到目前为止我发现的内容如下:
1 0 0 0 0 //red
0 1 0 0 0 //green
0 0 1 0 0 //blue
0 0 0 1 0 //alpha
这个矩阵是单位矩阵(应用时,不进行任何更改),数字范围从 0 到 1(浮点数)。该矩阵将与每个像素相乘以转换为新颜色。所以这就是我开始变得模糊的地方。所以我认为每个像素都是一个 1 x 4 向量,其中包含 argb 值(例如 0.2, 0.5, 0.8, 1
),该值将用变换矩阵点缀。因此,要将图像的红色强度加倍,您可以使用如下矩阵:
2 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
这将为您提供 0.4, 0.5, 0.8, 1
的向量(颜色)。从有限的测试来看,情况似乎如此,并且工作正常,但实际上我仍然遇到同样的问题(即白色获得着色)。进一步阅读告诉我,这是因为它对 RGB 值进行转换,而对于色调偏移,应首先将值转换为 HSL 值。因此,我可能可以编写一个类来读取图像并转换颜色,并使用新颜色重新绘制图像。这给 StateListDrawables 带来了另一个问题,因为我不确定如何在代码中获取这些内容并修改所有内容,以及这个过程有多慢。 :/
嗯,好吧,所以我想我会遇到的另一个问题是矩阵是否可以用于将 RGB 转换为另一个具有亮度信息的颜色空间,例如 Lab 或 HSL?如果是这样,我只需乘以该转换的矩阵,然后对该矩阵进行色调调整,然后将该矩阵应用为 ColorFilter。
I'm working on a UI for an app, and I'm attempting to use grayscale icons, and allow the user to change the theme to a color of their choosing. To do this, I'm trying to just apply a ColorFilter of some sort to overlay a color on top of the drawable. I've tried using PorterDuff.Mode.MULTIPLY, and it works almost exactly as I need, except that whites get overlayed with the color as well. What I'm ideally looking for is something like the "Color" blending mode in Photoshop, where the graphic retains its transparency and luminosity, and only modifies the color of the image. For example:
becomes
After doing some research, it appears that the ColorMatrixColorFilter class may do what I need, but I can't seem to find any resources pointing to how the matrix is used. It's a 4x5 matrix, but what I need to know is how I go about designing the matrix. Any ideas?
EDIT: So okay, what I've found so far on this is as follows:
1 0 0 0 0 //red
0 1 0 0 0 //green
0 0 1 0 0 //blue
0 0 0 1 0 //alpha
Where this matrix is the identity matrix (when applied, makes no changes), and the numbers range from 0 to 1 (floats). This matrix will be multiplied with each pixel to convert to the new color. So this is where it starts to get fuzzy for me. So I would think each pixel would be a 1 x 4 vector containing the argb values (e.g. 0.2, 0.5, 0.8, 1
) that would be dotted with the transformation matrix. So to double the red intensity of an image, you would use a matrix such as:
2 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
which would give you a vector (color) of 0.4, 0.5, 0.8, 1
. From limited testing, this seems to be the case, and works properly, but I actually still end up with the same problem (i.e. whites gain coloring). Further reading tells me that this is because it's doing the conversion on RGB values, whereas for hue shifting, the values should first be converted to HSL values. So possibly I could write a class that would read the image and convert the colors, and redraw the image with the new colors. This creates ANOTHER problem with StateListDrawables, as I'm not sure how I would go about getting each of these in code and modifying all of them, and how slow a process it would be. :/
Hmm, okay, so I suppose another question I would have is whether a matrix can be used to convert RGB to another color space with luminosity information, such as Lab or HSL? If so, I could just multiply the matrix for that converstion, then make the hue adjustment to THAT matrix, then apply that matrix as the ColorFilter.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
这就是我在游戏中使用的。这是在网站上的各种文章中找到的各个部分的汇编。致谢来自@see 链接的原作者。
请注意,颜色矩阵可以做更多的事情。包括反转等......
为了完成这个我应该添加一个例子:
This is what I use for my game. This is the compilation of various part found on various articles on websites. Credits goes to the original author from the @see links.
Note that a lot more can be done with color matrices. Including inverting, etc...
To complete this I should add an example:
如果你想调整亮度、对比度、饱和度和色调,这里是完整的代码。享受!
非常感谢@RichardLalancette
here is the complete code if you want to adjust the bright, contrast, saturation and hue. Enjoy!
Thanks a lot to @RichardLalancette
对于任何对如何使用 ColorMatrixColorFilter 感兴趣的人。我在这里使用的示例在画布上绘制位图时将每个像素都转换为红色。
类中的注释来自: http://developer.android.com/reference /android/graphics/ColorMatrix.html 这让您了解其工作原理
For anyone who is interested in how to use the ColorMatrixColorFilter. The sample I used here, converted every pixel into red when I draw the bitmap on the canvas.
The comment in the class is from: http://developer.android.com/reference/android/graphics/ColorMatrix.html this gives you some insights on how this is working
下面的课程是对已经发布的答案的改进。这使得从
位图
读取和创建ColorFilter
变得更加容易。用法示例:
The below class is an improvement on the answers that have already been posted. This makes it easier to read and create a
ColorFilter
from aBitmap
.Example usage:
色调和 RGB 之间不存在线性关系。色调以 60° 块分段定义 (http://en.wikipedia.org/wiki/HSL_color_space#General_approach ),因此HSV和RGB之间不存在简单的矩阵转换。
要更改图像的色调,可以使用以下方法:
There is no linear relationship between Hue and RGB. Hue is defined piecewise in 60° chunks (http://en.wikipedia.org/wiki/HSL_color_space#General_approach), and therefore there is not a simple matrix conversion between HSV and RGB.
To change the hue of an image, you can use the following method :
我认为这个方法会给你你想要的:
http ://android.okhelp.cz/hue-color-colored-filter-bitmap-image-android-example/
I think this method will give you what you want:
http://android.okhelp.cz/hue-color-colored-filter-bitmap-image-android-example/
与其他答案一样,我使用颜色矩阵来实现此行为,但您可以传入常规 Android 颜色资源。该矩阵将颜色映射到图像值和白色之间的范围。
Like the rest of the answers I used a color matrix to implement this behavior, but you can pass in a regular Android color resource. The matrix, maps the color into a range between the image value and white.
我根据以下代码片段制作了一个小小的 ColorMatrixFilter 测试器:
您可以在此处查看:
https://play.google.com/store/apps/details ?id=org.vaelostudio.colormatrixtester
I made a little ColorMatrixFilter tester, based on the following snippet:
You can check it out here:
https://play.google.com/store/apps/details?id=org.vaelostudio.colormatrixtester
尽管使用
ColorMatrix
可以实现很多有用的效果,但我个人会考虑将ColorMap[]
与ImageAttributes
一起使用。通过这样做,我们可以定义哪些颜色应该替换为哪些颜色。Even though a lot of useful effects can be achieved by using the
ColorMatrix
I personally would consider using aColorMap[]
along withImageAttributes
. By doing this we can define which colors should be replaced with which colors.我解决这个问题的方法是从灰度图像开始。
原创 ---> grayImage
你可以在 Photoshop 中轻松完成,或者如果你需要用代码完成,你可以使用以下方法。
获得灰度图像后,您可以使用 PorterDuff OVERLAY 模式添加所需的颜色。
上面结果如下
randomColorGif
The way I solved it is to start with a gray scale image.
original ---> grayImage
you can do it easily in photoshop, or if you need to do it in code you can use the following method.
After you have your GrayScale image you can use the PorterDuff OVERLAY mode to add the desired Color.
The above result is as follows
randomColorGif
为了支持完整的 360 度色调,我将接受的答案中的以下行更改为:
从:
到:
For supporting a full 360 degrees hue, I changed the following line in the accepted answer:
from:
to: