Android 平台的图像处理

数字图像是由有限个像素点构成的,而通常每一个像素的颜色值采用 RGBA 色彩空间来记录。其中 RGB 对应了如下图红,绿,蓝三原色。A 指 alpha 通道,A 的出现使 alpha 渲染和 alpha 合成成为可能。alpha 的名字来自线性插值方程 αA + (1-α)B 中的希腊字母。

RGBA 模型

数字图像是由有限个像素点构成的,而通常每一个像素的颜色值采用 RGBA 色彩空间来记录。其中 RGB 对应了如下图红,绿,蓝三原色。A 指 alpha 通道,A 的出现使 alpha 渲染和 alpha 合成成为可能。alpha 的名字来自线性插值方程 αA + (1-α)B 中的希腊字母。

三原色三原色

在 Android 系统中通常使用 8 位十六进制数表示一个色值如 #ff 88 00 ff, 0xff 88 00 ff。

数字图像处理本质上就是对构成图像的每个像素点做适当的修改以达到预期效果。

构成色彩的三个重要参数:

  • 色相:物体传递出来的颜色
  • 饱和度:从 0 (黑白色) 到 100% (饱和) 来描述
  • 亮度:颜色的相对明暗程度

一般情况下应用软件如 PhotoShop 直接提供了对色相,饱和度,亮度等参数的修改。

修改 RGBA 值实现滤镜

胶片效果:

public static Bitmap handleImageNegative(Bitmap bm) {
int width = bm.getWidth();
int height = bm.getHeight();
int color;
int r, g, b, a;

Bitmap bmp = Bitmap.createBitmap(width, height
, Bitmap.Config.ARGB_8888);

int[] oldPx = new int[width * height];
int[] newPx = new int[width * height];
bm.getPixels(oldPx, 0, width, 0, 0, width, height);

for (int i = 0; i < width * height; i++) {
color = oldPx[i];
r = Color.red(color);
g = Color.green(color);
b = Color.blue(color);
a = Color.alpha(color);

r = 255 - r;
g = 255 - g;
b = 255 - b;

r = r > 255 ? 255 : r;
r = r < 0 ? 0 : r;
g = g > 255 ? 255 : g;
g = g < 0 ? 0 : g;
b = b > 255 ? 255 : b;
b = b < 0 ? 0 : b;
newPx[i] = Color.argb(a, r, g, b);
}
bmp.setPixels(newPx, 0, width, 0, 0, width, height);
return bmp;
}

复古效果:

r1 = (int) (0.393 * r + 0.769 * g + 0.189 * b);
g1 = (int) (0.349 * r + 0.686 * g + 0.168 * b);
b1 = (int) (0.272 * r + 0.534 * g + 0.131 * b);

浮雕效果:

colorBefore = oldPx[i - 1];
a = Color.alpha(colorBefore);
r = Color.red(colorBefore);
g = Color.green(colorBefore);
b = Color.blue(colorBefore);

color = oldPx[i];
r1 = Color.red(color);
g1 = Color.green(color);
b1 = Color.blue(color);

r = (r - r1 + 127);
g = (g - g1 + 127);
b = (b - b1 + 127);

使用矩阵对 RGBA 操作

对一个像素 RGBA 个通道值的修改通常使用矩阵,Android 也是如此,这个影响像素 RGBA 的值矩阵称为 ColorMatrix 颜色矩阵。

颜色矩阵是一个用来表示三原色和透明度的 4x5 的矩阵,表示为一个数组的形式。

[ a, b, c, d, e,
f, g, h, i, j,
k, l, m, n, o,
p, q, r, s, t ]

一个颜色则使用 [R, G, B, A] 的方式进行表示,根据矩阵乘法 mxn 与 nxk 的外积为 mxk 的矩阵,使眼色矩阵与 [R, G, B, A, 1] 相乘,所以矩阵与颜色的计算方式则为:

R’ = a*R + b*G + c*B + d*A + e;
G’ = f*R + g*G + h*B + i*A + j;
B’ = k*R + l*G + m*B + n*A + o;
A’ = p*R + q*G + r*B + s*A + t;

[R’, G’, B’, A’] 即为新像素的 RGBA 各通道的值。

使用矩阵产生特效:

[ 0.33, 0.59, 0.11, 0, 0
0.33, 0.59, 0.11, 0, 0
0.33, 0.59, 0.11, 0, 0
0, 0, 0, 1, 0]

[ 0.393, 0.769, 0.189, 0, 0
0.349, 0.686, 0.168, 0, 0
0.272, 0.534, 0.131, 0, 0
0, 0, 0, 1, 0]