Skip to content

Commit

Permalink
Start working on base64 encode/decode to image by #1545
Browse files Browse the repository at this point in the history
  • Loading branch information
T8RIN committed Dec 24, 2024
1 parent b1ffc87 commit f5cb4d0
Show file tree
Hide file tree
Showing 25 changed files with 1,256 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import coil3.fetch.Fetcher
import coil3.fetch.SourceFetchResult
import coil3.request.Options
import okio.Buffer
import java.util.regex.Pattern
import ru.tech.imageresizershrinker.core.domain.utils.isBase64

internal class Base64Fetcher(
private val options: Options,
Expand Down Expand Up @@ -56,20 +56,12 @@ internal class Base64Fetcher(
imageLoader: ImageLoader,
): Fetcher? {
val stripped = data.toString().substringAfter(",")
return if (data.toString().startsWith("data:image") || isBase64(stripped)) {
return if (isBase64(stripped)) {
Base64Fetcher(
options = options,
base64 = stripped
)
} else null
}

companion object {
private fun isBase64(data: String) = BASE64_PATTERN.matcher(data).matches()

private val BASE64_PATTERN = Pattern.compile(
"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,17 @@

package ru.tech.imageresizershrinker.core.domain.utils

import java.util.regex.Pattern

inline fun <reified T> T?.notNullAnd(
predicate: (T) -> Boolean
): Boolean = if (this != null) predicate(this)
else false
else false

fun isBase64(data: String) = data.trim { it.isWhitespace() }
.isNotEmpty()
.and(BASE64_PATTERN.matcher(data).matches() || data.startsWith("data:image"))

private val BASE64_PATTERN = Pattern.compile(
"^(?=(.{4})*\$)[A-Za-z0-9+/]*={0,2}\$"
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
/*
* 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.resources.icons

import androidx.compose.material.icons.Icons
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.path
import androidx.compose.ui.unit.dp

val Icons.Rounded.Base64: ImageVector by lazy {
ImageVector.Builder(
name = "Base64Rounded",
defaultWidth = 24.dp,
defaultHeight = 24.dp,
viewportWidth = 24f,
viewportHeight = 24f
).apply {
path(fill = SolidColor(Color(0xFF000000))) {
moveTo(6.566f, 16.554f)
horizontalLineToRelative(0.909f)
verticalLineToRelative(0.909f)
horizontalLineToRelative(-0.909f)
close()
}
path(fill = SolidColor(Color(0xFF000000))) {
moveTo(14.526f, 8.969f)
lineToRelative(1.756f, 0f)
lineToRelative(0.307f, -1.756f)
lineToRelative(-1.756f, 0f)
close()
}
path(fill = SolidColor(Color(0xFF000000))) {
moveTo(18.307f, 3f)
horizontalLineToRelative(-5.259f)
horizontalLineTo(5.694f)
horizontalLineTo(5.693f)
curveTo(4.206f, 3f, 3f, 4.206f, 3f, 5.693f)
verticalLineToRelative(12.613f)
curveToRelative(0f, 1.302f, 0.923f, 2.388f, 2.151f, 2.639f)
curveToRelative(0.105f, 0.021f, 0.215f, 0.024f, 0.324f, 0.033f)
curveTo(5.548f, 20.984f, 5.618f, 21f, 5.693f, 21f)
horizontalLineToRelative(0f)
horizontalLineToRelative(8.294f)
horizontalLineToRelative(4.319f)
curveTo(19.794f, 21f, 21f, 19.794f, 21f, 18.307f)
verticalLineToRelative(-5.259f)
curveToRelative(0f, 0f, 0f, 0f, 0f, 0f)
verticalLineToRelative(-7.354f)
curveTo(21f, 4.206f, 19.794f, 3f, 18.307f, 3f)
close()
moveTo(8.383f, 14.737f)
horizontalLineTo(6.566f)
verticalLineToRelative(0.909f)
horizontalLineToRelative(0.909f)
curveToRelative(0.502f, 0f, 0.908f, 0.407f, 0.908f, 0.909f)
verticalLineToRelative(0.909f)
curveToRelative(0f, 0.502f, -0.407f, 0.908f, -0.908f, 0.908f)
horizontalLineTo(6.566f)
curveToRelative(-0.502f, 0f, -0.909f, -0.407f, -0.909f, -0.908f)
verticalLineToRelative(-2.726f)
curveToRelative(0f, -0.502f, 0.407f, -0.908f, 0.909f, -0.908f)
horizontalLineToRelative(1.817f)
verticalLineTo(14.737f)
close()
moveTo(11.942f, 18.371f)
horizontalLineToRelative(-0.909f)
verticalLineToRelative(-1.817f)
horizontalLineTo(9.217f)
verticalLineToRelative(-2.725f)
horizontalLineToRelative(0.909f)
verticalLineToRelative(1.817f)
horizontalLineToRelative(0.908f)
verticalLineToRelative(-1.817f)
horizontalLineToRelative(0.909f)
verticalLineTo(18.371f)
close()
moveTo(18.344f, 7.213f)
horizontalLineToRelative(-0.878f)
lineTo(17.159f, 8.969f)
horizontalLineToRelative(0.878f)
lineToRelative(-0.158f, 0.878f)
horizontalLineToRelative(-0.878f)
lineToRelative(-0.154f, 0.878f)
horizontalLineToRelative(-0.878f)
lineToRelative(0.154f, -0.878f)
horizontalLineToRelative(-1.756f)
lineToRelative(-0.154f, 0.878f)
horizontalLineToRelative(-0.878f)
lineToRelative(0.154f, -0.878f)
horizontalLineToRelative(-0.878f)
lineToRelative(0.158f, -0.878f)
horizontalLineToRelative(0.878f)
lineToRelative(0.307f, -1.756f)
horizontalLineToRelative(-0.878f)
lineToRelative(0.154f, -0.878f)
horizontalLineToRelative(0.878f)
lineToRelative(0.158f, -0.878f)
horizontalLineToRelative(0.878f)
lineToRelative(-0.158f, 0.878f)
horizontalLineToRelative(1.756f)
lineToRelative(0.158f, -0.878f)
horizontalLineToRelative(0.878f)
lineToRelative(-0.158f, 0.878f)
horizontalLineToRelative(0.878f)
lineTo(18.344f, 7.213f)
close()
}
}.build()
}


val Icons.Outlined.Base64: ImageVector by lazy {
ImageVector.Builder(
name = "Base64Outlined",
defaultWidth = 24.dp,
defaultHeight = 24.dp,
viewportWidth = 24f,
viewportHeight = 24f
).apply {
path(fill = SolidColor(Color(0xFF000000))) {
moveTo(6.566f, 13.829f)
curveToRelative(-0.502f, 0f, -0.908f, 0.407f, -0.908f, 0.908f)
verticalLineToRelative(2.725f)
curveToRelative(0f, 0.502f, 0.407f, 0.908f, 0.908f, 0.908f)
horizontalLineToRelative(0.908f)
curveToRelative(0.502f, 0f, 0.908f, -0.407f, 0.908f, -0.908f)
verticalLineToRelative(-0.908f)
curveToRelative(0f, -0.502f, -0.407f, -0.908f, -0.908f, -0.908f)
horizontalLineToRelative(-0.908f)
verticalLineToRelative(-0.908f)
horizontalLineToRelative(1.817f)
verticalLineToRelative(-0.908f)
horizontalLineTo(6.566f)
moveTo(6.566f, 16.554f)
horizontalLineToRelative(0.908f)
verticalLineToRelative(0.908f)
horizontalLineToRelative(-0.908f)
verticalLineTo(16.554f)
close()
}
path(fill = SolidColor(Color(0xFF000000))) {
moveTo(9.217f, 13.829f)
verticalLineToRelative(2.725f)
horizontalLineToRelative(1.817f)
verticalLineToRelative(1.817f)
horizontalLineToRelative(0.908f)
verticalLineToRelative(-4.542f)
horizontalLineToRelative(-0.908f)
verticalLineToRelative(1.817f)
horizontalLineToRelative(-0.908f)
verticalLineToRelative(-1.817f)
horizontalLineTo(9.217f)
close()
}
path(fill = SolidColor(Color(0xFF000000))) {
moveTo(18.344f, 7.213f)
lineToRelative(0.154f, -0.878f)
horizontalLineToRelative(-0.878f)
lineToRelative(0.158f, -0.878f)
horizontalLineToRelative(-0.878f)
lineToRelative(-0.158f, 0.878f)
horizontalLineToRelative(-1.756f)
lineToRelative(0.158f, -0.878f)
horizontalLineToRelative(-0.878f)
lineToRelative(-0.158f, 0.878f)
horizontalLineToRelative(-0.878f)
lineToRelative(-0.154f, 0.878f)
horizontalLineToRelative(0.878f)
lineToRelative(-0.307f, 1.756f)
horizontalLineToRelative(-0.878f)
lineTo(12.612f, 9.847f)
horizontalLineToRelative(0.878f)
lineToRelative(-0.154f, 0.878f)
horizontalLineToRelative(0.878f)
lineToRelative(0.154f, -0.878f)
horizontalLineToRelative(1.756f)
lineToRelative(-0.154f, 0.878f)
horizontalLineToRelative(0.878f)
lineToRelative(0.154f, -0.878f)
horizontalLineToRelative(0.878f)
lineToRelative(0.158f, -0.878f)
horizontalLineToRelative(-0.878f)
lineToRelative(0.307f, -1.756f)
horizontalLineTo(18.344f)
close()
moveTo(16.281f, 8.969f)
horizontalLineToRelative(-1.756f)
lineToRelative(0.307f, -1.756f)
horizontalLineToRelative(1.756f)
lineTo(16.281f, 8.969f)
close()
}
path(fill = SolidColor(Color(0xFF000000))) {
moveTo(21f, 5.693f)
curveTo(21f, 4.206f, 19.794f, 3f, 18.307f, 3f)
horizontalLineToRelative(-5.259f)
horizontalLineTo(5.694f)
horizontalLineTo(5.693f)
curveTo(4.206f, 3f, 3f, 4.206f, 3f, 5.693f)
verticalLineToRelative(12.613f)
curveToRelative(0f, 1.302f, 0.923f, 2.388f, 2.151f, 2.639f)
curveToRelative(0.105f, 0.021f, 0.215f, 0.024f, 0.324f, 0.033f)
curveTo(5.548f, 20.984f, 5.618f, 21f, 5.693f, 21f)
horizontalLineToRelative(0f)
horizontalLineToRelative(8.294f)
horizontalLineToRelative(4.319f)
curveTo(19.794f, 21f, 21f, 19.794f, 21f, 18.307f)
verticalLineToRelative(-5.259f)
curveToRelative(0f, 0f, 0f, 0f, 0f, 0f)
verticalLineTo(5.693f)
close()
moveTo(19f, 17.715f)
curveTo(19f, 18.424f, 18.424f, 19f, 17.715f, 19f)
horizontalLineToRelative(-3.737f)
horizontalLineTo(6.286f)
curveToRelative(-0.71f, 0f, -1.285f, -0.576f, -1.285f, -1.285f)
verticalLineTo(6.285f)
curveTo(5f, 5.576f, 5.576f, 5f, 6.286f, 5f)
horizontalLineToRelative(6.778f)
horizontalLineToRelative(4.651f)
curveToRelative(0.71f, 0f, 1.285f, 0.576f, 1.285f, 1.285f)
verticalLineToRelative(3.737f)
curveToRelative(-0f, 0f, -0f, 0f, -0f, 0f)
verticalLineTo(17.715f)
close()
}
}.build()
}
13 changes: 12 additions & 1 deletion core/resources/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1489,7 +1489,7 @@
<string name="material_you_slider_sub">Modern Material You slider, futuristic, fresh, acessible</string>
<string name="apply">Apply</string>
<string name="center_align_dialog_buttons">Center Dialog Buttons</string>
<string name="center_align_dialog_buttons_sub">Buttons of dialogs will be postioned at center instead of left side if possible</string>
<string name="center_align_dialog_buttons_sub">Buttons of dialogs will be positioned at center instead of left side if possible</string>
<string name="open_source_licenses">Open Source Licenses</string>
<string name="open_source_licenses_sub">View licenses of open source libraries used in this app</string>
<string name="area">Area</string>
Expand All @@ -1510,4 +1510,15 @@
<string name="clear_selection">Clear Selection</string>
<string name="settings_group_visibility_hidden">Setting group \"%s\" will be collapsed by default</string>
<string name="settings_group_visibility_visible">Setting group \"%s\" will be expanded by default</string>
<string name="base_64_conversion">Base64 conversion</string>
<string name="base_64_conversion_sub">Decode base64 string to image, or encode image to base64 format</string>
<string name="base_64">Base64</string>
<string name="not_a_valid_base_64">Pasted string is not a valid Base64 string</string>
<string name="copy_not_a_valid_base_64">Cannot copy empty or invalid Base64 string</string>
<string name="paste_base_64">Paste Base64</string>
<string name="copy_base_64">Copy Base64</string>
<string name="base_64_tips">Load image to copy or save Base64 string, if you have any, you can paste it above to obtain image</string>
<string name="save_base_64">Save Base64</string>
<string name="share_base_64">Share Base64</string>
<string name="options">Options</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ package ru.tech.imageresizershrinker.core.ui.utils.helper
import androidx.compose.foundation.Indication
import androidx.compose.material.LocalContentColor
import androidx.compose.material.RippleDefaults
import androidx.compose.material.ripple
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.unit.Dp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import kotlinx.serialization.encoding.Encoder
import ru.tech.imageresizershrinker.core.resources.R
import ru.tech.imageresizershrinker.core.resources.icons.Apng
import ru.tech.imageresizershrinker.core.resources.icons.ApngBox
import ru.tech.imageresizershrinker.core.resources.icons.Base64
import ru.tech.imageresizershrinker.core.resources.icons.CropSmall
import ru.tech.imageresizershrinker.core.resources.icons.Draw
import ru.tech.imageresizershrinker.core.resources.icons.Encrypted
Expand Down Expand Up @@ -133,6 +134,7 @@ sealed class Screen(
is CollageMaker -> "Collage_Maker"
is LibrariesInfo -> "Libraries_Info"
is MarkupLayers -> "Markup_Layers"
is Base64Conversion -> "Base64_Conversion"
}

val icon: ImageVector?
Expand Down Expand Up @@ -177,6 +179,7 @@ sealed class Screen(
NoiseGeneration -> Icons.Outlined.Grain
is CollageMaker -> Icons.Outlined.AutoAwesomeMosaic
is MarkupLayers -> Icons.Outlined.Stack
is Base64Conversion -> Icons.Outlined.Base64
}

@Serializable
Expand Down Expand Up @@ -804,6 +807,15 @@ sealed class Screen(
subtitle = R.string.markup_layers_sub
)

@Serializable
data class Base64Conversion(
val uri: KUri? = null
) : Screen(
id = 35,
title = R.string.base_64_conversion,
subtitle = R.string.base_64_conversion_sub
)

companion object {
val typedEntries by lazy {
listOf(
Expand Down Expand Up @@ -854,6 +866,7 @@ sealed class Screen(
DocumentScanner,
ScanQrCode(),
ColorTools,
Base64Conversion(),
GifTools(),
JxlTools(),
ApngTools(),
Expand All @@ -872,7 +885,7 @@ sealed class Screen(
typedEntries.flatMap { it.first }.sortedBy { it.id }
}

const val FEATURES_COUNT = 55
const val FEATURES_COUNT = 56
}
}

Expand Down
Loading

0 comments on commit f5cb4d0

Please sign in to comment.