From 7823d4f49f1d175d979b36781ef432cb4e74be6c Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Thu, 29 Jan 2026 12:37:21 -0400 Subject: [PATCH] Move UriGlideRenderer to lib:image-editor. --- .../securesms/mediasend/CameraXFragment.kt | 2 +- .../scribbles/ImageEditorFragment.java | 1 + .../securesms/util/BitmapUtil.java | 41 -------------- .../wallpaper/crop/WallpaperCropActivity.java | 3 +- .../org/signal/core/util/BitmapExtensions.kt | 36 +++++++++++++ gradle/verification-metadata.xml | 54 +++++++++++++++++++ lib/glide/build.gradle.kts | 2 +- lib/image-editor/build.gradle | 1 + .../core/renderers}/UriGlideRenderer.java | 11 ++-- 9 files changed, 103 insertions(+), 48 deletions(-) create mode 100644 core/util/src/main/java/org/signal/core/util/BitmapExtensions.kt rename {app/src/main/java/org/thoughtcrime/securesms/scribbles => lib/image-editor/src/main/java/org/signal/imageeditor/core/renderers}/UriGlideRenderer.java (97%) diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.kt index df1a799853..ac04465be2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.kt @@ -43,9 +43,9 @@ import org.signal.camera.CameraScreenEvents import org.signal.camera.CameraScreenViewModel import org.signal.camera.VideoCaptureResult import org.signal.camera.VideoOutput -import org.signal.camera.hud.StringResources import org.signal.camera.hud.StandardCameraHud import org.signal.camera.hud.StandardCameraHudEvents +import org.signal.camera.hud.StringResources import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.compose.ComposeFragment diff --git a/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java b/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java index aa45ce5683..439e5d8532 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java @@ -45,6 +45,7 @@ import org.signal.imageeditor.core.model.EditorModel; import org.signal.imageeditor.core.renderers.BezierDrawingRenderer; import org.signal.imageeditor.core.renderers.FaceBlurRenderer; import org.signal.imageeditor.core.renderers.MultiLineTextRenderer; +import org.signal.imageeditor.core.renderers.UriGlideRenderer; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.animation.ResizeAnimation; import org.thoughtcrime.securesms.attachments.AttachmentSaver; diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java index 8e0af616d4..d85dfd0807 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java @@ -174,47 +174,6 @@ public class BitmapUtil { } } - @WorkerThread - public static Bitmap createScaledBitmap(Context context, T model, int maxWidth, int maxHeight) - throws BitmapDecodingException - { - try { - return Glide.with(context.getApplicationContext()) - .asBitmap() - .load(model) - .centerInside() - .submit(maxWidth, maxHeight) - .get(); - } catch (InterruptedException | ExecutionException e) { - throw new BitmapDecodingException(e); - } - } - - @WorkerThread - public static Bitmap createScaledBitmap(Bitmap bitmap, int maxWidth, int maxHeight) { - if (bitmap.getWidth() <= maxWidth && bitmap.getHeight() <= maxHeight) { - return bitmap; - } - - if (maxWidth <= 0 || maxHeight <= 0) { - return bitmap; - } - - int newWidth = maxWidth; - int newHeight = maxHeight; - - float widthRatio = bitmap.getWidth() / (float) maxWidth; - float heightRatio = bitmap.getHeight() / (float) maxHeight; - - if (widthRatio > heightRatio) { - newHeight = (int) (bitmap.getHeight() / widthRatio); - } else { - newWidth = (int) (bitmap.getWidth() / heightRatio); - } - - return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true); - } - public static @NonNull CompressFormat getCompressFormatForContentType(@Nullable String contentType) { if (contentType == null) return CompressFormat.JPEG; diff --git a/app/src/main/java/org/thoughtcrime/securesms/wallpaper/crop/WallpaperCropActivity.java b/app/src/main/java/org/thoughtcrime/securesms/wallpaper/crop/WallpaperCropActivity.java index c07b9a1cf0..4446c4e53a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/wallpaper/crop/WallpaperCropActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/wallpaper/crop/WallpaperCropActivity.java @@ -21,7 +21,6 @@ import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; import androidx.lifecycle.ViewModelProvider; -import org.signal.core.ui.compose.SignalIcons; import org.signal.core.util.logging.Log; import org.signal.imageeditor.core.ImageEditorView; import org.signal.imageeditor.core.model.EditorElement; @@ -32,7 +31,7 @@ import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.components.ProgressCard; import org.thoughtcrime.securesms.conversation.colors.ColorizerView; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.scribbles.UriGlideRenderer; +import org.signal.imageeditor.core.renderers.UriGlideRenderer; import org.thoughtcrime.securesms.util.AsynchronousCallback; import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.Projection; diff --git a/core/util/src/main/java/org/signal/core/util/BitmapExtensions.kt b/core/util/src/main/java/org/signal/core/util/BitmapExtensions.kt new file mode 100644 index 0000000000..108d389b5c --- /dev/null +++ b/core/util/src/main/java/org/signal/core/util/BitmapExtensions.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2026 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.signal.core.util + +import android.graphics.Bitmap +import androidx.core.graphics.scale + +/** + * Creates a scaled bitmap with the given maximum dimensions while maintaining the original aspect ratio. + */ +fun Bitmap.scaleWithAspectRatio(maxWidth: Int, maxHeight: Int): Bitmap { + if (getWidth() <= maxWidth && getHeight() <= maxHeight) { + return this + } + + if (maxWidth <= 0 || maxHeight <= 0) { + return this + } + + var newWidth = maxWidth + var newHeight = maxHeight + + val widthRatio: Float = getWidth() / maxWidth.toFloat() + val heightRatio: Float = getHeight() / maxHeight.toFloat() + + if (widthRatio > heightRatio) { + newHeight = (getHeight() / widthRatio).toInt() + } else { + newWidth = (getWidth() / heightRatio).toInt() + } + + return scale(newWidth, newHeight) +} \ No newline at end of file diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 54b62c58c4..d0c6866b7e 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -50,6 +50,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + @@ -268,6 +276,9 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + @@ -1162,6 +1173,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + @@ -4155,6 +4171,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + @@ -4624,6 +4648,9 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + @@ -5049,6 +5076,9 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + @@ -5662,6 +5692,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + @@ -6179,6 +6217,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + @@ -6929,6 +6975,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + diff --git a/lib/glide/build.gradle.kts b/lib/glide/build.gradle.kts index 202cd4f079..ca0ddc5442 100644 --- a/lib/glide/build.gradle.kts +++ b/lib/glide/build.gradle.kts @@ -15,7 +15,7 @@ android { dependencies { implementation(project(":core:util")) - implementation(libs.glide.glide) + api(libs.glide.glide) ksp(libs.glide.ksp) implementation(platform(libs.androidx.compose.bom)) diff --git a/lib/image-editor/build.gradle b/lib/image-editor/build.gradle index 819497f4a5..a17097e63b 100644 --- a/lib/image-editor/build.gradle +++ b/lib/image-editor/build.gradle @@ -8,4 +8,5 @@ android { dependencies { implementation(project(":core:util")) + implementation(project(":lib:glide")) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/scribbles/UriGlideRenderer.java b/lib/image-editor/src/main/java/org/signal/imageeditor/core/renderers/UriGlideRenderer.java similarity index 97% rename from app/src/main/java/org/thoughtcrime/securesms/scribbles/UriGlideRenderer.java rename to lib/image-editor/src/main/java/org/signal/imageeditor/core/renderers/UriGlideRenderer.java index 0ed7eb6b8f..37cec499ab 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/scribbles/UriGlideRenderer.java +++ b/lib/image-editor/src/main/java/org/signal/imageeditor/core/renderers/UriGlideRenderer.java @@ -1,4 +1,9 @@ -package org.thoughtcrime.securesms.scribbles; +/* + * Copyright 2026 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.signal.imageeditor.core.renderers; import android.content.Context; import android.graphics.Bitmap; @@ -25,6 +30,7 @@ import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.transition.Transition; +import org.signal.core.util.BitmapExtensionsKt; import org.signal.core.util.logging.Log; import org.signal.imageeditor.core.Bounds; import org.signal.imageeditor.core.Renderer; @@ -33,7 +39,6 @@ import org.signal.imageeditor.core.SelectableRenderer; import org.signal.imageeditor.core.model.EditorElement; import org.signal.imageeditor.core.model.EditorModel; import org.signal.glide.decryptableuri.DecryptableUri; -import org.thoughtcrime.securesms.util.BitmapUtil; import java.util.concurrent.ExecutionException; @@ -256,7 +261,7 @@ public final class UriGlideRenderer implements SelectableRenderer { private static @NonNull Bitmap blur(Bitmap bitmap, Context context, float blurRadius) { Point previewSize = scaleKeepingAspectRatio(new Point(bitmap.getWidth(), bitmap.getHeight()), PREVIEW_DIMENSION_LIMIT); Point blurSize = scaleKeepingAspectRatio(new Point(previewSize.x / 2, previewSize.y / 2 ), MAX_BLUR_DIMENSION); - Bitmap small = BitmapUtil.createScaledBitmap(bitmap, blurSize.x, blurSize.y); + Bitmap small = BitmapExtensionsKt.scaleWithAspectRatio(bitmap, blurSize.x, blurSize.y); Log.d(TAG, "Bitmap: " + bitmap.getWidth() + "x" + bitmap.getHeight() + ", Blur: " + blurSize.x + "x" + blurSize.y);