mirror of
https://github.com/T8RIN/ImageToolbox.git
synced 2025-05-17 13:35:58 +08:00
kotlin 2.0.21, coil3
This commit is contained in:
@ -17,7 +17,7 @@
|
||||
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
@ -28,6 +28,7 @@ plugins {
|
||||
id("com.google.gms.google-services")
|
||||
id("com.google.firebase.crashlytics")
|
||||
id("com.mikepenz.aboutlibraries.plugin")
|
||||
id("org.jetbrains.kotlin.plugin.compose")
|
||||
}
|
||||
|
||||
android {
|
||||
@ -38,14 +39,14 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
|
||||
applicationId = "ru.tech.imageresizershrinker"
|
||||
minSdk = libs.versions.androidMinSdk.get().toIntOrNull()
|
||||
targetSdk = libs.versions.androidTargetSdk.get().toIntOrNull()
|
||||
versionCode = libs.versions.versionCode.get().toIntOrNull()
|
||||
versionName = System.getenv("VERSION_NAME") ?: libs.versions.versionName.get()
|
||||
|
||||
archivesName.set("image-toolbox-$versionName${if (isFoss) "-foss" else ""}")
|
||||
setProperty("archivesBaseName", "image-toolbox-$versionName${if (isFoss) "-foss" else ""}")
|
||||
}
|
||||
|
||||
androidResources {
|
||||
@ -92,12 +93,10 @@ android {
|
||||
isCoreLibraryDesugaringEnabled = true
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = javaVersion.toString()
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.fromTarget(libs.versions.jvmTarget.get()))
|
||||
}
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
|
@ -17,6 +17,9 @@
|
||||
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
|
||||
|
||||
plugins {
|
||||
id("com.android.test")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
@ -39,8 +42,10 @@ android {
|
||||
targetCompatibility = JavaVersion.toVersion(libs.versions.jvmTarget.get())
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = libs.versions.jvmTarget.get()
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.fromTarget(libs.versions.jvmTarget.get()))
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
@ -15,6 +15,7 @@
|
||||
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||
*/
|
||||
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
@ -30,8 +31,8 @@ java {
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
tasks.withType<KotlinCompile>().configureEach {
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_17.toString()
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_17)
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,6 +40,7 @@ dependencies {
|
||||
compileOnly(libs.agp.gradle)
|
||||
compileOnly(libs.kotlin.gradle)
|
||||
compileOnly(libs.detekt.gradle)
|
||||
compileOnly(libs.compose.compiler.gradle)
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
|
@ -17,35 +17,19 @@
|
||||
|
||||
import com.android.build.api.dsl.LibraryExtension
|
||||
import com.t8rin.imagetoolbox.configureCompose
|
||||
import com.t8rin.imagetoolbox.libs
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.gradle.kotlin.dsl.dependencies
|
||||
import org.gradle.kotlin.dsl.withType
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.gradle.kotlin.dsl.apply
|
||||
import org.gradle.kotlin.dsl.getByType
|
||||
|
||||
@Suppress("UNUSED")
|
||||
class ImageToolboxLibraryComposePlugin : Plugin<Project> {
|
||||
override fun apply(target: Project) {
|
||||
with(target) {
|
||||
dependencies {
|
||||
"implementation"(libs.findLibrary("androidx.material3").get())
|
||||
"implementation"(libs.findLibrary("androidx.material3.window.sizeclass").get())
|
||||
"implementation"(libs.findLibrary("androidx.material").get())
|
||||
"implementation"(libs.findLibrary("androidx.material.icons.extended").get())
|
||||
}
|
||||
apply(plugin = "com.android.library")
|
||||
apply(plugin = "org.jetbrains.kotlin.plugin.compose")
|
||||
|
||||
extensions.configure<LibraryExtension> {
|
||||
configureCompose(this)
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
compilerOptions.freeCompilerArgs.addAll(
|
||||
"-P",
|
||||
"plugin:androidx.compose.compiler.plugins.kotlin:strongSkipping=true",
|
||||
)
|
||||
}
|
||||
configureCompose(extensions.getByType<LibraryExtension>())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,11 @@ package com.t8rin.imagetoolbox
|
||||
|
||||
import com.android.build.api.dsl.CommonExtension
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.assign
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.gradle.kotlin.dsl.dependencies
|
||||
import org.jetbrains.kotlin.compose.compiler.gradle.ComposeCompilerGradlePluginExtension
|
||||
import org.jetbrains.kotlin.compose.compiler.gradle.ComposeFeatureFlag
|
||||
|
||||
internal fun Project.configureCompose(
|
||||
commonExtension: CommonExtension<*, *, *, *, *, *>,
|
||||
@ -28,15 +33,20 @@ internal fun Project.configureCompose(
|
||||
compose = true
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = libs.findVersion("compose.compiler").get().toString()
|
||||
}
|
||||
kotlinOptions {
|
||||
freeCompilerArgs += listOf(
|
||||
"-P",
|
||||
"plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
|
||||
"${project.rootProject.projectDir.absolutePath}/compose_compiler_config.conf"
|
||||
)
|
||||
dependencies {
|
||||
"implementation"(libs.findLibrary("androidx.material3").get())
|
||||
"implementation"(libs.findLibrary("androidx.material3.window.sizeclass").get())
|
||||
"implementation"(libs.findLibrary("androidx.material").get())
|
||||
"implementation"(libs.findLibrary("androidx.material.icons.extended").get())
|
||||
}
|
||||
}
|
||||
|
||||
extensions.configure<ComposeCompilerGradlePluginExtension> {
|
||||
featureFlags = setOf(
|
||||
ComposeFeatureFlag.OptimizeNonSkippingGroups
|
||||
)
|
||||
|
||||
stabilityConfigurationFile =
|
||||
rootProject.layout.projectDirectory.file("compose_compiler_config.conf")
|
||||
}
|
||||
}
|
||||
|
@ -20,11 +20,14 @@ package com.t8rin.imagetoolbox
|
||||
import com.android.build.api.dsl.CommonExtension
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.plugins.ExtensionAware
|
||||
import org.gradle.kotlin.dsl.assign
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.gradle.kotlin.dsl.dependencies
|
||||
import org.gradle.kotlin.dsl.withType
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.gradle.kotlin.dsl.provideDelegate
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
|
||||
|
||||
internal fun Project.configureKotlinAndroid(
|
||||
commonExtension: CommonExtension<*, *, *, *, *, *>,
|
||||
@ -72,26 +75,9 @@ internal fun Project.configureKotlinAndroid(
|
||||
disable += "UsingMaterialAndMaterial3Libraries"
|
||||
disable += "ModifierParameter"
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
freeCompilerArgs += listOf(
|
||||
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
|
||||
"-opt-in=androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi",
|
||||
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
||||
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
|
||||
"-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi",
|
||||
"-opt-in=androidx.compose.ui.unit.ExperimentalUnitApi",
|
||||
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||
)
|
||||
jvmTarget = javaVersion.toString()
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile>().configureEach {
|
||||
kotlinOptions {
|
||||
jvmTarget = javaVersion.toString()
|
||||
}
|
||||
}
|
||||
configureKotlin<KotlinAndroidProjectExtension>()
|
||||
|
||||
dependencies {
|
||||
add("coreLibraryDesugaring", libs.findLibrary("desugaring").get())
|
||||
@ -103,6 +89,28 @@ val Project.javaVersion: JavaVersion
|
||||
libs.findVersion("jvmTarget").get().toString()
|
||||
)
|
||||
|
||||
fun CommonExtension<*, *, *, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) {
|
||||
(this as ExtensionAware).extensions.configure("kotlinOptions", block)
|
||||
}
|
||||
/**
|
||||
* Configure base Kotlin options
|
||||
*/
|
||||
private inline fun <reified T : KotlinTopLevelExtension> Project.configureKotlin() = configure<T> {
|
||||
// Treat all Kotlin warnings as errors (disabled by default)
|
||||
// Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties
|
||||
val warningsAsErrors: String? by project
|
||||
when (this) {
|
||||
is KotlinAndroidProjectExtension -> compilerOptions
|
||||
is KotlinJvmProjectExtension -> compilerOptions
|
||||
else -> TODO("Unsupported project extension $this ${T::class}")
|
||||
}.apply {
|
||||
jvmTarget = JvmTarget.fromTarget(libs.findVersion("jvmTarget").get().toString())
|
||||
allWarningsAsErrors = warningsAsErrors.toBoolean()
|
||||
freeCompilerArgs.addAll(
|
||||
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
|
||||
"-opt-in=androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi",
|
||||
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
||||
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
|
||||
"-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi",
|
||||
"-opt-in=androidx.compose.ui.unit.ExperimentalUnitApi",
|
||||
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||
)
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ buildscript {
|
||||
classpath(libs.baselineprofile.gradle)
|
||||
classpath(libs.detekt.gradle)
|
||||
classpath(libs.aboutlibraries.gradle)
|
||||
classpath(libs.compose.compiler.gradle)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,10 +24,13 @@ android.namespace = "ru.tech.imageresizershrinker.core.data"
|
||||
|
||||
dependencies {
|
||||
api(libs.coil)
|
||||
api(libs.coilCompose)
|
||||
api(libs.coilNetwork)
|
||||
api(libs.ktor)
|
||||
implementation(libs.coilGif)
|
||||
implementation(libs.coilSvg)
|
||||
|
||||
implementation(libs.androidx.compose.ui.graphics)
|
||||
|
||||
api(libs.datastore.preferences.android)
|
||||
|
||||
implementation(libs.avif.coder.coil) {
|
||||
|
@ -1,177 +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.core.data.coil
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import coil.ImageLoader
|
||||
import coil.decode.DecodeResult
|
||||
import coil.decode.Decoder
|
||||
import coil.fetch.SourceResult
|
||||
import coil.request.Options
|
||||
import coil.size.Scale
|
||||
import coil.size.Size
|
||||
import coil.size.pxOrElse
|
||||
import com.awxkee.jxlcoder.JxlAnimatedImage
|
||||
import com.awxkee.jxlcoder.JxlResizeFilter
|
||||
import com.awxkee.jxlcoder.PreferredColorConfig
|
||||
import com.awxkee.jxlcoder.ScaleMode
|
||||
import com.awxkee.jxlcoder.animation.AnimatedDrawable
|
||||
import com.awxkee.jxlcoder.animation.JxlAnimatedStore
|
||||
import kotlinx.coroutines.runInterruptible
|
||||
import okio.BufferedSource
|
||||
import okio.ByteString.Companion.toByteString
|
||||
|
||||
internal class AnimatedJxlDecoderCoil2(
|
||||
private val source: SourceResult,
|
||||
private val options: Options,
|
||||
private val context: Context,
|
||||
private val preheatFrames: Int,
|
||||
private val exceptionLogger: ((Exception) -> Unit)? = null,
|
||||
) : Decoder {
|
||||
|
||||
override suspend fun decode(): DecodeResult? = runInterruptible {
|
||||
try {
|
||||
// ColorSpace is preferred to be ignored due to lib is trying to handle all color profile by itself
|
||||
val sourceData = source.source.source().readByteArray()
|
||||
|
||||
var mPreferredColorConfig: PreferredColorConfig = when (options.config) {
|
||||
Bitmap.Config.ALPHA_8 -> PreferredColorConfig.RGBA_8888
|
||||
Bitmap.Config.RGB_565 -> if (options.allowRgb565) PreferredColorConfig.RGB_565 else PreferredColorConfig.DEFAULT
|
||||
Bitmap.Config.ARGB_8888 -> PreferredColorConfig.RGBA_8888
|
||||
else -> PreferredColorConfig.DEFAULT
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && options.config == Bitmap.Config.RGBA_F16) {
|
||||
mPreferredColorConfig = PreferredColorConfig.RGBA_F16
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && options.config == Bitmap.Config.HARDWARE) {
|
||||
mPreferredColorConfig = PreferredColorConfig.HARDWARE
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && options.config == Bitmap.Config.RGBA_1010102) {
|
||||
mPreferredColorConfig = PreferredColorConfig.RGBA_1010102
|
||||
}
|
||||
|
||||
if (options.size == Size.ORIGINAL) {
|
||||
val originalImage = JxlAnimatedImage(
|
||||
byteArray = sourceData,
|
||||
preferredColorConfig = mPreferredColorConfig
|
||||
)
|
||||
return@runInterruptible DecodeResult(
|
||||
drawable = originalImage.drawable(),
|
||||
isSampled = false
|
||||
)
|
||||
}
|
||||
|
||||
val dstWidth = options.size.width.pxOrElse { 0 }
|
||||
val dstHeight = options.size.height.pxOrElse { 0 }
|
||||
val scaleMode = when (options.scale) {
|
||||
Scale.FILL -> ScaleMode.FILL
|
||||
Scale.FIT -> ScaleMode.FIT
|
||||
}
|
||||
|
||||
val originalImage = JxlAnimatedImage(
|
||||
byteArray = sourceData,
|
||||
preferredColorConfig = mPreferredColorConfig,
|
||||
scaleMode = scaleMode,
|
||||
jxlResizeFilter = JxlResizeFilter.BILINEAR
|
||||
)
|
||||
|
||||
DecodeResult(
|
||||
drawable = originalImage.drawable(
|
||||
dstWidth = dstWidth,
|
||||
dstHeight = dstHeight
|
||||
),
|
||||
isSampled = true
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
exceptionLogger?.invoke(e)
|
||||
return@runInterruptible null
|
||||
}
|
||||
}
|
||||
|
||||
private fun JxlAnimatedImage.drawable(
|
||||
dstWidth: Int = 0,
|
||||
dstHeight: Int = 0
|
||||
): Drawable = if (numberOfFrames > 1) {
|
||||
AnimatedDrawable(
|
||||
frameStore = JxlAnimatedStore(
|
||||
jxlAnimatedImage = this,
|
||||
targetWidth = dstWidth,
|
||||
targetHeight = dstHeight
|
||||
),
|
||||
preheatFrames = preheatFrames,
|
||||
firstFrameAsPlaceholder = true
|
||||
)
|
||||
} else {
|
||||
BitmapDrawable(
|
||||
context.resources,
|
||||
getFrame(
|
||||
frame = 0,
|
||||
scaleWidth = dstWidth,
|
||||
scaleHeight = dstHeight
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
class Factory(
|
||||
private val context: Context,
|
||||
private val preheatFrames: Int = 6,
|
||||
private val exceptionLogger: ((Exception) -> Unit)? = null,
|
||||
) : Decoder.Factory {
|
||||
override fun create(
|
||||
result: SourceResult,
|
||||
options: Options,
|
||||
imageLoader: ImageLoader,
|
||||
) = if (isJXL(result.source.source())) {
|
||||
AnimatedJxlDecoderCoil2(
|
||||
source = result,
|
||||
options = options,
|
||||
context = context,
|
||||
preheatFrames = preheatFrames,
|
||||
exceptionLogger = exceptionLogger,
|
||||
)
|
||||
} else null
|
||||
|
||||
companion object {
|
||||
private val MAGIC_1 = byteArrayOf(0xFF.toByte(), 0x0A).toByteString()
|
||||
private val MAGIC_2 = byteArrayOf(
|
||||
0x0.toByte(),
|
||||
0x0.toByte(),
|
||||
0x0.toByte(),
|
||||
0x0C.toByte(),
|
||||
0x4A,
|
||||
0x58,
|
||||
0x4C,
|
||||
0x20,
|
||||
0x0D,
|
||||
0x0A,
|
||||
0x87.toByte(),
|
||||
0x0A
|
||||
).toByteString()
|
||||
|
||||
private fun isJXL(source: BufferedSource): Boolean {
|
||||
return source.rangeEquals(0, MAGIC_1) || source.rangeEquals(
|
||||
0,
|
||||
MAGIC_2
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,128 +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.core.data.coil
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.os.Build
|
||||
import coil.ImageLoader
|
||||
import coil.decode.DecodeResult
|
||||
import coil.decode.Decoder
|
||||
import coil.fetch.SourceResult
|
||||
import coil.request.Options
|
||||
import coil.size.Scale
|
||||
import coil.size.pxOrElse
|
||||
import com.radzivon.bartoshyk.avif.coder.HeifCoder
|
||||
import com.radzivon.bartoshyk.avif.coder.PreferredColorConfig
|
||||
import com.radzivon.bartoshyk.avif.coder.ScaleMode
|
||||
import kotlinx.coroutines.runInterruptible
|
||||
import okio.ByteString.Companion.encodeUtf8
|
||||
|
||||
internal class HeifDecoderCoil2(
|
||||
private val source: SourceResult,
|
||||
private val options: Options,
|
||||
private val exceptionLogger: ((Exception) -> Unit)? = null,
|
||||
) : Decoder {
|
||||
|
||||
private val coder = HeifCoder()
|
||||
|
||||
override suspend fun decode(): DecodeResult? = runInterruptible {
|
||||
try {
|
||||
// ColorSpace is preferred to be ignored due to lib is trying to handle all color profile by itself
|
||||
val sourceData = source.source.source().readByteArray()
|
||||
|
||||
var mPreferredColorConfig: PreferredColorConfig = when (options.config) {
|
||||
Bitmap.Config.ALPHA_8 -> PreferredColorConfig.RGBA_8888
|
||||
Bitmap.Config.RGB_565 -> if (options.allowRgb565) PreferredColorConfig.RGB_565 else PreferredColorConfig.DEFAULT
|
||||
Bitmap.Config.ARGB_8888 -> PreferredColorConfig.RGBA_8888
|
||||
else -> PreferredColorConfig.DEFAULT
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && options.config == Bitmap.Config.RGBA_F16) {
|
||||
mPreferredColorConfig = PreferredColorConfig.RGBA_F16
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && options.config == Bitmap.Config.HARDWARE) {
|
||||
mPreferredColorConfig = PreferredColorConfig.HARDWARE
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && options.config == Bitmap.Config.RGBA_1010102) {
|
||||
mPreferredColorConfig = PreferredColorConfig.RGBA_1010102
|
||||
}
|
||||
|
||||
if (options.size == coil.size.Size.ORIGINAL) {
|
||||
val originalImage =
|
||||
coder.decode(
|
||||
sourceData,
|
||||
preferredColorConfig = mPreferredColorConfig
|
||||
)
|
||||
return@runInterruptible DecodeResult(
|
||||
BitmapDrawable(
|
||||
options.context.resources,
|
||||
originalImage
|
||||
), false
|
||||
)
|
||||
}
|
||||
|
||||
val dstWidth = options.size.width.pxOrElse { 0 }
|
||||
val dstHeight = options.size.height.pxOrElse { 0 }
|
||||
val scaleMode = when (options.scale) {
|
||||
Scale.FILL -> ScaleMode.FILL
|
||||
Scale.FIT -> ScaleMode.FIT
|
||||
}
|
||||
|
||||
val originalImage =
|
||||
coder.decodeSampled(
|
||||
sourceData,
|
||||
dstWidth,
|
||||
dstHeight,
|
||||
preferredColorConfig = mPreferredColorConfig,
|
||||
scaleMode,
|
||||
)
|
||||
return@runInterruptible DecodeResult(
|
||||
BitmapDrawable(
|
||||
options.context.resources,
|
||||
originalImage
|
||||
), true
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
exceptionLogger?.invoke(e)
|
||||
return@runInterruptible null
|
||||
}
|
||||
}
|
||||
|
||||
class Factory : Decoder.Factory {
|
||||
override fun create(
|
||||
result: SourceResult,
|
||||
options: Options,
|
||||
imageLoader: ImageLoader
|
||||
): Decoder? {
|
||||
return if (AVAILABLE_BRANDS.any {
|
||||
result.source.source().rangeEquals(4, it)
|
||||
}) HeifDecoderCoil2(result, options) else null
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val MIF = "ftypmif1".encodeUtf8()
|
||||
private val MSF = "ftypmsf1".encodeUtf8()
|
||||
private val HEIC = "ftypheic".encodeUtf8()
|
||||
private val HEIX = "ftypheix".encodeUtf8()
|
||||
private val HEVC = "ftyphevc".encodeUtf8()
|
||||
private val HEVX = "ftyphevx".encodeUtf8()
|
||||
private val AVIF = "ftypavif".encodeUtf8()
|
||||
private val AVIS = "ftypavis".encodeUtf8()
|
||||
|
||||
private val AVAILABLE_BRANDS = listOf(MIF, MSF, HEIC, HEIX, HEVC, HEVX, AVIF, AVIS)
|
||||
}
|
||||
}
|
||||
}
|
@ -17,8 +17,9 @@
|
||||
|
||||
package ru.tech.imageresizershrinker.core.data.coil
|
||||
|
||||
import coil.intercept.Interceptor
|
||||
import coil.request.ImageResult
|
||||
import coil3.intercept.Interceptor
|
||||
import coil3.request.ImageResult
|
||||
import coil3.request.transformations
|
||||
import com.t8rin.logger.makeLog
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -28,7 +29,7 @@ internal class TimeMeasureInterceptor @Inject constructor() : Interceptor {
|
||||
chain: Interceptor.Chain
|
||||
): ImageResult {
|
||||
val time = System.currentTimeMillis()
|
||||
val result = chain.proceed(chain.request)
|
||||
val result = chain.proceed()
|
||||
val endTime = System.currentTimeMillis()
|
||||
|
||||
val delta = endTime - time
|
||||
|
@ -19,16 +19,20 @@ package ru.tech.imageresizershrinker.core.data.di
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import coil.Coil
|
||||
import coil.ComponentRegistry
|
||||
import coil.ImageLoader
|
||||
import coil.decode.GifDecoder
|
||||
import coil.decode.ImageDecoderDecoder
|
||||
import coil.decode.SvgDecoder
|
||||
import coil.imageLoader
|
||||
import coil.util.DebugLogger
|
||||
import coil.util.Logger
|
||||
import coil3.ComponentRegistry
|
||||
import coil3.ImageLoader
|
||||
import coil3.SingletonImageLoader
|
||||
import coil3.annotation.DelicateCoilApi
|
||||
import coil3.gif.AnimatedImageDecoder
|
||||
import coil3.gif.GifDecoder
|
||||
import coil3.imageLoader
|
||||
import coil3.request.allowHardware
|
||||
import coil3.svg.SvgDecoder
|
||||
import coil3.util.DebugLogger
|
||||
import coil3.util.Logger
|
||||
import com.awxkee.jxlcoder.coil.AnimatedJxlDecoder
|
||||
import com.gemalto.jp2.coil.Jpeg2000Decoder
|
||||
import com.github.awxkee.avifcoil.decoder.HeifDecoder
|
||||
import com.t8rin.awebp.coil.AnimatedWebPDecoder
|
||||
import com.t8rin.djvu_coder.coil.DjvuDecoder
|
||||
import com.t8rin.psd.coil.PsdDecoder
|
||||
@ -40,8 +44,6 @@ import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import oupson.apng.coil.AnimatedPngDecoder
|
||||
import ru.tech.imageresizershrinker.core.data.coil.AnimatedJxlDecoderCoil2
|
||||
import ru.tech.imageresizershrinker.core.data.coil.HeifDecoderCoil2
|
||||
import ru.tech.imageresizershrinker.core.data.coil.TimeMeasureInterceptor
|
||||
import ru.tech.imageresizershrinker.core.domain.dispatchers.DispatchersHolder
|
||||
import ru.tech.imageresizershrinker.core.resources.BuildConfig
|
||||
@ -50,6 +52,7 @@ import ru.tech.imageresizershrinker.core.resources.BuildConfig
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object ImageLoaderModule {
|
||||
|
||||
@OptIn(DelicateCoilApi::class)
|
||||
@Provides
|
||||
fun provideImageLoader(
|
||||
@ApplicationContext context: Context,
|
||||
@ -58,13 +61,13 @@ internal object ImageLoaderModule {
|
||||
dispatchersHolder: DispatchersHolder
|
||||
): ImageLoader = context.imageLoader.newBuilder()
|
||||
.components(componentRegistry)
|
||||
.decoderDispatcher(dispatchersHolder.decodingDispatcher)
|
||||
.fetcherDispatcher(dispatchersHolder.ioDispatcher)
|
||||
.transformationDispatcher(dispatchersHolder.defaultDispatcher)
|
||||
.coroutineContext(dispatchersHolder.defaultDispatcher)
|
||||
.decoderCoroutineContext(dispatchersHolder.decodingDispatcher)
|
||||
.fetcherCoroutineContext(dispatchersHolder.ioDispatcher)
|
||||
.allowHardware(false)
|
||||
.logger(logger)
|
||||
.build()
|
||||
.also(Coil::setImageLoader)
|
||||
.also(SingletonImageLoader::setUnsafe)
|
||||
|
||||
@Provides
|
||||
fun provideCoilLogger(): Logger? = if (BuildConfig.DEBUG) DebugLogger()
|
||||
@ -72,21 +75,20 @@ internal object ImageLoaderModule {
|
||||
|
||||
@Provides
|
||||
fun provideComponentRegistry(
|
||||
@ApplicationContext context: Context,
|
||||
interceptor: TimeMeasureInterceptor
|
||||
): ComponentRegistry = ComponentRegistry.Builder()
|
||||
.apply {
|
||||
add(AnimatedPngDecoder.Factory())
|
||||
if (Build.VERSION.SDK_INT >= 28) add(ImageDecoderDecoder.Factory())
|
||||
if (Build.VERSION.SDK_INT >= 28) add(AnimatedImageDecoder.Factory())
|
||||
else {
|
||||
add(GifDecoder.Factory())
|
||||
add(AnimatedWebPDecoder.Factory())
|
||||
}
|
||||
add(SvgDecoder.Factory())
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
add(HeifDecoderCoil2.Factory())
|
||||
add(HeifDecoder.Factory())
|
||||
}
|
||||
add(AnimatedJxlDecoderCoil2.Factory(context))
|
||||
add(AnimatedJxlDecoder.Factory())
|
||||
add(Jpeg2000Decoder.Factory())
|
||||
add(TiffDecoder.Factory())
|
||||
add(QoiDecoder.Factory())
|
||||
|
@ -26,15 +26,16 @@ import android.provider.MediaStore
|
||||
import android.webkit.MimeTypeMap
|
||||
import androidx.core.net.toUri
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import coil.ImageLoader
|
||||
import coil.request.ImageRequest
|
||||
import coil.size.Size
|
||||
import coil3.ImageLoader
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.transformations
|
||||
import coil3.size.Size
|
||||
import coil3.toBitmap
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.withContext
|
||||
import ru.tech.imageresizershrinker.core.data.utils.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.data.utils.toCoil
|
||||
import ru.tech.imageresizershrinker.core.domain.dispatchers.DispatchersHolder
|
||||
import ru.tech.imageresizershrinker.core.domain.image.ImageGetter
|
||||
@ -106,7 +107,7 @@ internal class AndroidImageGetter @Inject constructor(
|
||||
if (originalSize) size(Size.ORIGINAL)
|
||||
}
|
||||
.build()
|
||||
).drawable?.toBitmap()
|
||||
).image?.toBitmap()
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
@ -127,7 +128,7 @@ internal class AndroidImageGetter @Inject constructor(
|
||||
)
|
||||
}
|
||||
.build()
|
||||
).drawable?.toBitmap()
|
||||
).image?.toBitmap()
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
@ -146,7 +147,7 @@ internal class AndroidImageGetter @Inject constructor(
|
||||
} ?: size(Size.ORIGINAL)
|
||||
}
|
||||
.build()
|
||||
).drawable?.toBitmap()
|
||||
).image?.toBitmap()
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
@ -167,7 +168,7 @@ internal class AndroidImageGetter @Inject constructor(
|
||||
.build()
|
||||
|
||||
runCatching {
|
||||
imageLoader.execute(request).drawable?.toBitmap()?.let { bitmap ->
|
||||
imageLoader.execute(request).image?.toBitmap()?.let { bitmap ->
|
||||
val newUri = uri.toUri().tryGetLocation(context)
|
||||
val fd = context.contentResolver.openFileDescriptor(newUri, "r")
|
||||
val exif = fd?.fileDescriptor?.let { ExifInterface(it) }
|
||||
@ -205,7 +206,7 @@ internal class AndroidImageGetter @Inject constructor(
|
||||
.build()
|
||||
|
||||
runCatching {
|
||||
imageLoader.execute(request).drawable?.toBitmap()
|
||||
imageLoader.execute(request).image?.toBitmap()
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,8 @@
|
||||
package ru.tech.imageresizershrinker.core.data.image
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.core.graphics.BitmapCompat
|
||||
import androidx.core.graphics.applyCanvas
|
||||
import com.awxkee.aire.Aire
|
||||
@ -234,7 +233,7 @@ internal class AndroidImageScaler @Inject constructor(
|
||||
).apply {
|
||||
setHasAlpha(true)
|
||||
}.applyCanvas {
|
||||
drawColor(Color.Transparent.toArgb(), PorterDuff.Mode.CLEAR)
|
||||
drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
|
||||
canvasColor?.let {
|
||||
drawColor(it)
|
||||
} ?: blurredBitmap?.let {
|
||||
@ -320,7 +319,7 @@ internal class AndroidImageScaler @Inject constructor(
|
||||
).apply {
|
||||
setHasAlpha(true)
|
||||
}.applyCanvas {
|
||||
drawColor(Color.Transparent.toArgb(), PorterDuff.Mode.CLEAR)
|
||||
drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
|
||||
canvasColor?.let {
|
||||
drawColor(it)
|
||||
} ?: blurredBitmap?.let {
|
||||
|
@ -20,12 +20,13 @@ package ru.tech.imageresizershrinker.core.data.image
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Matrix
|
||||
import coil.ImageLoader
|
||||
import coil.request.ImageRequest
|
||||
import coil.size.Size
|
||||
import coil3.ImageLoader
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.transformations
|
||||
import coil3.size.Size
|
||||
import coil3.toBitmap
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.withContext
|
||||
import ru.tech.imageresizershrinker.core.data.utils.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.data.utils.toCoil
|
||||
import ru.tech.imageresizershrinker.core.domain.dispatchers.DispatchersHolder
|
||||
import ru.tech.imageresizershrinker.core.domain.image.ImageTransformer
|
||||
@ -68,7 +69,7 @@ internal class AndroidImageTransformer @Inject constructor(
|
||||
}
|
||||
.build()
|
||||
|
||||
return@withContext imageLoader.execute(request).drawable?.toBitmap()
|
||||
return@withContext imageLoader.execute(request).image?.toBitmap()
|
||||
}
|
||||
|
||||
override suspend fun transform(
|
||||
@ -89,7 +90,7 @@ internal class AndroidImageTransformer @Inject constructor(
|
||||
.size(size.width, size.height)
|
||||
.build()
|
||||
|
||||
return@withContext imageLoader.execute(request).drawable?.toBitmap()
|
||||
return@withContext imageLoader.execute(request).image?.toBitmap()
|
||||
}
|
||||
|
||||
override suspend fun applyPresetBy(
|
||||
@ -105,7 +106,7 @@ internal class AndroidImageTransformer @Inject constructor(
|
||||
.data(it)
|
||||
.size(Size.ORIGINAL)
|
||||
.build()
|
||||
).drawable?.run { intrinsicWidth sizeTo intrinsicHeight }
|
||||
).image?.run { width sizeTo height }
|
||||
} ?: IntegerSize(image.width, image.height)
|
||||
|
||||
val rotated = abs(currentInfo.rotationDegrees) % 180 != 0f
|
||||
|
@ -19,7 +19,6 @@ package ru.tech.imageresizershrinker.core.data.image.utils
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.ui.graphics.BlendMode
|
||||
import ru.tech.imageresizershrinker.core.domain.image.model.BlendingMode
|
||||
import android.graphics.BlendMode as AndroidBlendMode
|
||||
import android.graphics.PorterDuff.Mode as PorterDuffMode
|
||||
@ -52,7 +51,7 @@ fun BlendingMode.toPorterDuffMode(): PorterDuffMode = when (this) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the compose [BlendMode] to the underlying Android platform [AndroidBlendMode]
|
||||
* Convert the domain [BlendingMode] to the underlying Android platform [AndroidBlendMode]
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
fun BlendingMode.toAndroidBlendMode(): AndroidBlendMode = when (this) {
|
||||
|
@ -20,7 +20,6 @@ package ru.tech.imageresizershrinker.core.data.utils
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
@ -45,8 +44,6 @@ fun Bitmap.toSoftware(): Bitmap = copy(getSuitableConfig(this), false) ?: this
|
||||
|
||||
val Bitmap.aspectRatio: Float get() = width / height.toFloat()
|
||||
|
||||
val ImageBitmap.aspectRatio: Float get() = width / height.toFloat()
|
||||
|
||||
val Drawable.aspectRatio: Float get() = intrinsicWidth / intrinsicHeight.toFloat()
|
||||
|
||||
val Bitmap.safeAspectRatio: Float
|
||||
@ -57,11 +54,6 @@ val Bitmap.safeAspectRatio: Float
|
||||
val Bitmap.safeConfig: Bitmap.Config
|
||||
get() = config ?: getSuitableConfig(this)
|
||||
|
||||
val ImageBitmap.safeAspectRatio: Float
|
||||
get() = aspectRatio
|
||||
.coerceAtLeast(0.005f)
|
||||
.coerceAtMost(1000f)
|
||||
|
||||
val Drawable.safeAspectRatio: Float
|
||||
get() = aspectRatio
|
||||
.coerceAtLeast(0.005f)
|
||||
|
@ -18,11 +18,11 @@
|
||||
package ru.tech.imageresizershrinker.core.data.utils
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import coil.size.Size
|
||||
import coil.size.pxOrElse
|
||||
import coil3.size.Size
|
||||
import coil3.size.pxOrElse
|
||||
import ru.tech.imageresizershrinker.core.domain.model.IntegerSize
|
||||
import ru.tech.imageresizershrinker.core.domain.transformation.Transformation
|
||||
import coil.transform.Transformation as CoilTransformation
|
||||
import coil3.transform.Transformation as CoilTransformation
|
||||
|
||||
fun Size.asDomain(): IntegerSize = if (this == Size.ORIGINAL) IntegerSize.Undefined
|
||||
else IntegerSize(width.pxOrElse { 1 }, height.pxOrElse { 1 })
|
||||
@ -30,7 +30,7 @@ else IntegerSize(width.pxOrElse { 1 }, height.pxOrElse { 1 })
|
||||
fun IntegerSize.asCoil(): Size = if (this == IntegerSize.Undefined) Size.ORIGINAL
|
||||
else Size(width, height)
|
||||
|
||||
fun Transformation<Bitmap>.toCoil(): CoilTransformation = object : CoilTransformation {
|
||||
fun Transformation<Bitmap>.toCoil(): CoilTransformation = object : CoilTransformation() {
|
||||
private val instance = this@toCoil
|
||||
|
||||
override fun toString(): String = instance::class.simpleName.toString()
|
||||
|
@ -115,7 +115,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.net.toUri
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import coil.transform.Transformation
|
||||
import coil3.transform.Transformation
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
|
@ -89,9 +89,12 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import coil.request.ImageRequest
|
||||
import coil.transform.Transformation
|
||||
import coil3.compose.rememberAsyncImagePainter
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.error
|
||||
import coil3.request.transformations
|
||||
import coil3.toBitmap
|
||||
import coil3.transform.Transformation
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.tech.imageresizershrinker.core.domain.model.FileModel
|
||||
import ru.tech.imageresizershrinker.core.domain.model.ImageModel
|
||||
@ -106,7 +109,6 @@ import ru.tech.imageresizershrinker.core.ui.theme.StrongBlack
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.White
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.isNetworkAvailable
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.toImageModel
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedAlertDialog
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
|
||||
@ -172,7 +174,7 @@ internal fun FilterSelectionItem(
|
||||
onSuccess = {
|
||||
loading = false
|
||||
scope.launch {
|
||||
isBitmapDark = calculateBrightnessEstimate(it.result.drawable.toBitmap()) < 110
|
||||
isBitmapDark = calculateBrightnessEstimate(it.result.image.toBitmap()) < 110
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -73,9 +73,11 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.min
|
||||
import androidx.compose.ui.unit.sp
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import coil.request.ImageRequest
|
||||
import coil.transform.Transformation
|
||||
import coil3.compose.rememberAsyncImagePainter
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.error
|
||||
import coil3.request.transformations
|
||||
import coil3.transform.Transformation
|
||||
import dev.shreyaspatil.capturable.capturable
|
||||
import dev.shreyaspatil.capturable.controller.rememberCaptureController
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -51,9 +51,12 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import coil.request.ImageRequest
|
||||
import coil.transform.Transformation
|
||||
import coil3.compose.rememberAsyncImagePainter
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.error
|
||||
import coil3.request.transformations
|
||||
import coil3.toBitmap
|
||||
import coil3.transform.Transformation
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.tech.imageresizershrinker.core.domain.model.ImageModel
|
||||
import ru.tech.imageresizershrinker.core.filters.domain.model.TemplateFilter
|
||||
@ -63,7 +66,6 @@ import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.StrongBlack
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.White
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.toImageModel
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.modifier.shimmer
|
||||
@ -108,7 +110,7 @@ internal fun TemplateFilterSelectionItem(
|
||||
onSuccess = {
|
||||
loading = false
|
||||
scope.launch {
|
||||
isBitmapDark = calculateBrightnessEstimate(it.result.drawable.toBitmap()) < 110
|
||||
isBitmapDark = calculateBrightnessEstimate(it.result.image.toBitmap()) < 110
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -49,6 +49,8 @@ dependencies {
|
||||
api(libs.coilCompose)
|
||||
api(libs.coilGif)
|
||||
api(libs.coilSvg)
|
||||
api(libs.coilNetwork)
|
||||
api(libs.ktor)
|
||||
|
||||
//Modules
|
||||
api(libs.toolbox.uCrop)
|
||||
@ -71,7 +73,7 @@ dependencies {
|
||||
|
||||
api(libs.reorderable)
|
||||
|
||||
api(libs.compose)
|
||||
api(libs.shadowGadgets)
|
||||
api(libs.shadowsPlus)
|
||||
|
||||
api(libs.kotlinx.collections.immutable)
|
||||
|
@ -18,8 +18,8 @@
|
||||
package ru.tech.imageresizershrinker.core.ui.transformation
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import coil.size.Size
|
||||
import coil.size.pxOrElse
|
||||
import coil3.size.Size
|
||||
import coil3.size.pxOrElse
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
@ -35,7 +35,7 @@ import ru.tech.imageresizershrinker.core.domain.model.IntegerSize
|
||||
import ru.tech.imageresizershrinker.core.domain.transformation.Transformation
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.asCoil
|
||||
import kotlin.math.roundToInt
|
||||
import coil.transform.Transformation as CoilTransformation
|
||||
import coil3.transform.Transformation as CoilTransformation
|
||||
|
||||
class ImageInfoTransformation @AssistedInject internal constructor(
|
||||
@Assisted private val imageInfo: ImageInfo,
|
||||
@ -45,7 +45,7 @@ class ImageInfoTransformation @AssistedInject internal constructor(
|
||||
private val imageScaler: ImageScaler<Bitmap>,
|
||||
private val imagePreviewCreator: ImagePreviewCreator<Bitmap>,
|
||||
private val shareProvider: ShareProvider<Bitmap>
|
||||
) : CoilTransformation, Transformation<Bitmap> {
|
||||
) : CoilTransformation(), Transformation<Bitmap> {
|
||||
|
||||
override val cacheKey: String
|
||||
get() = Triple(imageInfo, preset, transformations).hashCode().toString()
|
||||
|
@ -18,11 +18,11 @@
|
||||
package ru.tech.imageresizershrinker.core.ui.utils.helper
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import coil.size.Size
|
||||
import coil.size.pxOrElse
|
||||
import coil3.size.Size
|
||||
import coil3.size.pxOrElse
|
||||
import ru.tech.imageresizershrinker.core.domain.model.IntegerSize
|
||||
import ru.tech.imageresizershrinker.core.domain.transformation.Transformation
|
||||
import coil.transform.Transformation as CoilTransformation
|
||||
import coil3.transform.Transformation as CoilTransformation
|
||||
|
||||
fun Size.asDomain(): IntegerSize = if (this == Size.ORIGINAL) IntegerSize.Undefined
|
||||
else IntegerSize(width.pxOrElse { 1 }, height.pxOrElse { 1 })
|
||||
@ -30,7 +30,7 @@ else IntegerSize(width.pxOrElse { 1 }, height.pxOrElse { 1 })
|
||||
fun IntegerSize.asCoil(): Size = if (this == IntegerSize.Undefined) Size.ORIGINAL
|
||||
else Size(width, height)
|
||||
|
||||
fun Transformation<Bitmap>.toCoil(): CoilTransformation = object : CoilTransformation {
|
||||
fun Transformation<Bitmap>.toCoil(): CoilTransformation = object : CoilTransformation() {
|
||||
private val instance = this@toCoil
|
||||
|
||||
override fun toString(): String = instance::class.simpleName.toString()
|
||||
|
@ -18,6 +18,6 @@
|
||||
package ru.tech.imageresizershrinker.core.ui.utils.provider
|
||||
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import coil.ImageLoader
|
||||
import coil3.ImageLoader
|
||||
|
||||
val LocalImageLoader = compositionLocalOf<ImageLoader> { error("No ImageLoader provided") }
|
@ -39,13 +39,16 @@ import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.graphics.drawscope.DrawScope
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.core.graphics.drawable.toBitmapOrNull
|
||||
import coil.ImageLoader
|
||||
import coil.compose.AsyncImagePainter
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.compose.SubcomposeAsyncImageScope
|
||||
import coil.request.ImageRequest
|
||||
import coil.transform.Transformation
|
||||
import coil3.ImageLoader
|
||||
import coil3.compose.AsyncImagePainter
|
||||
import coil3.compose.SubcomposeAsyncImage
|
||||
import coil3.compose.SubcomposeAsyncImageScope
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.allowHardware
|
||||
import coil3.request.crossfade
|
||||
import coil3.request.transformations
|
||||
import coil3.toBitmap
|
||||
import coil3.transform.Transformation
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.withContext
|
||||
@ -155,7 +158,7 @@ fun Picture(
|
||||
onSuccess = {
|
||||
if (model is ImageRequest && Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && enableUltraHDRSupport) {
|
||||
activity.window.colorMode =
|
||||
if (it.result.drawable.toBitmapOrNull(400, 400)?.hasGainmap() == true) {
|
||||
if (it.result.image.toBitmap(400, 400).hasGainmap()) {
|
||||
ActivityInfo.COLOR_MODE_HDR
|
||||
} else ActivityInfo.COLOR_MODE_DEFAULT
|
||||
}
|
||||
|
@ -44,7 +44,9 @@ import androidx.compose.ui.layout.layout
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import coil.request.ImageRequest
|
||||
import coil3.asDrawable
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.crossfade
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.safeAspectRatio
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
|
||||
import kotlin.math.roundToInt
|
||||
@ -100,7 +102,7 @@ internal fun UrisCarousel(uris: List<Uri>) {
|
||||
.build()
|
||||
},
|
||||
onSuccess = {
|
||||
aspectRatio = it.result.drawable.safeAspectRatio
|
||||
aspectRatio = it.result.image.asDrawable(context.resources).safeAspectRatio
|
||||
},
|
||||
modifier = Modifier
|
||||
.animateContentSize()
|
||||
|
@ -46,8 +46,9 @@ import androidx.compose.ui.unit.Density
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import coil.request.ImageRequest
|
||||
import coil3.compose.rememberAsyncImagePainter
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.crossfade
|
||||
import ru.tech.imageresizershrinker.core.ui.shapes.CloverShape
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalImageLoader
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.modifier.shimmer
|
||||
|
@ -52,7 +52,7 @@ import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.transform.Transformation
|
||||
import coil3.transform.Transformation
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.notNullAnd
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
package ru.tech.imageresizershrinker.core.ui.widget.sheets
|
||||
|
||||
import android.content.res.Resources
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.scaleIn
|
||||
@ -50,7 +51,8 @@ import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.transform.Transformation
|
||||
import coil3.asDrawable
|
||||
import coil3.transform.Transformation
|
||||
import com.smarttoolfactory.colordetector.util.ColorUtil.roundToTwoDigits
|
||||
import net.engawapg.lib.zoomable.rememberZoomState
|
||||
import net.engawapg.lib.zoomable.zoomable
|
||||
@ -107,7 +109,8 @@ fun ZoomModalSheet(
|
||||
model = data,
|
||||
contentDescription = null,
|
||||
onSuccess = {
|
||||
aspectRatio = it.result.drawable.safeAspectRatio
|
||||
aspectRatio =
|
||||
it.result.image.asDrawable(Resources.getSystem()).safeAspectRatio
|
||||
},
|
||||
contentScale = ContentScale.FillBounds,
|
||||
showTransparencyChecker = false,
|
||||
|
@ -57,12 +57,12 @@ import androidx.compose.ui.unit.Density
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.graphics.applyCanvas
|
||||
import coil.request.ImageRequest
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.data.utils.safeConfig
|
||||
import ru.tech.imageresizershrinker.core.domain.model.IntegerSize
|
||||
import ru.tech.imageresizershrinker.core.domain.model.Pt
|
||||
import ru.tech.imageresizershrinker.core.ui.shapes.MaterialStarShape
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalImageLoader
|
||||
import ru.tech.imageresizershrinker.feature.draw.domain.DrawLineStyle
|
||||
import ru.tech.imageresizershrinker.feature.draw.domain.DrawMode
|
||||
@ -347,7 +347,7 @@ fun NativeCanvas.drawRepeatedImageOnPath(
|
||||
.data(drawMode.imageData)
|
||||
.size(strokeWidth.toPx(canvasSize).roundToInt())
|
||||
.build()
|
||||
).drawable?.toBitmap()
|
||||
).image?.toBitmap()
|
||||
}
|
||||
}
|
||||
pathImage?.let { bitmap ->
|
||||
|
@ -19,8 +19,8 @@ package ru.tech.imageresizershrinker.feature.filters.data.model
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import coil.size.Size
|
||||
import coil.size.pxOrElse
|
||||
import coil3.size.Size
|
||||
import coil3.size.pxOrElse
|
||||
import jp.co.cyberagent.android.gpuimage.GPUImage
|
||||
import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter
|
||||
import ru.tech.imageresizershrinker.core.data.utils.asCoil
|
||||
@ -28,11 +28,11 @@ import ru.tech.imageresizershrinker.core.data.utils.aspectRatio
|
||||
import ru.tech.imageresizershrinker.core.domain.model.IntegerSize
|
||||
import ru.tech.imageresizershrinker.core.domain.transformation.Transformation
|
||||
import java.lang.Integer.max
|
||||
import coil.transform.Transformation as CoilTransformation
|
||||
import coil3.transform.Transformation as CoilTransformation
|
||||
|
||||
internal abstract class GPUFilterTransformation(
|
||||
private val context: Context,
|
||||
) : CoilTransformation, Transformation<Bitmap> {
|
||||
) : CoilTransformation(), Transformation<Bitmap> {
|
||||
|
||||
/**
|
||||
* Create the [GPUImageFilter] to apply to this [Transformation]
|
||||
|
@ -31,7 +31,7 @@ import androidx.compose.ui.graphics.ShaderBrush
|
||||
import androidx.compose.ui.graphics.TileMode
|
||||
import androidx.core.net.toUri
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import coil.transform.Transformation
|
||||
import coil3.transform.Transformation
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
|
@ -47,11 +47,11 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.net.toUri
|
||||
import coil.request.ImageRequest
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.toBitmap
|
||||
import com.t8rin.modalsheet.FullscreenPopup
|
||||
import ru.tech.imageresizershrinker.core.domain.image.model.ImageFrames
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.Picker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.rememberImagePicker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen
|
||||
@ -191,7 +191,7 @@ internal fun ImagePreviewGrid(
|
||||
ImageRequest.Builder(context)
|
||||
.data(uri.toUri())
|
||||
.build()
|
||||
).drawable?.toBitmap()
|
||||
).image?.toBitmap()
|
||||
}
|
||||
)
|
||||
}
|
@ -40,6 +40,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil3.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.safeAspectRatio
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.Picker
|
||||
@ -119,7 +120,7 @@ fun ImageSplitterContent(
|
||||
.padding(4.dp)
|
||||
.clip(MaterialTheme.shapes.medium),
|
||||
onSuccess = {
|
||||
aspectRatio = it.result.drawable.safeAspectRatio
|
||||
aspectRatio = it.result.image.toBitmap().safeAspectRatio
|
||||
}
|
||||
)
|
||||
} else {
|
||||
|
@ -48,11 +48,11 @@ import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.AsyncImagePainter
|
||||
import coil3.compose.AsyncImagePainter
|
||||
import coil3.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.domain.image.model.ImageInfo
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.resources.icons.ImageEdit
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.asClip
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.isLandscapeOrientationAsState
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen
|
||||
@ -212,7 +212,7 @@ fun LoadNetImageContent(
|
||||
if (it is AsyncImagePainter.State.Error) {
|
||||
component.updateBitmap(null)
|
||||
} else if (it is AsyncImagePainter.State.Success) {
|
||||
component.updateBitmap(it.result.drawable.toBitmap())
|
||||
component.updateBitmap(it.result.image.toBitmap())
|
||||
}
|
||||
imageState = it
|
||||
},
|
||||
|
@ -21,7 +21,7 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import coil.ImageLoader
|
||||
import coil3.ImageLoader
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import com.t8rin.dynamic.theme.ColorTuple
|
||||
import com.t8rin.dynamic.theme.extractPrimaryColor
|
||||
|
@ -26,9 +26,10 @@ import android.graphics.pdf.PdfRenderer
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.core.net.toUri
|
||||
import coil.ImageLoader
|
||||
import coil.request.ImageRequest
|
||||
import coil.size.Size
|
||||
import coil3.ImageLoader
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.size.Size
|
||||
import coil3.toBitmap
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
@ -36,7 +37,6 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import ru.tech.imageresizershrinker.core.data.utils.aspectRatio
|
||||
import ru.tech.imageresizershrinker.core.data.utils.getSuitableConfig
|
||||
import ru.tech.imageresizershrinker.core.data.utils.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.domain.dispatchers.DispatchersHolder
|
||||
import ru.tech.imageresizershrinker.core.domain.image.ImageScaler
|
||||
import ru.tech.imageresizershrinker.core.domain.image.model.ImageScaleMode
|
||||
@ -186,12 +186,12 @@ internal class AndroidPdfManager @Inject constructor(
|
||||
val r = PdfRenderer(fileDescriptor)
|
||||
List(r.pageCount) {
|
||||
val page = r.openPage(it)
|
||||
page?.run {
|
||||
page.run {
|
||||
IntegerSize(width, height)
|
||||
}.also {
|
||||
page.close()
|
||||
}
|
||||
}.filterNotNull().also {
|
||||
}.also {
|
||||
pagesBuf[uri] = it
|
||||
}
|
||||
}
|
||||
@ -217,7 +217,7 @@ internal class AndroidPdfManager @Inject constructor(
|
||||
.data(uri)
|
||||
.size(Size.ORIGINAL)
|
||||
.build()
|
||||
).drawable?.toBitmap()?.let {
|
||||
).image?.toBitmap()?.let {
|
||||
imageScaler.scaleImage(
|
||||
image = it,
|
||||
width = (it.width * percent / 100f).roundToInt(),
|
||||
|
@ -90,8 +90,10 @@ import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||
import coil.memory.MemoryCache
|
||||
import coil.request.ImageRequest
|
||||
import coil3.Image
|
||||
import coil3.asImage
|
||||
import coil3.memory.MemoryCache
|
||||
import coil3.request.ImageRequest
|
||||
import com.t8rin.dynamic.theme.observeAsState
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
@ -477,9 +479,9 @@ private fun PdfPage(
|
||||
val imageLoader = LocalImageLoader.current
|
||||
val imageLoadingScope = rememberCoroutineScope()
|
||||
|
||||
val cacheValue: Bitmap? = imageLoader.memoryCache?.get(cacheKey)?.bitmap
|
||||
val cacheValue: Image? = imageLoader.memoryCache?.get(cacheKey)?.image
|
||||
|
||||
var bitmap: Bitmap? by remember { mutableStateOf(cacheValue) }
|
||||
var bitmap: Image? by remember { mutableStateOf(cacheValue) }
|
||||
if (bitmap == null) {
|
||||
DisposableEffect(cacheKey, index) {
|
||||
val job = imageLoadingScope.launch(Dispatchers.IO) {
|
||||
@ -503,7 +505,7 @@ private fun PdfPage(
|
||||
null,
|
||||
PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY
|
||||
)
|
||||
bitmap = destinationBitmap
|
||||
bitmap = destinationBitmap.asImage()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
@ -518,11 +520,13 @@ private fun PdfPage(
|
||||
}
|
||||
}
|
||||
|
||||
val request = ImageRequest.Builder(context)
|
||||
.size(renderWidth, renderHeight)
|
||||
.memoryCacheKey(cacheKey)
|
||||
.data(bitmap)
|
||||
.build()
|
||||
val request = remember(context, renderWidth, renderHeight, bitmap) {
|
||||
ImageRequest.Builder(context)
|
||||
.size(renderWidth, renderHeight)
|
||||
.memoryCacheKey(cacheKey)
|
||||
.data(bitmap)
|
||||
.build()
|
||||
}
|
||||
|
||||
val transition = updateTransition(selected)
|
||||
val padding by transition.animateDp { s ->
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
package ru.tech.imageresizershrinker.feature.recognize.text.domain
|
||||
|
||||
import okhttp3.internal.toImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import ru.tech.imageresizershrinker.feature.recognize.text.domain.Constants.KEY_CHOP_ENABLE
|
||||
import ru.tech.imageresizershrinker.feature.recognize.text.domain.Constants.KEY_EDGES_MAX_CHILDREN_PER_OUTLINE
|
||||
import ru.tech.imageresizershrinker.feature.recognize.text.domain.Constants.KEY_ENABLE_NEW_SEGSEARCH
|
||||
|
@ -49,7 +49,8 @@ import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.request.ImageRequest
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.notNullAnd
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.readableByteCount
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
@ -60,7 +61,6 @@ import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.copyToClip
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.FileType
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImagePickerMode
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.safeAspectRatio
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.Picker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.isPortraitOrientationAsState
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.localImagePickerMode
|
||||
@ -148,7 +148,7 @@ fun RecognizeTextContent(
|
||||
selector = {
|
||||
imageLoader.execute(
|
||||
ImageRequest.Builder(context).data(it).build()
|
||||
).drawable?.toBitmap()
|
||||
).image?.toBitmap()
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -70,7 +70,7 @@ import ru.tech.imageresizershrinker.feature.recognize.text.domain.TextRecognitio
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import coil.transform.Transformation as CoilTransformation
|
||||
import coil3.transform.Transformation as CoilTransformation
|
||||
|
||||
class RecognizeTextComponent @AssistedInject internal constructor(
|
||||
@Assisted componentContext: ComponentContext,
|
||||
|
@ -23,7 +23,7 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import coil.ImageLoader
|
||||
import coil3.ImageLoader
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import com.arkivanov.decompose.DelicateDecomposeApi
|
||||
import com.arkivanov.decompose.router.stack.ChildStack
|
||||
|
@ -67,6 +67,7 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil3.toBitmap
|
||||
import kotlinx.coroutines.launch
|
||||
import net.engawapg.lib.zoomable.rememberZoomState
|
||||
import net.engawapg.lib.zoomable.zoomable
|
||||
@ -80,7 +81,6 @@ import ru.tech.imageresizershrinker.core.filters.presentation.widget.FilterReord
|
||||
import ru.tech.imageresizershrinker.core.filters.presentation.widget.FilterTemplateCreationSheetComponent
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.theme.mixedContainer
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedFloatingActionButton
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton
|
||||
@ -292,7 +292,7 @@ fun FilterEditOption(
|
||||
}
|
||||
}.value,
|
||||
onSuccess = {
|
||||
stateBitmap = it.result.drawable.toBitmap()
|
||||
stateBitmap = it.result.image.toBitmap()
|
||||
},
|
||||
showTransparencyChecker = false,
|
||||
modifier = Modifier
|
||||
|
@ -32,10 +32,10 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.request.ImageRequest
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.resources.icons.ImageReset
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.Picker
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.asClip
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.isPortraitOrientationAsState
|
||||
@ -94,7 +94,7 @@ fun WatermarkingContent(
|
||||
selector = {
|
||||
imageLoader.execute(
|
||||
ImageRequest.Builder(context).data(it).build()
|
||||
).drawable?.toBitmap()
|
||||
).image?.toBitmap()
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -25,7 +25,7 @@ import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.core.net.toUri
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import coil.transform.Transformation
|
||||
import coil3.transform.Transformation
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
|
@ -7,16 +7,15 @@ versionName = "3.1.0-rc01"
|
||||
versionCode = "156"
|
||||
|
||||
jvmTarget = "17"
|
||||
compose-compiler = "1.5.15"
|
||||
|
||||
imageToolboxLibs = "3.0.1"
|
||||
imageToolboxLibs = "3.1.1"
|
||||
trickle = "1.2.2"
|
||||
|
||||
avifCoder = "2.0.8"
|
||||
avifCoderCoil = "2.0.8"
|
||||
aire = "0.15.4"
|
||||
jxlCoder = "2.4.0"
|
||||
jxlCoderCoil = "2.4.0"
|
||||
jxlCoder = "2.4.0.1"
|
||||
jxlCoderCoil = "2.4.0.1"
|
||||
jpegliCoder = "1.0.1"
|
||||
|
||||
tesseract = "4.7.0"
|
||||
@ -40,12 +39,13 @@ detekt = "1.23.7"
|
||||
detektCompose = "0.4.18"
|
||||
decompose = "3.2.2"
|
||||
|
||||
kotlin = "1.9.25"
|
||||
kotlin = "2.0.21"
|
||||
agp = "8.7.2"
|
||||
hilt = "2.52"
|
||||
gms = "4.4.2"
|
||||
|
||||
coil = "2.7.0"
|
||||
ktor = "3.0.1"
|
||||
coil = "3.0.2"
|
||||
appCompat = "1.7.0"
|
||||
androidxCore = "1.15.0"
|
||||
androidxLifecycle = "2.9.0-alpha07"
|
||||
@ -58,13 +58,13 @@ reviewKtx = "2.0.2"
|
||||
splashScreen = "1.2.0-alpha02"
|
||||
|
||||
espresso = "3.6.1"
|
||||
ksp = "1.9.25-1.0.20"
|
||||
ksp = "2.0.21-1.0.27"
|
||||
|
||||
androidx-test-ext-junit = "1.2.1"
|
||||
documentfile = "1.0.1"
|
||||
uiautomator = "2.3.0"
|
||||
androidxMacroBenchmark = "1.4.0-alpha05"
|
||||
quickie = "1.12.4"
|
||||
quickie = "1.13.0"
|
||||
|
||||
material = "1.13.0-alpha07"
|
||||
jsoup = "1.18.1"
|
||||
@ -128,13 +128,14 @@ androidx-exifinterface = { module = "androidx.exifinterface:exifinterface", vers
|
||||
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidxLifecycle" }
|
||||
androidx-material3-window-sizeclass = { module = "androidx.compose.material3:material3-window-size-class", version.ref = "material3" }
|
||||
androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "materialIconsExtended" }
|
||||
androidx-compose-ui-graphics = { module = "androidx.compose.ui:ui-graphics", version.ref = "composeVersion" }
|
||||
androidx-material = { module = "androidx.compose.material:material", version.ref = "composeVersion" }
|
||||
androidx-material3 = { module = "androidx.compose.material3:material3", version.ref = "material3" }
|
||||
app-update-ktx = { module = "com.google.android.play:app-update-ktx", version.ref = "appUpdateKtx" }
|
||||
app-update = { module = "com.google.android.play:app-update", version.ref = "appUpdate" }
|
||||
avif-coder = { module = "com.github.awxkee:avif-coder", version.ref = "avifCoder" }
|
||||
avif-coder-coil = { module = "com.github.awxkee:avif-coder-coil", version.ref = "avifCoderCoil" }
|
||||
compose = { module = "com.github.zed-alpha.shadow-gadgets:compose", version.ref = "shadowGadgets" }
|
||||
shadowGadgets = { module = "com.github.zed-alpha.shadow-gadgets:compose", version.ref = "shadowGadgets" }
|
||||
datastore-preferences-android = { module = "androidx.datastore:datastore-preferences-android", version.ref = "androidx-datastorePreferencesAndroid" }
|
||||
fadingEdges = { module = "com.github.t8rin:ComposeFadingEdges", version.ref = "fadingEdges" }
|
||||
firebase-crashlytics-ktx = { module = "com.google.firebase:firebase-crashlytics-ktx", version.ref = "firebaseCrashlyticsKtx" }
|
||||
@ -144,10 +145,14 @@ decomposeExtensions = { module = "com.arkivanov.decompose:extensions-compose", v
|
||||
shadowsPlus = { module = "com.github.GIGAMOLE:ComposeShadowsPlus", version.ref = "shadowsPlus" }
|
||||
dagger-hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" }
|
||||
desugaring = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugaring" }
|
||||
coilCompose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
|
||||
coilGif = { module = "io.coil-kt:coil-gif", version.ref = "coil" }
|
||||
coilSvg = { module = "io.coil-kt:coil-svg", version.ref = "coil" }
|
||||
coil = { module = "io.coil-kt:coil", version.ref = "coil" }
|
||||
|
||||
ktor = { module = "io.ktor:ktor-client-android", version.ref = "ktor" }
|
||||
coilNetwork = { module = "io.coil-kt.coil3:coil-network-ktor3", version.ref = "coil" }
|
||||
coilCompose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" }
|
||||
coilGif = { module = "io.coil-kt.coil3:coil-gif", version.ref = "coil" }
|
||||
coilSvg = { module = "io.coil-kt.coil3:coil-svg", version.ref = "coil" }
|
||||
coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" }
|
||||
|
||||
firebase-analytics-ktx = { module = "com.google.firebase:firebase-analytics-ktx", version.ref = "firebaseAnalyticsKtx" }
|
||||
jxl-coder-coil = { module = "io.github.awxkee:jxl-coder-coil", version.ref = "jxlCoderCoil" }
|
||||
jxl-coder = { module = "io.github.awxkee:jxl-coder", version.ref = "jxlCoder" }
|
||||
@ -183,6 +188,7 @@ detekt-gradle = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", v
|
||||
detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
|
||||
detekt-compose = { module = "io.nlopez.compose.rules:detekt", version.ref = "detektCompose" }
|
||||
aboutlibraries-gradle = { module = "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin", version.ref = "aboutlibraries" }
|
||||
compose-compiler-gradle = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" }
|
||||
|
||||
[plugins]
|
||||
image-toolbox-library = { id = "image.toolbox.library", version = "unspecified" }
|
||||
|
Reference in New Issue
Block a user