From efac38a871a1ea9dd31d7f891986f5239a3a6da8 Mon Sep 17 00:00:00 2001 From: gdlbo <41114720+gdlbo@users.noreply.github.com> Date: Tue, 12 Jul 2022 15:49:02 +0300 Subject: [PATCH] added some effects) --- .../lite/ui/wallpapers/ImageFilters.java | 453 +++++------------- .../ui/wallpapers/WallpaperMenuFragment.java | 50 +- .../lite/ui/wallpapers/WallpapersHooks.java | 3 + 3 files changed, 175 insertions(+), 331 deletions(-) diff --git a/app/src/main/java/ru/vtosters/lite/ui/wallpapers/ImageFilters.java b/app/src/main/java/ru/vtosters/lite/ui/wallpapers/ImageFilters.java index 1f342b84f..53163a220 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/wallpapers/ImageFilters.java +++ b/app/src/main/java/ru/vtosters/lite/ui/wallpapers/ImageFilters.java @@ -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; - } } diff --git a/app/src/main/java/ru/vtosters/lite/ui/wallpapers/WallpaperMenuFragment.java b/app/src/main/java/ru/vtosters/lite/ui/wallpapers/WallpaperMenuFragment.java index 7aff2523a..350595d58 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/wallpapers/WallpaperMenuFragment.java +++ b/app/src/main/java/ru/vtosters/lite/ui/wallpapers/WallpaperMenuFragment.java @@ -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"); diff --git a/app/src/main/java/ru/vtosters/lite/ui/wallpapers/WallpapersHooks.java b/app/src/main/java/ru/vtosters/lite/ui/wallpapers/WallpapersHooks.java index f35c3decf..bae8d4696 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/wallpapers/WallpapersHooks.java +++ b/app/src/main/java/ru/vtosters/lite/ui/wallpapers/WallpapersHooks.java @@ -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; }