Refactor wp (#944)
* Extract couple filters to separate classes * Move ImageEffects to separate file * Refactor effects to use bitmap * Reformat code, extract last batch of effects to classes * Shitty intermediate refactor * Still intermediate sh**, buildable btw * More refactoring, still looks disgusting, but a bit better) * Add fixme about order * Remove unused stuff * Remove unused code, prevent re-creating of drawable * Refactor img effects to native * Add native lib sources * Implement Dim, Mosaic and Blur in native * Add pre-built libs * Get rid of filter abstraction * Include native build * Force rust toolchains * Fix typos * Comment not used smali * Simplify wallpapers handling * Fixes after main merge * Minor fixes, add prebuilt lib, disable auto re-builds for native * Fix missed copyscpec for native builds * Fix entry for dim effect * Fix resizing to respect current image dimensions * Wtf? who stole NDK from actions * Learning GH actions I don't want to read the docs * Revert "Learning GH actions" This reverts commitf6f9a97d10. * Revert "Wtf? who stole NDK from actions" This reverts commit1d0f1b8879. * Try out latest LTS just why not --------- Co-authored-by: saoq <wfmfe@ya.ru>
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
package ru.vtosters.lite.ui.wallpapers;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.vtosters.lite.R;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
|
||||
enum ImageEffects {
|
||||
Blur(true,
|
||||
AndroidUtils.getArray(R.array.filter_types),
|
||||
new String[]{"disabled", "low", "med", "high"},
|
||||
getGlobalContext().getString(R.string.filter_blur)
|
||||
) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
int radius;
|
||||
switch (getPreferences().getString(ImageEffects.Blur.toString(), "disabled")) {
|
||||
case "low":
|
||||
radius = 8;
|
||||
break;
|
||||
case "med":
|
||||
radius = 14;
|
||||
break;
|
||||
case "high":
|
||||
radius = 20;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
NativeEffects.gaussian(bitmap, height, width, radius);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSummary() {
|
||||
switch (getPreferences().getString(ImageEffects.Blur.toString(), "disabled")) {
|
||||
case "low":
|
||||
return AndroidUtils.getString(R.string.wallpapers_low);
|
||||
case "med":
|
||||
return AndroidUtils.getString(R.string.wallpapers_med);
|
||||
case "high":
|
||||
return AndroidUtils.getString(R.string.wallpapers_high);
|
||||
default:
|
||||
return AndroidUtils.getString(R.string.wallpapers_disabled);
|
||||
}
|
||||
}
|
||||
},
|
||||
Dim(true,
|
||||
AndroidUtils.getArray(R.array.filter_dim_types),
|
||||
new String[]{"disabled", "dim_black", "dim_white"},
|
||||
getGlobalContext().getString(R.string.filter_dim)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
var delta = 0;
|
||||
switch (getPreferences().getString(ImageEffects.Dim.toString(), "disabled")) {
|
||||
case "dim_black":
|
||||
delta = -50; break;
|
||||
case "dim_white":
|
||||
delta = 50; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
NativeEffects.dim(bitmap, height, width, delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSummary() {
|
||||
switch (getPreferences().getString(ImageEffects.Dim.toString(), "disabled")) {
|
||||
case "dim_black":
|
||||
return AndroidUtils.getString(R.string.wallpapers_dim_black);
|
||||
case "dim_white":
|
||||
return AndroidUtils.getString(R.string.wallpapers_dim_white);
|
||||
default:
|
||||
return AndroidUtils.getString(R.string.wallpapers_disabled);
|
||||
}
|
||||
}
|
||||
},
|
||||
Mosaic(true,
|
||||
AndroidUtils.getArray(R.array.filter_types),
|
||||
new String[]{"disabled", "low", "med", "high"},
|
||||
getGlobalContext().getString(R.string.filter_mosaic)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
var scale = 0;
|
||||
switch (getPreferences().getString(ImageEffects.Mosaic.toString(), "disabled")) {
|
||||
case "high":
|
||||
scale = 50; break;
|
||||
case "med":
|
||||
scale = 25; break;
|
||||
case "low":
|
||||
scale = 10; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
NativeEffects.mosaic(bitmap, height, width, scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSummary() {
|
||||
switch (getPreferences().getString(ImageEffects.Mosaic.toString(), "disabled")) {
|
||||
case "low":
|
||||
return AndroidUtils.getString(R.string.wallpapers_low);
|
||||
case "med":
|
||||
return AndroidUtils.getString(R.string.wallpapers_med);
|
||||
case "high":
|
||||
return AndroidUtils.getString(R.string.wallpapers_high);
|
||||
default:
|
||||
return AndroidUtils.getString(R.string.wallpapers_disabled);
|
||||
}
|
||||
}
|
||||
},
|
||||
Monochrome(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_monochrome)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()) {
|
||||
NativeEffects.monochrome(bitmap);
|
||||
}
|
||||
}
|
||||
},
|
||||
Invert(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_invert_colors)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()) {
|
||||
NativeEffects.invert(bitmap);
|
||||
}
|
||||
}
|
||||
},
|
||||
Sepia(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_sepia)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()) {
|
||||
NativeEffects.sepia(bitmap);
|
||||
}
|
||||
}
|
||||
},
|
||||
Emboss(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_emboss)) {
|
||||
@Override
|
||||
public String getSummary() {
|
||||
return getGlobalContext().getString(R.string.filter_maybe_lag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()) {
|
||||
NativeEffects.emboss(bitmap, height, width);
|
||||
}
|
||||
}
|
||||
},
|
||||
Engrave(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_engrave)) {
|
||||
@Override
|
||||
public String getSummary() {
|
||||
return getGlobalContext().getString(R.string.filter_maybe_lag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()) {
|
||||
NativeEffects.engrave(bitmap, height, width);
|
||||
}
|
||||
}
|
||||
},
|
||||
Flea(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_flea)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()) {
|
||||
NativeEffects.flea(bitmap);
|
||||
}
|
||||
}
|
||||
},
|
||||
Snow(false, null, null,
|
||||
getGlobalContext().getString(R.string.filter_snow)) {
|
||||
@Override
|
||||
public void applyEffect(ByteBuffer bitmap, int height, int width) {
|
||||
if (isApplied()){
|
||||
NativeEffects.snow(bitmap);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final boolean free;
|
||||
private final String title;
|
||||
@Nullable
|
||||
private final String[] entryValues;
|
||||
@Nullable
|
||||
private final String[] entries;
|
||||
|
||||
ImageEffects(boolean free, @Nullable String[] entries, @Nullable String[] entryValues, String title) {
|
||||
this.free = free;
|
||||
this.entries = entries;
|
||||
this.entryValues = entryValues;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public Boolean isSwitch() {
|
||||
return entryValues == null || entryValues.length == 0;
|
||||
}
|
||||
|
||||
public Boolean isList() {
|
||||
return entryValues != null && entryValues.length > 0;
|
||||
}
|
||||
|
||||
public boolean isFree() {
|
||||
return free;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String[] getEntries() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String[] getEntryValues() {
|
||||
return entryValues;
|
||||
}
|
||||
|
||||
public String getSummary() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public abstract void applyEffect(ByteBuffer bitmap, int height, int width);
|
||||
|
||||
protected boolean isApplied() {
|
||||
return getPreferences().getBoolean(this.toString(), false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "msg_" + super.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,351 +1,37 @@
|
||||
package ru.vtosters.lite.ui.wallpapers;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getResources;
|
||||
import static ru.vtosters.lite.utils.Preferences.hasVerification;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.LightingColorFilter;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.vk.medianative.MediaNative;
|
||||
|
||||
import java.util.Random;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class ImageFilters {
|
||||
public static final int COLOR_MAX = 0xFF;
|
||||
|
||||
public static Drawable getFilteredDrawable(Drawable orig) {
|
||||
if (orig == null) return null;
|
||||
if (!(orig instanceof BitmapDrawable)) return orig;
|
||||
|
||||
if (!getPreferences().getString("msg_blur_radius", "disabled").equals("disabled")) {
|
||||
orig = getBlurredWallpaper(orig, getRadius());
|
||||
Bitmap bitmap = ((BitmapDrawable) orig).getBitmap();
|
||||
if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
|
||||
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
|
||||
}
|
||||
|
||||
if (!getPreferences().getString("msg_dim", "off").equals("off")) {
|
||||
orig = getDimmed(orig);
|
||||
var directBuff = ByteBuffer.allocateDirect(bitmap.getByteCount());
|
||||
directBuff.order(ByteOrder.nativeOrder());
|
||||
bitmap.copyPixelsToBuffer(directBuff);
|
||||
|
||||
// FIXME: preserve order of filters
|
||||
// e.g. user turned invert first then mosaic then monochrome
|
||||
// invocation here happens regardless of that order
|
||||
for (var type : ImageEffects.values()) {
|
||||
type.applyEffect(directBuff, bitmap.getHeight(), bitmap.getWidth());
|
||||
}
|
||||
|
||||
if (!getPreferences().getString("msg_mosaic", "disabled").equals("disabled")) {
|
||||
orig = getMosaic(orig);
|
||||
}
|
||||
|
||||
if (!hasVerification()) {
|
||||
return orig;
|
||||
}
|
||||
|
||||
if (getPreferences().getBoolean("msg_monochrome", false)) {
|
||||
orig = getMonochrome(orig);
|
||||
}
|
||||
|
||||
Bitmap bm;
|
||||
|
||||
if (orig != null) {
|
||||
bm = ((BitmapDrawable) orig).getBitmap();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
Bitmap instance = bm.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);
|
||||
}
|
||||
|
||||
private static int getRadius() {
|
||||
String radius = getPreferences().getString("msg_blur_radius", "disabled");
|
||||
return switch (radius) {
|
||||
case "low" -> 8;
|
||||
case "med" -> 14;
|
||||
default -> 20;
|
||||
};
|
||||
}
|
||||
|
||||
public static Drawable getBlurredWallpaper(Drawable orig, int radius) {
|
||||
try {
|
||||
if (orig == null) return null;
|
||||
if (!(orig instanceof BitmapDrawable)) return orig; // we need only BitmapDrawable
|
||||
Bitmap bm = ((BitmapDrawable) orig).getBitmap();
|
||||
|
||||
Bitmap instance = bm.copy(Bitmap.Config.ARGB_8888, true);
|
||||
|
||||
MediaNative.blurBitmap(instance, radius);
|
||||
return new BitmapDrawable(getResources(), instance);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return orig;
|
||||
}
|
||||
}
|
||||
|
||||
public static Drawable getMosaic(Drawable orig) {
|
||||
int scale = 100;
|
||||
|
||||
if (orig == null) return null;
|
||||
if (!(orig instanceof BitmapDrawable)) return orig;
|
||||
Bitmap bm = ((BitmapDrawable) orig).getBitmap();
|
||||
|
||||
|
||||
Bitmap instance = bm.copy(Bitmap.Config.ARGB_8888, true);
|
||||
|
||||
|
||||
String radius = getPreferences().getString("msg_mosaic", "disabled");
|
||||
|
||||
switch (radius) {
|
||||
case "high" -> scale = 25;
|
||||
case "med" -> scale = 50;
|
||||
case "low" -> scale = 75;
|
||||
}
|
||||
|
||||
Bitmap temp = Bitmap.createScaledBitmap(instance, scale, scale, false);
|
||||
Bitmap mosaicBitmap = Bitmap.createScaledBitmap(temp, instance.getWidth(), instance.getHeight(), false);
|
||||
|
||||
return new BitmapDrawable(getResources(), mosaicBitmap);
|
||||
}
|
||||
|
||||
public static Drawable getDimmed(Drawable orig) {
|
||||
if (orig == null) return null;
|
||||
if (!(orig instanceof BitmapDrawable)) return orig;
|
||||
Bitmap bm = ((BitmapDrawable) orig).getBitmap();
|
||||
|
||||
Bitmap instance = bm.copy(Bitmap.Config.ARGB_8888, true);
|
||||
|
||||
String radius = getPreferences().getString("msg_dim", "disabled");
|
||||
switch (radius) {
|
||||
case "dim_black":
|
||||
darken(instance);
|
||||
case "dim_white":
|
||||
lighten(instance);
|
||||
}
|
||||
return new BitmapDrawable(getResources(), instance);
|
||||
}
|
||||
|
||||
public static Drawable getMonochrome(Drawable orig) {
|
||||
if (orig == null) return null;
|
||||
if (!(orig instanceof BitmapDrawable)) return orig;
|
||||
Bitmap bm = ((BitmapDrawable) orig).getBitmap();
|
||||
|
||||
Bitmap instance = bm.copy(Bitmap.Config.ARGB_8888, true);
|
||||
|
||||
Bitmap bwBitmap = Bitmap.createBitmap(instance.getWidth(), instance.getHeight(), Bitmap.Config.RGB_565);
|
||||
float[] hsv = new float[3];
|
||||
for (int col = 0; col < instance.getWidth(); col++) {
|
||||
for (int row = 0; row < instance.getHeight(); row++) {
|
||||
Color.colorToHSV(instance.getPixel(col, row), hsv);
|
||||
if (hsv[2] > 0.5f) {
|
||||
bwBitmap.setPixel(col, row, 0xffffffff);
|
||||
} else {
|
||||
bwBitmap.setPixel(col, row, 0xff000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new BitmapDrawable(getResources(), bwBitmap);
|
||||
}
|
||||
|
||||
private static void darken(Bitmap bm) {
|
||||
try {
|
||||
Canvas canvas = new Canvas(bm);
|
||||
Paint p = new Paint(Color.RED);
|
||||
ColorFilter filter = new LightingColorFilter(0xFF7F7F7F, 0x00000000); // darken
|
||||
p.setColorFilter(filter);
|
||||
canvas.drawBitmap(bm, new Matrix(), p);
|
||||
} catch (Exception e) {
|
||||
Log.d("WallpaperD", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static void lighten(Bitmap bm) {
|
||||
try {
|
||||
Canvas canvas = new Canvas(bm);
|
||||
Paint p = new Paint(Color.RED);
|
||||
ColorFilter filter = new LightingColorFilter(0xFFFFFFFF, 0x00222222); // lighten
|
||||
p.setColorFilter(filter);
|
||||
canvas.drawBitmap(bm, new Matrix(), p);
|
||||
} catch (Exception e) {
|
||||
Log.d("WallpaperL", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
int A, R, G, B;
|
||||
int pixelColor;
|
||||
// image size
|
||||
int height = src.getHeight();
|
||||
int width = src.getWidth();
|
||||
|
||||
// scan through every pixel
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
// get one pixel
|
||||
pixelColor = src.getPixel(x, y);
|
||||
// saving alpha channel
|
||||
A = Color.alpha(pixelColor);
|
||||
// inverting byte for each R/G/B channel
|
||||
R = 255 - Color.red(pixelColor);
|
||||
G = 255 - Color.green(pixelColor);
|
||||
B = 255 - Color.blue(pixelColor);
|
||||
// set newly-inverted pixel to output image
|
||||
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
|
||||
}
|
||||
}
|
||||
|
||||
// return final bitmap
|
||||
return bmOut;
|
||||
}
|
||||
|
||||
public static Bitmap applySepiaEffect(Bitmap src) {
|
||||
// image size
|
||||
int width = src.getWidth();
|
||||
int height = src.getHeight();
|
||||
// create output bitmap
|
||||
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
|
||||
// constant grayscale
|
||||
final double GS_RED = 0.3;
|
||||
final double GS_GREEN = 0.59;
|
||||
final double GS_BLUE = 0.11;
|
||||
// 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);
|
||||
// get color on each channel
|
||||
A = Color.alpha(pixel);
|
||||
R = Color.red(pixel);
|
||||
G = Color.green(pixel);
|
||||
B = Color.blue(pixel);
|
||||
// apply grayscale sample
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// return final image
|
||||
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;
|
||||
// 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, thresHold;
|
||||
// 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;
|
||||
directBuff.flip();
|
||||
bitmap.copyPixelsFromBuffer(directBuff);
|
||||
return new BitmapDrawable(getResources(), bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package ru.vtosters.lite.ui.wallpapers;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class NativeEffects {
|
||||
|
||||
static {
|
||||
System.loadLibrary("native_effects");
|
||||
}
|
||||
|
||||
public static native String monochrome(ByteBuffer input);
|
||||
public static native String invert(ByteBuffer input);
|
||||
public static native String sepia(ByteBuffer input);
|
||||
public static native String emboss(ByteBuffer input, int height, int width);
|
||||
public static native String engrave(ByteBuffer input, int height, int width);
|
||||
public static native String flea(ByteBuffer input);
|
||||
public static native String snow(ByteBuffer input);
|
||||
// FIXME: slow when comparing with MediaNative.blurBitmap
|
||||
public static native String gaussian(ByteBuffer input, int height, int width, float radius);
|
||||
public static native String dim(ByteBuffer input, int height, int width, int delta);
|
||||
public static native String mosaic(ByteBuffer input, int height, int width, int scale);
|
||||
}
|
||||
@@ -7,17 +7,16 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.ListPreference;
|
||||
import com.vtosters.lite.R;
|
||||
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
||||
import com.vtosters.lite.im.ImEngineProvider;
|
||||
import ru.vtosters.lite.ui.PreferenceFragmentUtils;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static ru.vtosters.lite.ui.wallpapers.WallpapersHooks.*;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||
@@ -29,7 +28,6 @@ public class WallpaperMenuFragment extends MaterialPreferenceToolbarFragment {
|
||||
private WallpaperPreferences mWPPreviewPref;
|
||||
|
||||
public static void copyStream(InputStream copyFrom, OutputStream copyTo) throws IOException {
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int length;
|
||||
while ((length = copyFrom.read(buffer)) > 0) {
|
||||
@@ -47,146 +45,117 @@ public class WallpaperMenuFragment extends MaterialPreferenceToolbarFragment {
|
||||
|
||||
addPreferencesFromResource(R.xml.empty);
|
||||
|
||||
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), requireContext().getString(R.string.vkim_settings_appearance_chat_preview_title));
|
||||
PreferenceFragmentUtils.addPreferenceCategory(
|
||||
getPreferenceScreen(),
|
||||
requireContext().getString(R.string.vkim_settings_appearance_chat_preview_title)
|
||||
);
|
||||
|
||||
mWPPreviewPref = new WallpaperPreferences(getContext());
|
||||
mWPPreviewPref.setIcon(null);
|
||||
mWPPreviewPref.setIconSpaceReserved(false);
|
||||
getPreferenceScreen().addPreference(mWPPreviewPref);
|
||||
|
||||
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "wp_set", requireContext().getString(R.string.wallpaper_select), requireContext().getString(R.string.wallpaper_from_gallery), R.drawable.ic_picture_outline_28, preference -> {
|
||||
startActivityForResult(new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI), 1488);
|
||||
removeStickCache();
|
||||
return true;
|
||||
});
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"wp_set",
|
||||
requireContext().getString(R.string.wallpaper_select),
|
||||
requireContext().getString(R.string.wallpaper_from_gallery),
|
||||
R.drawable.ic_picture_outline_28,
|
||||
preference -> {
|
||||
startActivityForResult(
|
||||
new Intent(
|
||||
Intent.ACTION_PICK,
|
||||
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
||||
),
|
||||
1488
|
||||
);
|
||||
removeStickCache();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "wp_clear", requireContext().getString(R.string.wallpaper_remove), "", R.drawable.ic_delete_outline_28, preference -> {
|
||||
removeWallpaper();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
removeStickCache();
|
||||
return true;
|
||||
});
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"wp_clear",
|
||||
requireContext().getString(R.string.wallpaper_remove),
|
||||
"",
|
||||
R.drawable.ic_delete_outline_28,
|
||||
preference -> {
|
||||
removeWallpaper();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
removeStickCache();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), requireContext().getString(R.string.vtlfilters));
|
||||
|
||||
if (!hasVerification() && !getBoolValue("dialogrecomm", false)) {
|
||||
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", requireContext().getString(R.string.filters_warning), requireContext().getString(R.string.icons_warning_info), 0, preference -> {
|
||||
requireContext().startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("https://vtosters.app/donate/")));
|
||||
return false;
|
||||
});
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
requireContext().getString(R.string.filters_warning),
|
||||
requireContext().getString(R.string.icons_warning_info),
|
||||
0,
|
||||
preference -> {
|
||||
requireContext().startActivity(
|
||||
new Intent(Intent.ACTION_VIEW)
|
||||
.setData(Uri.parse("https://vtosters.app/donate/"))
|
||||
);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
PreferenceFragmentUtils.addListPreference(getPreferenceScreen(), "msg_blur_radius", "disabled", requireContext().getString(R.string.filter_blur), AndroidUtils.getArray(R.array.filter_types), new String[]{
|
||||
"disabled", "low", "med", "high"
|
||||
});
|
||||
Arrays.stream(ImageEffects.values())
|
||||
.filter(imageEffects -> imageEffects.isFree() || hasVerification())
|
||||
.forEach(it -> {
|
||||
if (it.isList()) {
|
||||
var pref = PreferenceFragmentUtils.addListPreference(
|
||||
getPreferenceScreen(),
|
||||
it.toString(),
|
||||
"disabled",
|
||||
it.getTitle(),
|
||||
it.getEntries(),
|
||||
it.getEntryValues()
|
||||
);
|
||||
pref.setSummary(it.getSummary());
|
||||
pref.setOnPreferenceChangeListener((preference, o) -> {
|
||||
edit().putString(it.toString(), (String) o).apply();
|
||||
preference.setSummary(it.getSummary());
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
} else if (it.isSwitch()) {
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(
|
||||
getPreferenceScreen(),
|
||||
it.toString(),
|
||||
it.getTitle(),
|
||||
it.getSummary(),
|
||||
0,
|
||||
false,
|
||||
(preference, o) -> {
|
||||
edit().putBoolean(it.toString(), (Boolean) o).apply();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addListPreference(getPreferenceScreen(), "msg_dim", "off", requireContext().getString(R.string.filter_dim), AndroidUtils.getArray(R.array.filter_dim_types), new String[]{
|
||||
"off", "dim_black", "dim_white"
|
||||
});
|
||||
|
||||
|
||||
PreferenceFragmentUtils.addListPreference(getPreferenceScreen(), "msg_mosaic", "disabled", requireContext().getString(R.string.filter_mosaic), AndroidUtils.getArray(R.array.filter_types), new String[]{
|
||||
"disabled", "low", "med", "high"
|
||||
});
|
||||
|
||||
if (hasVerification()) {
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_monochrome", requireContext().getString(R.string.filter_monochrome), "", 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_monochrome", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_invert", requireContext().getString(R.string.filter_invert_colors), "", 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_invert", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_sepia", requireContext().getString(R.string.filter_sepia), "", 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_sepia", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_emboss", requireContext().getString(R.string.filter_emboss), requireContext().getString(R.string.filter_maybe_lag), 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_emboss", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_engrave", requireContext().getString(R.string.filter_engrave), requireContext().getString(R.string.filter_maybe_lag), 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_engrave", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_flea", requireContext().getString(R.string.filter_flea), "", 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_flea", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "msg_snow", requireContext().getString(R.string.filter_flea), "", 0, false, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("msg_snow", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(getPreferenceScreen(), "compresswp", requireContext().getString(R.string.compress_wallpaper_title), requireContext().getString(R.string.compress_wallpaper_summ), 0, true, (preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("compresswp", 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");
|
||||
|
||||
blur.setSummary(getRadiusSummary());
|
||||
dim.setSummary(getDimmingSummary());
|
||||
mosaic.setSummary(getMosaicSummary());
|
||||
|
||||
blur.setOnPreferenceChangeListener((preference, o) -> {
|
||||
edit().putString("msg_blur_radius", (String) o).apply();
|
||||
preference.setSummary(getRadiusSummary());
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
dim.setOnPreferenceChangeListener((preference, o) -> {
|
||||
edit().putString("msg_dim", (String) o).apply();
|
||||
preference.setSummary(getDimmingSummary());
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
|
||||
mosaic.setOnPreferenceChangeListener((preference, o) -> {
|
||||
edit().putString("msg_mosaic", (String) o).apply();
|
||||
preference.setSummary(getMosaicSummary());
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(
|
||||
getPreferenceScreen(),
|
||||
"compresswp",
|
||||
requireContext().getString(R.string.compress_wallpaper_title),
|
||||
requireContext().getString(R.string.compress_wallpaper_summ),
|
||||
0,
|
||||
true,
|
||||
(preference, o) -> {
|
||||
boolean value = (boolean) o;
|
||||
edit().putBoolean("compresswp", value).commit();
|
||||
requestUpdateWallpaper();
|
||||
mWPPreviewPref.redraw();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package ru.vtosters.lite.ui.wallpapers;
|
||||
|
||||
import static ru.vtosters.lite.ui.wallpapers.WallpapersHooks.getFilteredFile;
|
||||
import static ru.vtosters.lite.ui.wallpapers.WallpapersHooks.getWallpaperFile;
|
||||
import static ru.vtosters.lite.ui.wallpapers.WallpapersHooks.*;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
@@ -59,12 +58,8 @@ public class WallpaperPreferences extends Preference {
|
||||
}
|
||||
|
||||
private void requestBg() {
|
||||
final Drawable drawable = getFilteredFile();
|
||||
|
||||
if (drawable != null && getWallpaperFile() != null)
|
||||
mChatBackground.setImageDrawable(drawable);
|
||||
else
|
||||
mChatBackground.setImageDrawable(null);
|
||||
final Drawable drawable = getWallpaper();
|
||||
mChatBackground.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
|
||||
@@ -1,78 +1,97 @@
|
||||
package ru.vtosters.lite.ui.wallpapers;
|
||||
|
||||
import static com.vk.im.engine.h.im_bg_chat;
|
||||
import static ru.vtosters.lite.ui.wallpapers.ImageFilters.getFilteredDrawable;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.ThemesUtils;
|
||||
import vigo.sdk.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.vk.im.engine.h.im_bg_chat;
|
||||
import static ru.vtosters.lite.ui.wallpapers.ImageFilters.getFilteredDrawable;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
|
||||
public class WallpapersHooks {
|
||||
private static final boolean compress = getBoolValue("compresswp", true);
|
||||
private static File mWallpaperFile;
|
||||
// TODO: force compress by default not asking user about that?
|
||||
private static final Supplier<Boolean> compress = () -> getBoolValue("compresswp", true);
|
||||
private static final File originalWp = new File(getGlobalContext().getFilesDir(), "wallpaper.jpeg");
|
||||
private static final File compressedWp = new File(getGlobalContext().getFilesDir(), "compressedwp.jpeg");
|
||||
// TODO: cache to file?
|
||||
private static Drawable mWallpaper;
|
||||
private static boolean mUpdateWallpaperRequested = true;
|
||||
private static boolean mUpdateWallpaperFileRequested = true;
|
||||
|
||||
public static File getWallpaperFile() {
|
||||
if (mWallpaperFile == null) {
|
||||
mWallpaperFile = new File(getGlobalContext().getFilesDir(), "wallpaper.webp");
|
||||
// TODO: respect blur, when there is blur/mosaic effect applied these two can be even less, just HD (1280x720) for e.g.
|
||||
private static final int MAX_WP_WIDTH = 1080;
|
||||
private static final int MAX_WP_HEIGHT = 1920;
|
||||
|
||||
|
||||
public static void setBg(View view) {
|
||||
if (hasWallpapers()) {
|
||||
((ImageView) view).setImageDrawable(getWallpaper()); // set picture to background
|
||||
} else {
|
||||
view.setBackgroundColor(ThemesUtils.getColorFromAttr(im_bg_chat)); // set default bg color
|
||||
}
|
||||
|
||||
return mWallpaperFile;
|
||||
}
|
||||
|
||||
public static Drawable getFilteredFile() {
|
||||
File file = null;
|
||||
File wp = mWallpaperFile;
|
||||
String temp = getGlobalContext().getFilesDir() + File.separator + "filteredwp.webp";
|
||||
|
||||
if (wp != null && mUpdateWallpaperFileRequested) {
|
||||
try {
|
||||
file = new File(temp);
|
||||
file.createNewFile();
|
||||
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
((BitmapDrawable) getFilteredDrawable(Drawable.createFromPath(wp.getAbsolutePath()))).getBitmap().compress(Bitmap.CompressFormat.WEBP, (compress ? 80 : 95), bos);
|
||||
byte[] bitmapdata = bos.toByteArray();
|
||||
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
fos.write(bitmapdata);
|
||||
fos.flush();
|
||||
fos.close();
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.d("Wallpapers", e.getMessage());
|
||||
}
|
||||
|
||||
mUpdateWallpaperFileRequested = false;
|
||||
}
|
||||
|
||||
try {
|
||||
return Drawable.createFromPath(temp);
|
||||
} catch (Exception e) {
|
||||
if (file != null) {
|
||||
return Drawable.createFromPath(file.getAbsolutePath());
|
||||
} else {
|
||||
public static Drawable getWallpaper() {
|
||||
if (mWallpaper == null || mUpdateWallpaperRequested) {
|
||||
if (!originalWp.exists()) {
|
||||
return null;
|
||||
}
|
||||
Drawable drawable;
|
||||
if (compress.get()) {
|
||||
if (!compressedWp.exists() && !prepareCompressed()) {
|
||||
return null;
|
||||
}
|
||||
drawable = Drawable.createFromPath(compressedWp.getAbsolutePath());
|
||||
} else {
|
||||
drawable = Drawable.createFromPath(originalWp.getAbsolutePath());
|
||||
}
|
||||
|
||||
if (drawable == null) {
|
||||
return null;
|
||||
}
|
||||
mWallpaper = getFilteredDrawable(drawable);
|
||||
mUpdateWallpaperRequested = false;
|
||||
}
|
||||
|
||||
return mWallpaper;
|
||||
}
|
||||
|
||||
private static boolean prepareCompressed() {
|
||||
// TODO remove this check? with "compress" enabled it should be fine
|
||||
if (!eligibleWallpaperFile(originalWp)) {
|
||||
return false;
|
||||
}
|
||||
try (var f = new FileOutputStream(compressedWp)) {
|
||||
var bitmap = BitmapFactory.decodeFile(originalWp.getAbsolutePath());
|
||||
|
||||
if (bitmap.getHeight() > MAX_WP_HEIGHT || bitmap.getWidth() > MAX_WP_WIDTH) {
|
||||
bitmap = resize(bitmap, MAX_WP_WIDTH, MAX_WP_HEIGHT);
|
||||
}
|
||||
var drawable = new BitmapDrawable(null, bitmap);
|
||||
// TODO: remove duplication without changes when provided image already fits required params
|
||||
drawable.getBitmap().compress(Bitmap.CompressFormat.WEBP, 90, f);
|
||||
} catch (Exception e) {
|
||||
Log.d("Wallpapers", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static File getWallpaperFile() {
|
||||
return originalWp;
|
||||
}
|
||||
|
||||
private static Boolean eligibleWallpaperFile(File file) {
|
||||
@@ -85,94 +104,40 @@ public class WallpapersHooks {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setBg(View view) {
|
||||
if (hasWallpapers()) {
|
||||
((ImageView) view).setImageDrawable(getFilteredFile()); // set picture to background
|
||||
} else {
|
||||
view.setBackgroundColor(ThemesUtils.getColorFromAttr(im_bg_chat)); // set default bg color
|
||||
}
|
||||
}
|
||||
|
||||
public static String getWallpaperUrl() {
|
||||
var file = getWallpaperFile();
|
||||
|
||||
if (file.exists() && eligibleWallpaperFile(file)) {
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
return "default";
|
||||
}
|
||||
|
||||
public static boolean hasWallpapers() {
|
||||
return getWallpaper() != null;
|
||||
}
|
||||
|
||||
public static Drawable getWallpaper() {
|
||||
if (mWallpaper == null || mUpdateWallpaperRequested) {
|
||||
String url = getWallpaperUrl();
|
||||
|
||||
if (url.equals("default") || url.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Drawable drawable = Drawable.createFromPath(getWallpaperUrl());
|
||||
|
||||
if (drawable == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
mWallpaper = drawable;
|
||||
|
||||
mWallpaper = getFilteredDrawable(mWallpaper);
|
||||
|
||||
mUpdateWallpaperRequested = false;
|
||||
}
|
||||
|
||||
return mWallpaper;
|
||||
}
|
||||
|
||||
public static void requestUpdateWallpaper() {
|
||||
mUpdateWallpaperRequested = true;
|
||||
mUpdateWallpaperFileRequested = true;
|
||||
}
|
||||
|
||||
public static String getRadiusSummary() {
|
||||
String radius = getPreferences().getString("msg_blur_radius", "disabled");
|
||||
return switch (radius) {
|
||||
case "low" -> AndroidUtils.getString(R.string.wallpapers_low);
|
||||
case "med" -> AndroidUtils.getString(R.string.wallpapers_med);
|
||||
case "high" -> AndroidUtils.getString(R.string.wallpapers_high);
|
||||
default -> AndroidUtils.getString(R.string.wallpapers_disabled);
|
||||
};
|
||||
}
|
||||
|
||||
public static String getDimmingSummary() {
|
||||
String radius = getPreferences().getString("msg_dim", "disabled");
|
||||
return switch (radius) {
|
||||
case "dim_black" -> AndroidUtils.getString(R.string.wallpapers_dim_black);
|
||||
case "dim_white" -> AndroidUtils.getString(R.string.wallpapers_dim_white);
|
||||
default -> AndroidUtils.getString(R.string.wallpapers_disabled);
|
||||
};
|
||||
}
|
||||
|
||||
public static String getMosaicSummary() {
|
||||
String radius = getPreferences().getString("msg_mosaic", "disabled");
|
||||
return switch (radius) {
|
||||
case "low" -> AndroidUtils.getString(R.string.wallpapers_low);
|
||||
case "med" -> AndroidUtils.getString(R.string.wallpapers_med);
|
||||
case "high" -> AndroidUtils.getString(R.string.wallpapers_high);
|
||||
default -> AndroidUtils.getString(R.string.wallpapers_disabled);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static void removeWallpaper() {
|
||||
try {
|
||||
new File(getGlobalContext().getFilesDir(), "wallpaper.webp").delete();
|
||||
new File(getGlobalContext().getFilesDir(), "filteredwp.webp").delete();
|
||||
mWallpaperFile = null;
|
||||
mWallpaper = null;
|
||||
originalWp.delete();
|
||||
compressedWp.delete();
|
||||
} catch (Exception e) {
|
||||
Log.d("Wallpapers", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) {
|
||||
if (maxHeight > 0 && maxWidth > 0) {
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
float ratioBitmap = (float) width / (float) height;
|
||||
float ratioMax = (float) maxWidth / (float) maxHeight;
|
||||
|
||||
int finalWidth = maxWidth;
|
||||
int finalHeight = maxHeight;
|
||||
if (ratioMax > ratioBitmap) {
|
||||
finalWidth = (int) ((float) maxHeight * ratioBitmap);
|
||||
} else {
|
||||
finalHeight = (int) ((float) maxWidth / ratioBitmap);
|
||||
}
|
||||
image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user