我想将多个滤色器链式应用于可绘制对象。那可能吗?或者也许创建一个过滤器,它是我想要应用的过滤器的组合。
例如,我想:
Drawable d = ...;
d.setColorFilter(0x3F000000, Mode.OVERLAY).setColorFilter(0xFF2D2D2D, Mode.SCREEN)
我想将多个滤色器链式应用于可绘制对象。那可能吗?或者也许创建一个过滤器,它是我想要应用的过滤器的组合。
例如,我想:
Drawable d = ...;
d.setColorFilter(0x3F000000, Mode.OVERLAY).setColorFilter(0xFF2D2D2D, Mode.SCREEN)
这是我最终使用的方法:Drawable
在 a 上操作位图Canvas
并根据需要应用尽可能多的图层,使用Paint
,它不仅适用于颜色过滤器,而且适用于任何类型的图像混合。
...
Drawable myBackground = createBackground(getResources().getColor(R.color.Green));
setBackgroundDrawable(myBackground);
...
private Drawable createBackground(int color) {
Canvas canvas = new Canvas();
Bitmap buttonImage = BitmapFactory.decodeResource(getResources(), R.drawable.btn_image);
Bitmap buttonShadows = BitmapFactory.decodeResource(getResources(), R.drawable.btn_shadows);
Bitmap buttonHighLights = BitmapFactory.decodeResource(getResources(), R.drawable.btn_highlights);
Bitmap result = Bitmap.createBitmap(buttonImage.getWidth(), buttonImage.getHeight(), Bitmap.Config.ARGB_8888);
canvas.setBitmap(result);
Paint paint = new Paint();
paint.setFilterBitmap(false);
// Color
paint.setColorFilter(new PorterDuffColorFilter(color, Mode.MULTIPLY));
canvas.drawBitmap(buttonImage, 0, 0, paint);
paint.setColorFilter(null);
// Shadows
paint.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY));
canvas.drawBitmap(buttonShadows, 0, 0, paint);
// HighLights
paint.setXfermode(new PorterDuffXfermode(Mode.SCREEN));
canvas.drawBitmap(buttonHighLights, 0, 0, paint);
paint.setXfermode(null);
return new BitmapDrawable(getResources(), result);
}
警告: setBackgroundDrawable(Drawable d)
已弃用,而setBackground(Drawable d)
仅从 api 16 开始可用,所以如果你像我一样有一个 min target api-14 max target api-17 你没有“干净”的方法来将可绘制对象设置为背景。我坚持使用已弃用的电话。
经过大量搜索,我没有找到完全满足我需求的答案。但是,我从 2018 年开始偶然发现了这个名为“Android 中的实用图像处理”的视频,它为我指明了正确的方向:ImageFilterView
课堂。您可以在此处找到文档。
看到他们在同一张图像上应用多个过滤器的方式非常有启发性,而且并不那么难。它包括使用 a并通过调用方法ColorMatrix
连接多个 other 。最后,结果包含您应用的所有过滤器。ColorMatrix
ColorMatrix.postConcat
这是更改图像亮度和饱和度的示例代码。
package com.rewieer.imagefilters;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.SeekBar;
public class MainActivity extends AppCompatActivity {
private ImageView image;
private SeekBar brightnessSeekBar;
private SeekBar saturationSeekBar;
private BitmapDrawable defaultDrawable;
private int brightness = 0;
private int saturation = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = findViewById(R.id.mainImage);
defaultDrawable = (BitmapDrawable) image.getDrawable();
brightnessSeekBar = findViewById(R.id.brightnessSeekBar);
saturationSeekBar = findViewById(R.id.saturationSeekBar);
brightnessSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
brightness = progress;
redraw();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
saturationSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
saturation = progress;
redraw();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
public void redraw() {
ColorMatrix matrix = new ColorMatrix();
matrix.postConcat(new ColorMatrix(new float[]{
1f, 0, 0, 0, brightness,
0, 1f, 0, 0, brightness,
0, 0, 1f, 0, brightness,
0, 0, 0, 1f, 0
}));
float MS = 1.0F - saturation;
float Rt = 0.2999F * MS;
float Gt = 0.587F * MS;
float Bt = 0.114F * MS;
matrix.postConcat(new ColorMatrix(new float[]{
Rt + saturation, Gt, Bt, 0, 0,
Rt, Gt + saturation, Bt, 0, 0,
Rt, Gt, Bt + saturation, 0, 0,
0, 0, 0, 1f, 0
}));
image.setColorFilter(new ColorMatrixColorFilter(matrix));
}
}
这里最重要的方法是redraw
。通过查看ImageFilterView
源代码,我们还可以很容易地通过简单的复制粘贴他们的算法来对图像应用温暖和对比。