diff --git a/.gitignore b/.gitignore
index aa724b7..de5e7c2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
*.iml
.gradle
/local.properties
+.idea
/.idea/caches
/.idea/libraries
/.idea/modules.xml
diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml
new file mode 100644
index 0000000..4a53bee
--- /dev/null
+++ b/.idea/AndroidProjectSystem.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/appInsightsSettings.xml b/.idea/appInsightsSettings.xml
index 38888e6..3f1cc79 100644
--- a/.idea/appInsightsSettings.xml
+++ b/.idea/appInsightsSettings.xml
@@ -8,14 +8,9 @@
-
-
-
-
-
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 7643783..7f70f7e 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -1,5 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index b589d56..b86273d 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
new file mode 100644
index 0000000..06fe69e
--- /dev/null
+++ b/.idea/deploymentTargetSelector.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 2ad3255..33b0310 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -4,8 +4,7 @@
-
-
+
@@ -15,7 +14,6 @@
-
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 44ca2d9..7b9fbe3 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -1,6 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -9,6 +33,9 @@
+
+
+
@@ -33,6 +60,9 @@
+
+
+
diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml
new file mode 100644
index 0000000..5f2a36a
--- /dev/null
+++ b/.idea/material_theme_project_new.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 8978d23..74dd639 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,7 @@
+
-
+
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..16660f1
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.kotlin/errors/errors-1752874289006.log b/.kotlin/errors/errors-1752874289006.log
new file mode 100644
index 0000000..85999fa
--- /dev/null
+++ b/.kotlin/errors/errors-1752874289006.log
@@ -0,0 +1,50 @@
+kotlin version: 2.2.0
+error message: androidx.compose.compiler.plugins.kotlin.IncompatibleComposeRuntimeVersionException: The Compose Compiler requires the Compose Runtime to be on the class path, but none could be found. The compose compiler plugin you are using (version 1.5.14) expects a minimum runtime version of 1.0.0.
+ at androidx.compose.compiler.plugins.kotlin.VersionChecker.noRuntimeOnClasspathError(VersionChecker.kt:221)
+ at androidx.compose.compiler.plugins.kotlin.VersionChecker.check(VersionChecker.kt:193)
+ at androidx.compose.compiler.plugins.kotlin.ComposeIrGenerationExtension.generate(ComposeIrGenerationExtension.kt:62)
+ at org.jetbrains.kotlin.fir.pipeline.ConvertToIrKt.applyIrGenerationExtensions(convertToIr.kt:468)
+ at org.jetbrains.kotlin.fir.pipeline.Fir2IrPipeline.runActualizationPipeline(convertToIr.kt:245)
+ at org.jetbrains.kotlin.fir.pipeline.Fir2IrPipeline.convertToIrAndActualize(convertToIr.kt:128)
+ at org.jetbrains.kotlin.fir.pipeline.ConvertToIrKt.convertToIrAndActualize(convertToIr.kt:97)
+ at org.jetbrains.kotlin.fir.pipeline.ConvertToIrKt.convertToIrAndActualize$default(convertToIr.kt:72)
+ at org.jetbrains.kotlin.cli.jvm.compiler.legacy.pipeline.JvmCompilerPipelineKt.convertToIrAndActualizeForJvm(jvmCompilerPipeline.kt:109)
+ at org.jetbrains.kotlin.cli.pipeline.jvm.JvmFir2IrPipelinePhase.executePhase(JvmFir2IrPipelinePhase.kt:26)
+ at org.jetbrains.kotlin.cli.pipeline.jvm.JvmFir2IrPipelinePhase.executePhase(JvmFir2IrPipelinePhase.kt:17)
+ at org.jetbrains.kotlin.cli.pipeline.PipelinePhase.phaseBody(PipelinePhase.kt:68)
+ at org.jetbrains.kotlin.cli.pipeline.PipelinePhase.phaseBody(PipelinePhase.kt:58)
+ at org.jetbrains.kotlin.config.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:102)
+ at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:22)
+ at org.jetbrains.kotlin.config.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:53)
+ at org.jetbrains.kotlin.cli.pipeline.AbstractCliPipeline.runPhasedPipeline(AbstractCliPipeline.kt:109)
+ at org.jetbrains.kotlin.cli.pipeline.AbstractCliPipeline.execute(AbstractCliPipeline.kt:68)
+ at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecutePhased(K2JVMCompiler.kt:78)
+ at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecutePhased(K2JVMCompiler.kt:44)
+ at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:90)
+ at org.jetbrains.kotlin.cli.common.CLICompiler.exec(CLICompiler.kt:352)
+ at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunnerBase.runCompiler(IncrementalJvmCompilerRunnerBase.kt:175)
+ at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunnerBase.runCompiler(IncrementalJvmCompilerRunnerBase.kt:38)
+ at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:504)
+ at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:421)
+ at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:306)
+ at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:133)
+ at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:679)
+ at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:93)
+ at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1806)
+ at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
+ at java.base/java.lang.reflect.Method.invoke(Unknown Source)
+ at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
+ at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
+ at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
+ at java.base/java.security.AccessController.doPrivileged(Unknown Source)
+ at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
+ at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
+ at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
+ at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
+ at java.base/java.security.AccessController.doPrivileged(Unknown Source)
+ at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
+ at java.base/java.lang.Thread.run(Unknown Source)
+
+
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 554fe85..10ba00d 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,17 +1,19 @@
-@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.kotlinAndroid)
+ alias(libs.plugins.compose.compiler)
}
android {
namespace = "dev.eren.removebg"
- compileSdk = 33
+ compileSdk = 36
defaultConfig {
applicationId = "dev.eren.removebg"
minSdk = 24
- targetSdk = 33
+ targetSdk = 36
versionCode = 1
versionName = "1.0"
@@ -31,11 +33,14 @@ android {
}
}
compileOptions {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
}
- kotlinOptions {
- jvmTarget = "1.8"
+ kotlin {
+ compilerOptions {
+ jvmTarget.set(JvmTarget.JVM_17)
+ javaParameters.set(true)
+ }
}
buildFeatures {
compose = true
@@ -60,6 +65,8 @@ dependencies {
implementation(libs.ui.graphics)
implementation(libs.ui.tooling.preview)
implementation(libs.material3)
+ implementation(libs.androidx.runtime)
+
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.espresso.core)
diff --git a/app/src/main/java/dev/eren/removebg/MainActivity.kt b/app/src/main/java/dev/eren/removebg/MainActivity.kt
index acee99d..358ef4a 100644
--- a/app/src/main/java/dev/eren/removebg/MainActivity.kt
+++ b/app/src/main/java/dev/eren/removebg/MainActivity.kt
@@ -1,51 +1,66 @@
package dev.eren.removebg
import android.graphics.Bitmap
+import android.graphics.ImageDecoder
+import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
-import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
+import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
-import androidx.compose.material3.Button
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Add
+import androidx.compose.material.icons.filled.Favorite
+import androidx.compose.material.icons.filled.FavoriteBorder
+import androidx.compose.material3.AssistChip
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.FloatingActionButton
+import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
+import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
import dev.eren.removebg.ui.theme.RemovebgTheme
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onStart
-
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
+ enableEdgeToEdge()
super.onCreate(savedInstanceState)
setContent {
RemovebgTheme {
@@ -65,87 +80,128 @@ class MainActivity : ComponentActivity() {
fun RemoveBackground() {
val context = LocalContext.current
- val outputImage: MutableState = remember {
- mutableStateOf(null)
- }
+ val outputImage = remember { mutableStateOf(null) }
+ val inputImage = remember { mutableStateOf(null) }
+ var loading by remember { mutableStateOf(false) }
+ var isReal by remember { mutableStateOf(false) }
- val inputImage: MutableState = remember {
- mutableStateOf(null)
- }
+ val remover = remember { RemoveBg(context = context) }
val pickMedia = rememberLauncherForActivityResult(
- contract = ActivityResultContracts.PickVisualMedia(),
- onResult = { uri ->
- if (uri != null) {
- inputImage.value =
- MediaStore.Images.Media.getBitmap(context.contentResolver, uri)
- } else {
- Log.d("PhotoPicker", "No media selected")
+ contract = ActivityResultContracts.PickVisualMedia()
+ ) { uri ->
+ uri?.let {
+ try {
+ val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ // For Android P (API 28) and above, use ImageDecoder
+ ImageDecoder.decodeBitmap(ImageDecoder.createSource(context.contentResolver, it))
+ } else {
+ // For older Android versions, use the deprecated getBitmap (as a fallback)
+ @Suppress("DEPRECATION")
+ MediaStore.Images.Media.getBitmap(context.contentResolver, it)
+ }
+ inputImage.value = bitmap
+ } catch (e: Exception) {
+ e.printStackTrace()
}
- })
-
- var loading: Boolean by remember {
- mutableStateOf(false)
- }
-
- var isReal: Boolean by remember {
- mutableStateOf(false)
- }
-
- val remover = remember {
- RemoveBg(context = context)
+ }
}
- LaunchedEffect(key1 = inputImage.value) {
+ // Trigger removal when inputImage changes
+ LaunchedEffect(inputImage.value) {
inputImage.value?.let { image ->
remover.clearBackground(image)
- .onStart {
- loading = true
- }
- .onCompletion {
- loading = false
- }.collect { output ->
- outputImage.value = output
+ .onStart { loading = true }
+ .onCompletion { loading = false }
+ .collect { result ->
+ outputImage.value = result
}
}
}
- Scaffold { paddingValues ->
- Box(modifier = Modifier.background(Color.White)) {
- Row(
- horizontalArrangement = Arrangement.End,
- modifier = Modifier
- .padding(paddingValues)
- .fillMaxWidth()
- ) {
- Button(onClick = {
+ Scaffold(
+ floatingActionButton = {
+ FloatingActionButton(
+ onClick = {
pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
- }) {
- Text(text = "Open Gallery")
- }
+ },
+ containerColor = MaterialTheme.colorScheme.primary
+ ) {
+ Icon(Icons.Default.Add, contentDescription = "Pick Image")
}
+ }
+ ) { paddingValues ->
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(paddingValues)
+ .background(MaterialTheme.colorScheme.background)
+ ) {
Column(
modifier = Modifier
.fillMaxSize()
- .padding(paddingValues),
+ .padding(24.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
- if (loading) {
- CircularProgressIndicator()
- }
- if (outputImage.value != null && inputImage.value != null) {
- Image(
- bitmap = if (!isReal) outputImage.value!!.asImageBitmap() else inputImage.value!!.asImageBitmap(),
- contentDescription = "",
- Modifier
- .fillMaxWidth()
- .clickable {
- isReal = !isReal
+ when {
+ loading -> {
+ CircularProgressIndicator()
+ Spacer(modifier = Modifier.height(16.dp))
+ Text("Removing background...", style = MaterialTheme.typography.bodyMedium)
+ }
+
+ inputImage.value != null && outputImage.value != null -> {
+ Card(
+ modifier = Modifier
+ .fillMaxWidth()
+ .aspectRatio(3f / 4f)
+ .clickable { isReal = !isReal },
+ shape = RoundedCornerShape(16.dp),
+ elevation = CardDefaults.cardElevation(8.dp)
+ ) {
+ AnimatedContent(
+ targetState = isReal,
+ label = "ImageSwitcher"
+ ) { showOriginal ->
+ val bitmap =
+ if (showOriginal) inputImage.value else outputImage.value
+ bitmap?.let {
+ Image(
+ bitmap = it.asImageBitmap(),
+ contentDescription = "Image",
+ contentScale = ContentScale.Crop,
+ modifier = Modifier.fillMaxSize()
+ )
+ }
}
- )
+ }
+
+ Spacer(modifier = Modifier.height(16.dp))
+
+ AssistChip(
+ onClick = { isReal = !isReal },
+ label = {
+ Text(if (isReal) "Showing: Original" else "Showing: Background Removed")
+ },
+ leadingIcon = {
+ Icon(
+ imageVector = if (isReal) Icons.Default.FavoriteBorder else Icons.Default.Favorite,
+ contentDescription = null
+ )
+ }
+ )
+ }
+
+ else -> {
+ Text(
+ text = "Pick an image to remove background",
+ style = MaterialTheme.typography.bodyLarge,
+ textAlign = TextAlign.Center
+ )
+ }
}
}
}
}
-}
\ No newline at end of file
+}
diff --git a/build.gradle.kts b/build.gradle.kts
index cf521f9..53d136f 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,8 +1,8 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
-@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
plugins {
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.kotlinAndroid) apply false
alias(libs.plugins.androidLibrary) apply false
+ alias(libs.plugins.compose.compiler) apply false
}
true // Needed to make the Suppress annotation work for the plugins block
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index dcf5043..fc939a5 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,21 +1,21 @@
[versions]
-agp = "8.3.0-alpha06"
-androidx-lifecycle-runtime-ktx = "2.6.1"
-kotlin = "1.8.10"
-core-ktx = "1.9.0"
+agp = "8.11.1"
+kotlin = "2.2.0"
+core-ktx = "1.16.0"
junit = "4.13.2"
-androidx-test-ext-junit = "1.1.5"
-espresso-core = "3.5.1"
-kotlinx-coroutines-core = "1.7.3"
-lifecycle-runtime-ktx = "2.6.2"
-activity-compose = "1.7.2"
-compose-bom = "2023.03.00"
-appcompat = "1.6.1"
-material = "1.9.0"
-pytorch_android_torchvision_lite = "1.13.1"
+androidx-test-ext-junit = "1.2.1"
+espresso-core = "3.6.1"
+kotlinx-coroutines-core = "1.10.2"
+lifecycle-runtime-ktx = "2.9.2"
+activity-compose = "1.10.1"
+compose-bom = "2025.07.00"
+appcompat = "1.7.1"
+material = "1.12.0"
+pytorch_android_torchvision_lite = "2.1.0"
+runtime = "1.8.3"
[libraries]
-androidx-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle-runtime-ktx" }
+androidx-runtime = { module = "androidx.compose.runtime:runtime", version.ref = "runtime" }
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" }
@@ -40,4 +40,5 @@ material = { group = "com.google.android.material", name = "material", version.r
androidApplication = { id = "com.android.application", version.ref = "agp" }
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
androidLibrary = { id = "com.android.library", version.ref = "agp" }
+compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index ffec72b..d78330f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Sep 25 10:16:23 TRT 2023
+#Sat Jul 19 02:21:53 IST 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-rc-2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/removebg/build.gradle.kts b/removebg/build.gradle.kts
index ca9951e..a3c8d20 100644
--- a/removebg/build.gradle.kts
+++ b/removebg/build.gradle.kts
@@ -1,13 +1,15 @@
-@Suppress("DSL_SCOPE_VIOLATION")
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+
plugins {
alias(libs.plugins.androidLibrary)
alias(libs.plugins.kotlinAndroid)
`maven-publish`
+ alias(libs.plugins.compose.compiler)
}
android {
namespace = "dev.eren.removebg"
- compileSdk = 33
+ compileSdk = 36
defaultConfig {
minSdk = 24
@@ -26,11 +28,14 @@ android {
}
}
compileOptions {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
}
- kotlinOptions {
- jvmTarget = "1.8"
+ kotlin {
+ compilerOptions {
+ jvmTarget.set(JvmTarget.JVM_17)
+ javaParameters.set(true)
+ }
}
publishing {
@@ -44,9 +49,10 @@ android {
dependencies {
implementation(libs.core.ktx)
implementation(libs.kotlinx.coroutines.core)
- implementation(libs.androidx.lifecycle.runtime)
+ implementation(libs.lifecycle.runtime.ktx)
implementation(libs.pytorch.android.lite)
implementation(libs.pytorch.android.torchvision.lite)
+ implementation(libs.androidx.runtime)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit)
diff --git a/removebg/src/main/java/dev/eren/removebg/RemoveBg.kt b/removebg/src/main/java/dev/eren/removebg/RemoveBg.kt
index 60b5363..fb8fd10 100644
--- a/removebg/src/main/java/dev/eren/removebg/RemoveBg.kt
+++ b/removebg/src/main/java/dev/eren/removebg/RemoveBg.kt
@@ -6,6 +6,8 @@ import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
+import androidx.core.graphics.createBitmap
+import androidx.core.graphics.scale
import dev.eren.removebg.common.ModelTypes
import dev.eren.removebg.utils.FileUtils.assetFilePath
import dev.eren.removebg.utils.NetUtils
@@ -22,7 +24,7 @@ import org.pytorch.torchvision.TensorImageUtils
/**
* Created by erenalpaslan on 18.08.2023
*/
-class RemoveBg(context: Context): Remover {
+class RemoveBg(context: Context) : Remover {
private var module: Module = LiteModuleLoader.load(
assetFilePath(
@@ -36,7 +38,7 @@ class RemoveBg(context: Context): Remover {
init {
maskPaint.isAntiAlias = true
maskPaint.style = Paint.Style.FILL
- maskPaint.setXfermode(PorterDuffXfermode(PorterDuff.Mode.DST_IN))
+ maskPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
}
override fun clearBackground(image: Bitmap): Flow = flow {
@@ -45,7 +47,7 @@ class RemoveBg(context: Context): Remover {
}.flowOn(Dispatchers.IO)
override fun getMaskedImage(input: Bitmap, mask: Bitmap): Bitmap {
- val result = Bitmap.createBitmap(mask.width, mask.height, Bitmap.Config.ARGB_8888)
+ val result = createBitmap(mask.width, mask.height)
val mCanvas = Canvas(result)
mCanvas.drawBitmap(input, 0f, 0f, null)
@@ -57,7 +59,7 @@ class RemoveBg(context: Context): Remover {
val width = input.width
val height = input.height
- val scaledBitmap = Bitmap.createScaledBitmap(input, size, size, true)
+ val scaledBitmap = input.scale(size, size)
val inputTensor = TensorImageUtils.bitmapToFloat32Tensor(
scaledBitmap,
TensorImageUtils.TORCHVISION_NORM_MEAN_RGB,
@@ -65,9 +67,7 @@ class RemoveBg(context: Context): Remover {
)
val outputTensor = module.forward(IValue.from(inputTensor)).toTuple()
val arr = outputTensor[0].toTensor().dataAsFloatArray
- val scaledMask = NetUtils.convertArrayToBitmap(arr, size, size)?.let {
- Bitmap.createScaledBitmap(it, width, height, true)
- }
+ val scaledMask = NetUtils.convertArrayToBitmap(arr, size, size)?.scale(width, height)
return scaledMask?.let { getMaskedImage(input, it) }
}
diff --git a/removebg/src/main/java/dev/eren/removebg/utils/NetUtils.kt b/removebg/src/main/java/dev/eren/removebg/utils/NetUtils.kt
index ee74afd..72a67ca 100644
--- a/removebg/src/main/java/dev/eren/removebg/utils/NetUtils.kt
+++ b/removebg/src/main/java/dev/eren/removebg/utils/NetUtils.kt
@@ -1,16 +1,18 @@
package dev.eren.removebg.utils
import android.graphics.Bitmap
+import androidx.core.graphics.createBitmap
+import androidx.core.graphics.set
/**
* Created by erenalpaslan on 18.08.2023
*/
object NetUtils {
fun convertArrayToBitmap(arr: FloatArray, width: Int, height: Int): Bitmap? {
- val grayToneImage = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
+ val grayToneImage = createBitmap(width, height)
for (i in 0 until width) {
for (j in 0 until height) {
- grayToneImage.setPixel(j, i, (arr[i * height + j] * 255f).toInt() shl 24)
+ grayToneImage[j, i] = (arr[i * height + j] * 255f).toInt() shl 24
}
}
return grayToneImage