added some effects)

This commit is contained in:
gdlbo
2022-07-12 15:49:02 +03:00
parent 049940f3bb
commit efac38a871
3 changed files with 175 additions and 331 deletions
@@ -3,7 +3,6 @@ import static ru.vtosters.lite.utils.Globals.getPreferences;
import static ru.vtosters.lite.utils.Globals.getResources;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
@@ -13,8 +12,6 @@ import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@@ -30,6 +27,38 @@ public class ImageFilters{
public static final int COLOR_MIN = 0x00;
public static final int COLOR_MAX = 0xFF;
public static Drawable getFilteredDrawable(Drawable orig){
if (orig == null) return null;
if (!(orig instanceof BitmapDrawable)) return orig;
Bitmap instance = ((BitmapDrawable) orig).getBitmap().copy(Bitmap.Config.ARGB_8888, true);
if (getPreferences().getBoolean("msg_invert", false)) {
instance = applyInvertEffect(instance);
}
if (getPreferences().getBoolean("msg_sepia", false)) {
instance = applySepiaEffect(instance);
}
if (getPreferences().getBoolean("msg_emboss", false)) {
instance = applyEmbossEffect(instance);
}
if (getPreferences().getBoolean("msg_engrave", false)) {
instance = applyEngraveEffect(instance);
}
if (getPreferences().getBoolean("msg_flea", false)) {
instance = applyFleaEffect(instance);
}
if (getPreferences().getBoolean("msg_snow", false)) {
instance = applySnowEffect(instance);
}
return new BitmapDrawable(getResources(), instance);
}
public static Drawable getBlurredWallpaper(Drawable orig, int radius){
try {
if (orig == null) return null;
@@ -119,37 +148,7 @@ public class ImageFilters{
canvas.drawBitmap(bm, new Matrix(), p);
}
public Bitmap applyHighlightEffect(Bitmap src){
// create new bitmap, which will be painted and becomes result image
Bitmap bmOut = Bitmap.createBitmap(src.getWidth() + 96, src.getHeight() + 96, Bitmap.Config.ARGB_8888);
// setup canvas for painting
Canvas canvas = new Canvas(bmOut);
// setup default color
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
// create a blur paint for capturing alpha
Paint ptBlur = new Paint();
ptBlur.setMaskFilter(new BlurMaskFilter(15, BlurMaskFilter.Blur.NORMAL));
int[] offsetXY = new int[2];
// capture alpha into a bitmap
Bitmap bmAlpha = src.extractAlpha(ptBlur, offsetXY);
// create a color paint
Paint ptAlphaColor = new Paint();
ptAlphaColor.setColor(0xFFFFFFFF);
// paint color for captured alpha region (bitmap)
canvas.drawBitmap(bmAlpha, offsetXY[0], offsetXY[1], ptAlphaColor);
// free memory
bmAlpha.recycle();
// paint the image source
canvas.drawBitmap(src, 0, 0, null);
// return out final image
return bmOut;
}
public Bitmap applyInvertEffect(Bitmap src){
public static Bitmap applyInvertEffect(Bitmap src){
// create new bitmap with the same settings as source bitmap
Bitmap bmOut = Bitmap.createBitmap(src.getWidth(), src.getHeight(), src.getConfig());
// color info
@@ -179,123 +178,7 @@ public class ImageFilters{
return bmOut;
}
public Bitmap applyGreyscaleEffect(Bitmap src){
// constant factors
final double GS_RED = 0.299;
final double GS_GREEN = 0.587;
final double GS_BLUE = 0.114;
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(src.getWidth(), src.getHeight(), src.getConfig());
// pixel information
int A, R, G, B;
int pixel;
// get image size
int width = src.getWidth();
int height = src.getHeight();
// scan through every single pixel
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
// get one pixel color
pixel = src.getPixel(x, y);
// retrieve color of all channels
A = Color.alpha(pixel);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
// take conversion up to one single value
R = G = B = (int) (GS_RED * R + GS_GREEN * G + GS_BLUE * B);
// set new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
// return final image
return bmOut;
}
//Gamma Image (R, G, B) = (1.8, 1.8, 1.8)
public Bitmap applyGammaEffect(Bitmap src, double red, double green, double blue){
// create output image
Bitmap bmOut = Bitmap.createBitmap(src.getWidth(), src.getHeight(), src.getConfig());
// get image size
int width = src.getWidth();
int height = src.getHeight();
// color information
int A, R, G, B;
int pixel;
// constant value curve
final int MAX_SIZE = 256;
final double MAX_VALUE_DBL = 255.0;
final int MAX_VALUE_INT = 255;
final double REVERSE = 1.0;
// gamma arrays
int[] gammaR = new int[MAX_SIZE];
int[] gammaG = new int[MAX_SIZE];
int[] gammaB = new int[MAX_SIZE];
// setting values for every gamma channels
for (int i = 0; i < MAX_SIZE; ++i) {
gammaR[i] = (int) Math.min(MAX_VALUE_INT,
(int) ((MAX_VALUE_DBL * Math.pow(i / MAX_VALUE_DBL, REVERSE / red)) + 0.5));
gammaG[i] = (int) Math.min(MAX_VALUE_INT,
(int) ((MAX_VALUE_DBL * Math.pow(i / MAX_VALUE_DBL, REVERSE / green)) + 0.5));
gammaB[i] = (int) Math.min(MAX_VALUE_INT,
(int) ((MAX_VALUE_DBL * Math.pow(i / MAX_VALUE_DBL, REVERSE / blue)) + 0.5));
}
// apply gamma table
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
// look up gamma
R = gammaR[Color.red(pixel)];
G = gammaG[Color.green(pixel)];
B = gammaB[Color.blue(pixel)];
// set new color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
// return final image
return bmOut;
}
public Bitmap applyColorFilterEffect(Bitmap src, double red, double green, double blue){
// image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// color information
int A, R, G, B;
int pixel;
// scan through all pixels
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
// apply filtering on each channel R, G, B
A = Color.alpha(pixel);
R = (int) (Color.red(pixel) * red);
G = (int) (Color.green(pixel) * green);
B = (int) (Color.blue(pixel) * blue);
// set new color pixel to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
// return final image
return bmOut;
}
public Bitmap applySepiaToningEffect(Bitmap src, int depth, double red, double green, double blue){
public static Bitmap applySepiaEffect(Bitmap src){
// image size
int width = src.getWidth();
int height = src.getHeight();
@@ -320,25 +203,10 @@ public class ImageFilters{
G = Color.green(pixel);
B = Color.blue(pixel);
// apply grayscale sample
B = G = R = (int) (GS_RED * R + GS_GREEN * G + GS_BLUE * B);
// apply intensity level for sepid-toning on each channel
R += (depth * red);
if (R > 255) {
R = 255;
}
G += (depth * green);
if (G > 255) {
G = 255;
}
B += (depth * blue);
if (B > 255) {
B = 255;
}
// set new pixel color to output image
B = (int) (GS_RED * R + GS_GREEN * G + GS_BLUE * B);
// apply intensity level for sepia tone
R = G = B = (int) (B * 0.9);
// set new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
@@ -347,6 +215,91 @@ public class ImageFilters{
return bmOut;
}
public static Bitmap applyEmbossEffect(Bitmap src){
double[][] EmbossConfig = new double[][] {
{-1, 0, -1},
{0, 4, 0},
{-1, 0, -1}
};
ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
convMatrix.applyConfig(EmbossConfig);
convMatrix.Factor = 1;
convMatrix.Offset = 127;
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
}
public static Bitmap applyEngraveEffect(Bitmap src){
ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
convMatrix.setAll(0);
convMatrix.Matrix[0][0] = -2;
convMatrix.Matrix[1][1] = 2;
convMatrix.Factor = 1;
convMatrix.Offset = 95;
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
}
public static Bitmap applyFleaEffect(Bitmap source){
// get image size
int width = source.getWidth();
int height = source.getHeight();
int[] pixels = new int[width * height];
// get pixel array from source
source.getPixels(pixels, 0, width, 0, 0, width, height);
// a random object
Random random = new Random();
int index = 0;
// iteration through pixels
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
// get current index in 2D-matrix
index = y * width + x;
// get random color
int randColor = Color.rgb(random.nextInt(COLOR_MAX),
random.nextInt(COLOR_MAX), random.nextInt(COLOR_MAX));
// OR
pixels[index] |= randColor;
}
}
// output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, source.getConfig());
bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
return bmOut;
}
public static Bitmap applySnowEffect(Bitmap source){
// get image size
int width = source.getWidth();
int height = source.getHeight();
int[] pixels = new int[width * height];
// get pixel array from source
source.getPixels(pixels, 0, width, 0, 0, width, height);
// random object
Random random = new Random();
int R, G, B, index = 0, thresHold = 50;
// iteration through pixels
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
// get current index in 2D-matrix
index = y * width + x;
// get color
R = Color.red(pixels[index]);
G = Color.green(pixels[index]);
B = Color.blue(pixels[index]);
// generate threshold
thresHold = random.nextInt(COLOR_MAX);
if (R > thresHold && G > thresHold && B > thresHold) {
pixels[index] = Color.rgb(COLOR_MAX, COLOR_MAX, COLOR_MAX);
}
}
}
// output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
return bmOut;
}
public Bitmap applyDecreaseColorDepthEffect(Bitmap src, int bitOffset){
// get image size
int width = src.getWidth();
@@ -540,29 +493,6 @@ public class ImageFilters{
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
}
public Bitmap applyEmbossEffect(Bitmap src){
double[][] EmbossConfig = new double[][] {
{-1, 0, -1},
{0, 4, 0},
{-1, 0, -1}
};
ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
convMatrix.applyConfig(EmbossConfig);
convMatrix.Factor = 1;
convMatrix.Offset = 127;
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
}
public Bitmap applyEngraveEffect(Bitmap src){
ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
convMatrix.setAll(0);
convMatrix.Matrix[0][0] = -2;
convMatrix.Matrix[1][1] = 2;
convMatrix.Factor = 1;
convMatrix.Offset = 95;
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
}
public Bitmap applyBoostEffect(Bitmap src, int type, float percent){
int width = src.getWidth();
int height = src.getHeight();
@@ -594,37 +524,6 @@ public class ImageFilters{
return bmOut;
}
public Bitmap applyRoundCornerEffect(Bitmap src, float round){
// image size
int width = src.getWidth();
int height = src.getHeight();
// create bitmap output
Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
// set canvas for painting
Canvas canvas = new Canvas(result);
canvas.drawARGB(0, 0, 0, 0);
// config paint
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
// config rectangle for embedding
final Rect rect = new Rect(0, 0, width, height);
final RectF rectF = new RectF(rect);
// draw rect to canvas
canvas.drawRoundRect(rectF, round, round, paint);
// create Xfer mode
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
// draw source image to canvas
canvas.drawBitmap(src, rect, rect, paint);
// return final image
return result;
}
public Bitmap applyTintEffect(Bitmap src, int degree){
int width = src.getWidth();
@@ -669,35 +568,6 @@ public class ImageFilters{
return outBitmap;
}
public Bitmap applyFleaEffect(Bitmap source){
// get image size
int width = source.getWidth();
int height = source.getHeight();
int[] pixels = new int[width * height];
// get pixel array from source
source.getPixels(pixels, 0, width, 0, 0, width, height);
// a random object
Random random = new Random();
int index = 0;
// iteration through pixels
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
// get current index in 2D-matrix
index = y * width + x;
// get random color
int randColor = Color.rgb(random.nextInt(COLOR_MAX),
random.nextInt(COLOR_MAX), random.nextInt(COLOR_MAX));
// OR
pixels[index] |= randColor;
}
}
// output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, source.getConfig());
bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
return bmOut;
}
public Bitmap applyBlackFilter(Bitmap source){
// get image size
int width = source.getWidth();
@@ -731,39 +601,6 @@ public class ImageFilters{
return bmOut;
}
public Bitmap applySnowEffect(Bitmap source){
// get image size
int width = source.getWidth();
int height = source.getHeight();
int[] pixels = new int[width * height];
// get pixel array from source
source.getPixels(pixels, 0, width, 0, 0, width, height);
// random object
Random random = new Random();
int R, G, B, index = 0, thresHold = 50;
// iteration through pixels
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
// get current index in 2D-matrix
index = y * width + x;
// get color
R = Color.red(pixels[index]);
G = Color.green(pixels[index]);
B = Color.blue(pixels[index]);
// generate threshold
thresHold = random.nextInt(COLOR_MAX);
if (R > thresHold && G > thresHold && B > thresHold) {
pixels[index] = Color.rgb(COLOR_MAX, COLOR_MAX, COLOR_MAX);
}
}
}
// output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
return bmOut;
}
public Bitmap applyShadingFilter(Bitmap source, int shadingColor){
// get image size
int width = source.getWidth();
@@ -847,48 +684,4 @@ public class ImageFilters{
bmOut.setPixels(pixels, 0, width, 0, 0, width, height);
return bmOut;
}
public Bitmap applyReflection(Bitmap originalImage){
// gap space between original and reflected
final int reflectionGap = 4;
// get image size
int width = originalImage.getWidth();
int height = originalImage.getHeight();
// this will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
// create a Bitmap with the flip matrix applied to it.
// we only want the bottom half of the image
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height / 2, width, height / 2, matrix, false);
// create a new bitmap with same width but taller to fit reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Bitmap.Config.ARGB_8888);
// create a new Canvas with the bitmap that's big enough for
// the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
// draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null);
// draw in the gap
Paint defaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);
// draw in the reflection
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
// create a shader that is a linear gradient that covers the reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff,
Shader.TileMode.CLAMP);
// set the paint to use this shader (linear gradient)
paint.setShader(shader);
// set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
// draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);
return bitmapWithReflection;
}
}
@@ -73,7 +73,7 @@ public class WallpaperMenuFragment extends MaterialPreferenceToolbarFragment{
return true;
});
PreferencesUtil.addPreferenceCategory(this, "Параметры");
PreferencesUtil.addPreferenceCategory(this, "Фильтры");
PreferencesUtil.addListPreference(this, "msg_blur_radius", "disabled", "Размытие фона сообщений", new CharSequence[] {
"Отключено", "Низкое (15px)", "Среднее (25px)", "Высокое (50px)"
@@ -101,6 +101,54 @@ public class WallpaperMenuFragment extends MaterialPreferenceToolbarFragment{
return true;
});
PreferencesUtil.addMaterialSwitchPreference(this, "msg_invert", "Инвертировать цвета", "", null, false, (preference, o) -> {
boolean value = (boolean) o;
edit().putBoolean("msg_invert", value).commit();
requestUpdateWallpaper();
mWPPreviewPref.redraw();
return true;
});
PreferencesUtil.addMaterialSwitchPreference(this, "msg_sepia", "Эффект сепии", "Возможна нагрузка на устройство", null, false, (preference, o) -> {
boolean value = (boolean) o;
edit().putBoolean("msg_sepia", value).commit();
requestUpdateWallpaper();
mWPPreviewPref.redraw();
return true;
});
PreferencesUtil.addMaterialSwitchPreference(this, "msg_emboss", "Emboss фильтр", "Возможна нагрузка на устройство", null, false, (preference, o) -> {
boolean value = (boolean) o;
edit().putBoolean("msg_emboss", value).commit();
requestUpdateWallpaper();
mWPPreviewPref.redraw();
return true;
});
PreferencesUtil.addMaterialSwitchPreference(this, "msg_engrave", "Engrave фильтр", "", null, false, (preference, o) -> {
boolean value = (boolean) o;
edit().putBoolean("msg_engrave", value).commit();
requestUpdateWallpaper();
mWPPreviewPref.redraw();
return true;
});
PreferencesUtil.addMaterialSwitchPreference(this, "msg_flea", "Flea фильтр", "", null, false, (preference, o) -> {
boolean value = (boolean) o;
edit().putBoolean("msg_flea", value).commit();
requestUpdateWallpaper();
mWPPreviewPref.redraw();
return true;
});
PreferencesUtil.addMaterialSwitchPreference(this, "msg_snow", "Эффект снега", "", null, false, (preference, o) -> {
boolean value = (boolean) o;
edit().putBoolean("msg_snow", value).commit();
requestUpdateWallpaper();
mWPPreviewPref.redraw();
return true;
});
ListPreference blur = (ListPreference) findPreference("msg_blur_radius");
ListPreference dim = (ListPreference) findPreference("msg_dim");
ListPreference mosaic = (ListPreference) findPreference("msg_mosaic");
@@ -2,6 +2,7 @@ package ru.vtosters.lite.ui.wallpapers;
import static com.vk.im.engine.h.im_bg_chat;
import static ru.vtosters.lite.ui.wallpapers.ImageFilters.getBlurredWallpaper;
import static ru.vtosters.lite.ui.wallpapers.ImageFilters.getDimmed;
import static ru.vtosters.lite.ui.wallpapers.ImageFilters.getFilteredDrawable;
import static ru.vtosters.lite.ui.wallpapers.ImageFilters.getMonochrome;
import static ru.vtosters.lite.ui.wallpapers.ImageFilters.getMosaic;
import static ru.vtosters.lite.utils.Globals.getContext;
@@ -58,6 +59,8 @@ public class WallpapersHooks{
mWallpaper = getMonochrome(mWallpaper);
}
mWallpaper = getFilteredDrawable(mWallpaper);
mUpdateWallpaperRequested = false;
}