返回
高级 UI 之 Paint(滤镜、颜色通道、矩阵运算)
Android
2023-10-11 01:48:48
前言
在 Android 开发中,Canvas 和 Paint 是至关重要的图形组件。Canvas 作为画布,而 Paint 作为画笔,赋予图形色彩和样式。在上一篇文章中,我们深入探讨了 Canvas 的基本操作。本文将重点关注 Paint 的高级特性,包括滤镜、颜色通道和矩阵运算,从而帮助 Android 开发人员创建更复杂、更令人印象深刻的 UI 效果。
一、滤镜
滤镜是一种图像处理技术,可以增强、调整或转换图像的外观。Paint 提供了一系列预定义的滤镜,如:
- ColorMatrixColorFilter: 允许对颜色通道进行线性操作。
- LightingColorFilter: 应用光源,创建阴影和高光效果。
- PorterDuffColorFilter: 结合两种图像,根据指定的模式进行混合。
这些滤镜可以通过 ColorFilter 接口应用于 Paint 对象。例如,要应用色相旋转滤镜,可以按如下方式进行:
Paint paint = new Paint();
paint.setColorFilter(new LightingColorFilter(0xFFFFFFFF, 0xFF0000));
二、颜色通道
颜色通道是图像中颜色的基本组件。Paint 提供了方法来操作这些通道:
- Color.alpha(): 获取或设置颜色的透明度。
- Color.red()、Color.green()、Color.blue(): 获取或设置颜色的 RGB 值。
通过调整颜色通道,我们可以创建颜色混合、饱和度调整和反色效果。例如,要将颜色转换为其反色,可以按如下方式进行:
int color = Color.parseColor("#FF0000");
int invertedColor = 0xFFFFFFFF - color;
三、矩阵运算
矩阵运算是一种强大的数学工具,可用于变换图像。Paint 支持通过 ColorMatrix 类进行矩阵运算。ColorMatrix 可以定义为一个 4x5 的矩阵,用于对颜色通道进行线性变换。
例如,要创建亮度调整矩阵,可以按如下方式进行:
float[] matrix = {
1, 0, 0, 0, 100,
0, 1, 0, 0, 100,
0, 0, 1, 0, 100,
0, 0, 0, 1, 0
};
paint.setColorFilter(new ColorMatrixColorFilter(matrix));
示例
为了展示高级 Paint 特性的实际应用,让我们创建一个小程序,其中用户可以实时调整图像滤镜、颜色通道和矩阵运算。
代码:
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.LightingColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.SeekBar;
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
private SeekBar seekBarHue, seekBarSaturation, seekBarBrightness, seekBarContrast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.imageView);
seekBarHue = findViewById(R.id.seekBarHue);
seekBarSaturation = findViewById(R.id.seekBarSaturation);
seekBarBrightness = findViewById(R.id.seekBarBrightness);
seekBarContrast = findViewById(R.id.seekBarContrast);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
// 创建一个 Paint 对象
Paint paint = new Paint();
// 设置监听器以响应 SeekBar 更改
seekBarHue.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
float hue = progress / 360f;
paint.setColorFilter(new LightingColorFilter(0xFFFFFFFF, hue));
updateImage(bitmap, paint);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarSaturation.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
float saturation = progress / 100f;
float[] matrix = {
1, 0, 0, 0, saturation,
0, 1, 0, 0, saturation,
0, 0, 1, 0, saturation,
0, 0, 0, 1, 0
};
paint.setColorFilter(new ColorMatrixColorFilter(matrix));
updateImage(bitmap, paint);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarBrightness.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
float brightness = progress / 100f;
int invertedColor = 0xFFFFFFFF - Color.parseColor("#FF0000");
paint.setColorFilter(new PorterDuffColorFilter(invertedColor, PorterDuff.Mode.ADD));
updateImage(bitmap, paint);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarContrast.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
float contrast = progress / 100f;
float[] matrix = {
contrast, 0, 0, 0, 0,
0, contrast, 0, 0, 0,
0, 0, contrast, 0, 0,
0, 0, 0, 1, 0
};
paint.setColorFilter(new ColorMatrixColorFilter(matrix));
updateImage(bitmap, paint);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
updateImage(bitmap, paint);
}
private void updateImage(Bitmap bitmap, Paint paint) {
// 创建一个新的 Bitmap 以应用效果
Bitmap updatedBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
// 创建一个 Canvas 并绘制图像
Canvas canvas = new Canvas(updatedBitmap);
canvas.drawBitmap(bitmap, 0, 0, paint);
// 设置图像视图的图像
imageView.setImageBitmap(updatedBitmap);
}
}
结论
通过掌握 Paint 的高级特性,包括滤镜、颜色通道和矩阵运算,Android 开发人员可以创建更加复杂、更具互动性的 UI 效果。本文提供了一个实用的示例,展示了如何实时调整这些特性,从而提供引人入胜的用户体验。