Refactor auto background remover

This commit is contained in:
T8RIN
2025-03-20 03:22:44 +03:00
parent 46610abd7d
commit 4992c0454d
6 changed files with 144 additions and 108 deletions

View File

@ -1,6 +1,6 @@
/*
* ImageToolbox is an image editor for android
* Copyright (c) 2024 T8RIN (Malik Mukhametzyanov)
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,21 +18,19 @@
package ru.tech.imageresizershrinker.feature.erase_background.data
import android.graphics.Bitmap
import android.os.Build
import androidx.annotation.RequiresApi
import ru.tech.imageresizershrinker.feature.erase_background.domain.AutoBackgroundRemoverBackend
import javax.inject.Inject
@RequiresApi(api = Build.VERSION_CODES.N)
internal object MlKitSubjectBackgroundRemover {
internal class AndroidAutoBackgroundRemoverBackend @Inject constructor() :
AutoBackgroundRemoverBackend<Bitmap> {
/**
* Process the image to get buffer and image height and width
* @param bitmap Bitmap which you want to remove background.
* @param onFinish listener for success and failure callback.
**/
@RequiresApi(api = Build.VERSION_CODES.N)
fun removeBackground(
bitmap: Bitmap,
override fun performBackgroundRemove(
image: Bitmap,
onFinish: (Result<Bitmap>) -> Unit
) = onFinish(Result.failure(UnsupportedOperationException("FOSS")))
) {
onFinish(
Result.failure(UnsupportedOperationException("FOSS"))
)
}
}

View File

@ -1,41 +0,0 @@
/*
* ImageToolbox is an image editor for android
* Copyright (c) 2024 T8RIN (Malik Mukhametzyanov)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* You should have received a copy of the Apache License
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package ru.tech.imageresizershrinker.feature.erase_background.data
import android.graphics.Bitmap
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
internal object MlKitBackgroundRemover {
/**
* Process the image to get buffer and image height and width
* @param bitmap Bitmap which you want to remove background.
* @param onFinish listener for success and failure callback.
**/
fun removeBackground(
bitmap: Bitmap,
scope: CoroutineScope,
onFinish: suspend (Result<Bitmap>) -> Unit
) {
scope.launch {
onFinish(Result.failure(UnsupportedOperationException("FOSS")))
}
}
}

View File

@ -17,21 +17,19 @@
package ru.tech.imageresizershrinker.feature.erase_background.data
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.os.Build
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import kotlinx.coroutines.CoroutineScope
import com.t8rin.logger.makeLog
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import ru.tech.imageresizershrinker.core.domain.dispatchers.DispatchersHolder
import ru.tech.imageresizershrinker.feature.erase_background.domain.AutoBackgroundRemover
import ru.tech.imageresizershrinker.feature.erase_background.domain.AutoBackgroundRemoverBackend
import javax.inject.Inject
internal class AndroidAutoBackgroundRemover @Inject constructor(
dispatchersHolder: DispatchersHolder
) : DispatchersHolder by dispatchersHolder, AutoBackgroundRemover<Bitmap> {
private val backend: AutoBackgroundRemoverBackend<Bitmap>
) : AutoBackgroundRemover<Bitmap> {
override suspend fun trimEmptyParts(
image: Bitmap
@ -83,54 +81,16 @@ internal class AndroidAutoBackgroundRemover @Inject constructor(
image: Bitmap,
onSuccess: (Bitmap) -> Unit,
onFailure: (Throwable) -> Unit
) {
runCatching {
autoRemove(
type = ApiType.Best,
image = image,
onFinish = {
it.onSuccess(onSuccess).onFailure(onFailure)
) = backend.performBackgroundRemove(
image = image,
onFinish = { result ->
result
.onSuccess(onSuccess)
.onFailure {
it.makeLog()
onFailure(it)
}
)
}.onFailure(onFailure)
}
private fun autoRemove(
type: ApiType,
image: Bitmap,
onFinish: (Result<Bitmap>) -> Unit
) {
val old = {
MlKitBackgroundRemover.removeBackground(
bitmap = image,
scope = CoroutineScope(defaultDispatcher),
onFinish = onFinish
)
}
val new = {
@SuppressLint("NewApi")
MlKitSubjectBackgroundRemover.removeBackground(
bitmap = image,
onFinish = {
if (it.isFailure) {
old()
} else onFinish(it)
}
)
}
when (type) {
ApiType.Old -> old()
ApiType.New -> new()
}
}
private enum class ApiType {
Old, New;
companion object {
val Best: ApiType get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) New else Old
}
}
)
}

View File

@ -23,7 +23,9 @@ import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import ru.tech.imageresizershrinker.feature.erase_background.data.AndroidAutoBackgroundRemover
import ru.tech.imageresizershrinker.feature.erase_background.data.AndroidAutoBackgroundRemoverBackend
import ru.tech.imageresizershrinker.feature.erase_background.domain.AutoBackgroundRemover
import ru.tech.imageresizershrinker.feature.erase_background.domain.AutoBackgroundRemoverBackend
import javax.inject.Singleton
@Module
@ -36,4 +38,10 @@ internal interface EraseBackgroundModule {
remover: AndroidAutoBackgroundRemover
): AutoBackgroundRemover<Bitmap>
@Binds
@Singleton
fun provideBackend(
backend: AndroidAutoBackgroundRemoverBackend
): AutoBackgroundRemoverBackend<Bitmap>
}

View File

@ -0,0 +1,27 @@
/*
* ImageToolbox is an image editor for android
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* You should have received a copy of the Apache License
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package ru.tech.imageresizershrinker.feature.erase_background.domain
internal interface AutoBackgroundRemoverBackend<I> {
fun performBackgroundRemove(
image: I,
onFinish: (Result<I>) -> Unit
)
}

View File

@ -0,0 +1,84 @@
/*
* ImageToolbox is an image editor for android
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* You should have received a copy of the Apache License
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package ru.tech.imageresizershrinker.feature.erase_background.data
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.os.Build
import kotlinx.coroutines.CoroutineScope
import ru.tech.imageresizershrinker.core.domain.dispatchers.DispatchersHolder
import ru.tech.imageresizershrinker.feature.erase_background.domain.AutoBackgroundRemoverBackend
import javax.inject.Inject
internal class AndroidAutoBackgroundRemoverBackend @Inject constructor(
dispatchersHolder: DispatchersHolder
) : AutoBackgroundRemoverBackend<Bitmap>, DispatchersHolder by dispatchersHolder {
override fun performBackgroundRemove(
image: Bitmap,
onFinish: (Result<Bitmap>) -> Unit
) {
runCatching {
autoRemove(
image = image,
onFinish = onFinish
)
}.onFailure {
onFinish(Result.failure(it))
}
}
@SuppressLint("NewApi")
private fun autoRemove(
type: ApiType = ApiType.Best,
image: Bitmap,
onFinish: (Result<Bitmap>) -> Unit
) {
val old = {
MlKitBackgroundRemover.removeBackground(
bitmap = image,
scope = CoroutineScope(defaultDispatcher),
onFinish = onFinish
)
}
val new = {
MlKitSubjectBackgroundRemover.removeBackground(
bitmap = image,
onFinish = {
if (it.isFailure) {
old()
} else onFinish(it)
}
)
}
when (type) {
ApiType.Old -> old()
ApiType.New -> new()
}
}
private enum class ApiType {
Old, New;
companion object {
val Best: ApiType get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) New else Old
}
}
}