java - Android 保留一个位图作为更改色调、对比度、饱和度等的源
问题描述
我正在我的 android 应用程序中开发一项功能,用户将能够使用 SeekBar 修改位图的饱和度、色调、对比度等。我为每个处理编写了不同的方法。这可以单独工作,但如果我更改位图的色调并且在调用任何其他方法(例如饱和度)之前,我想保留位图并应用色调进度等。如果进度设置为默认值,用户应该能够看到原始位图。
例如,如果我将位图的色调值更改为 200。现在,如果我想编辑饱和度,则新的饱和度位图应该使用应用的色调。如果我将饱和度和色调进度重置为默认值,那么用户应该能够看到原始位图颜色。
我已经尝试了很多方法来实现这种行为,例如在每个方法调用之前复制像素,但这并没有帮助。目前,我只是在用户单击每种位图处理类型时将修改位图的像素复制到原始位图,但是如果我重置所有值,这不会将位图更改为原始颜色。请看我的代码。
我希望这将有助于理解问题。
private Bitmap wallpaper, modifiedWallpaper;
private ImageView imageView;
private ImageButton contrast;
private ImageButton hue;
private ImageButton saturation;
private float contrastProgress;
private float hueProgress;
private float satProgress;
private boolean isBlur, isBright, isContrast;
private boolean isHue, isSaturation, isRGB;
private TextView currentMode;
private SeekBar seekBar;
private Paint paint;
private Canvas canvas;
private CardView editor;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_customize_wallpaper, container, false);
imageView = view.findViewById(R.id.wallpaper);
rgbContainer = view.findViewById(R.id.rgb);
close = view.findViewById(R.id.close);
currentMode = view.findViewById(R.id.current_mode);
seekBar = view.findViewById(R.id.seekBar);
seekBar.setOnSeekBarChangeListener(seekBarChangeListener);
contrast = view.findViewById(R.id.contrast);
hue = view.findViewById(R.id.hue);
saturation = view.findViewById(R.id.saturation);
contrast.setOnClickListener(this);
hue.setOnClickListener(this);
saturation.setOnClickListener(this);
satProgress = 256f;
loadWallpaper(final String wallpaperUrl);
return view;
}
private void loadWallpaper(final String wallpaperUrl) {
Picasso.get().load(Constants.DOMAIN + wallpaperUrl).into(new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
wallpaper = bitmap; //original loaded
modifiedWallpaper = wallpaper.copy(Bitmap.Config.ARGB_8888, true);
imageView.setImageBitmap(wallpaper);
}
@Override
public void onBitmapFailed(Exception e, Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.contrast : {
wallpaper = modifiedWallpaper.copy(Bitmap.Config.ARGB_8888, true);
isBlur = false;
isBright = false;
isContrast = true;
isHue = false;
isSaturation = false;
isRGB = false;
seekBar.setVisibility(View.VISIBLE);
rgbContainer.setVisibility(View.GONE);
changeIconTint();
seekBar.setOnSeekBarChangeListener(null);
seekBar.setMax(90);
seekBar.setProgress((int) contrastProgress);
seekBar.setOnSeekBarChangeListener(seekBarChangeListener);
currentMode.setText("Contrast");
break;
}
case R.id.hue : {
wallpaper = modifiedWallpaper.copy(Bitmap.Config.ARGB_8888, true);
isBlur = false;
isBright = false;
isContrast = false;
isHue = true;
isSaturation = false;
isRGB = false;
seekBar.setVisibility(View.VISIBLE);
rgbContainer.setVisibility(View.GONE);
changeIconTint();
seekBar.setOnSeekBarChangeListener(null);
seekBar.setMax(180);
seekBar.setProgress((int) hueProgress);
seekBar.setOnSeekBarChangeListener(seekBarChangeListener);
currentMode.setText("Hue");
break;
}
case R.id.saturation : {
wallpaper = modifiedWallpaper.copy(Bitmap.Config.ARGB_8888, true);
isBlur = false;
isBright = false;
isContrast = false;
isHue = false;
isSaturation = true;
isRGB = false;
seekBar.setVisibility(View.VISIBLE);
rgbContainer.setVisibility(View.GONE);
changeIconTint();
seekBar.setOnSeekBarChangeListener(null);
seekBar.setMax(512);
seekBar.setProgress((int) satProgress);
seekBar.setOnSeekBarChangeListener(seekBarChangeListener);
currentMode.setText("Saturation");
break;
}
}
}
private void changeContrast(float contrastProgress) {
float cb = this.contrastProgress == 0 ? 0 : -(this.contrastProgress / 1.8f) * 5;
ColorMatrix cm = new ColorMatrix(new float[]
{
contrastProgress, 0, 0, 0, cb,
0, contrastProgress, 0, 0, cb,
0, 0, contrastProgress, 0, cb,
0, 0, 0, contrastProgress, 0
});
paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(cm));
modifiedWallpaper = wallpaper.copy(Bitmap.Config.ARGB_8888, true);
canvas = new Canvas(modifiedWallpaper);
canvas.drawBitmap(modifiedWallpaper, 0, 0, paint);
imageView.setImageBitmap(modifiedWallpaper);
}
private void changeHue() {
ColorMatrix cm = new ColorMatrix();
float hueProgress = cleanValue() / 90f * (float) Math.PI;
if (hueProgress == 0){
return;
}
float cosVal = (float) Math.cos(hueProgress);
float sinVal = (float) Math.sin(hueProgress);
float lumR = 0.213f;
float lumG = 0.715f;
float lumB = 0.072f;
float[] mat = new float[]
{//logic };
cm.postConcat(new ColorMatrix(mat));
paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(cm));
modifiedWallpaper = wallpaper.copy(Bitmap.Config.ARGB_8888, true);
canvas = new Canvas(modifiedWallpaper);
canvas.drawBitmap(modifiedWallpaper, 0, 0, paint);
imageView.setImageBitmap(modifiedWallpaper);
}
private void changeSaturation() {
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(satProgress / 256);
paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
modifiedWallpaper = wallpaper.copy(Bitmap.Config.ARGB_8888, true);
canvas = new Canvas(modifiedWallpaper);
canvas.drawBitmap(modifiedWallpaper, 0, 0, paint);
imageView.setImageBitmap(modifiedWallpaper);
}
private SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener()
{
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (isContrast) {
contrastProgress = seekBar.getProgress();
Log.d("Contrast", "" + (int) contrastProgress);
changeContrast((float) (seekBar.getProgress() + 10) / 10);
return;
}
if (isHue) {
hueProgress = seekBar.getProgress();
Log.d("Hue", "" + (int) hueProgress);
changeHue();
return;
}
if (isSaturation) {
satProgress = seekBar.getProgress();
Log.d("Saturation", "" + (int) satProgress);
changeSaturation();
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
解决方案
应用过滤器时,您没有保存状态。你用一个新的和一个新的来创建一个新 的。这就是为什么一个过滤器会覆盖前一个过滤器的原因。Paint
ColorMatrix
Bitmap
有几种方法可以解决这个问题。我认为一个好的第一步是将“过滤”与“绘图”功能分开。示例:changeSaturation()
在您的代码中,不仅更改了饱和度,而且还绘制到屏幕上。这是我的做法:
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (isContrast) contrast = (float) (seekBar.getProgress() + 10) / 10
if (isHue) hue = seekBar.getProgress();
if (isSaturation) saturation = seekBar.getProgress();
ColorMatrix matrix = calculateColorMatrix(contrast, hue, saturation);
drawBitmap(matrix);
}
private void drawBitmap(ColorMatrix colorMatrix) {
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
modifiedWallpaper = wallpaper.copy(Bitmap.Config.ARGB_8888, true);
canvas = new Canvas(modifiedWallpaper);
canvas.drawBitmap(modifiedWallpaper, 0, 0, paint);
imageView.setImageBitmap(modifiedWallpaper);
}
private ColorMatrix calculateColorMatrix(float contrast, hue, saturation) {
ColorMatrix colorMatrix = new ColorMatrix();
// saturation
colorMatrix.setSaturation(satProgress / 256);
// hue
float cosVal = (float) Math.cos(hueProgress);
float sinVal = (float) Math.sin(hueProgress);
float lumR = 0.213f;
// logic...
colorMatrix.postConcat(new ColorMatrix(mat));
//contrast
// logic...
colorMatrix.postConcat(new ColorMatrix(new float[]
{
contrastProgress, 0, 0, 0, cb,
0, contrastProgress, 0, 0, cb,
0, 0, contrastProgress, 0, cb,
0, 0, 0, contrastProgress, 0
}));
return colorMatrix;
}
这只是一种方法。可能是最简单的一种。如果您不想在每次滑块移动时创建所有过滤器,您可以matrix
为每个过滤器保留三个不同的过滤器,并且每次只修改其中一个。
ColorMatrix hue = new ColorMatrix();
ColorMatrix sat = new ColorMatrix();
ColorMatrix con = new ColorMatrix();
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (isContrast) {
con = //logic to create contrast matrix
}
if (isHue) {
hue //logic to create hue matrix
}
if (isSaturation) {
//...
sat.setSaturation(...)
}
ColorMatrix matrix = hue.postConcat(sat).postConcat(con);
drawBitmap(matrix);
}
我自己没有测试过这段代码,你可能需要做一些改变,但我希望这能让你朝着正确的方向前进!
推荐阅读
- python-3.x - 是否可以用scrapy做(某种)多态性
- javascript - 如何在 lightGallery 中动态更改图像 url
- r - 当值不存在时,有没有办法让排序函数返回 0 而不是 NA?
- sql - 带有额外数据的 SQL 表破坏了 SELECT 语句
- c# - 当 TabControl 中的选项卡更改时,对 ItemsControl 的 ItemsSource 的更改未在 UI 中更新
- xcode - XCTest:由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“参数“test”不得为 nil。
- spring-boot - Spring Boot 微服务 - Kafka Kerberos - PCF 中的 krb5 和 jaas 配置文件 - PCF 中的部署
- c# - 如何在动态选择中使用表达式创建“内联 if 语句”以进行空值检查
- javascript - 检查一个javascript数组是否包含另一个数组的所有元素或部分元素值
- javascript - 在 webpack 捆绑库上模拟 fbasyncInit 行为