Skip to content

Commit

Permalink
Introduce Image Editor v2
Browse files Browse the repository at this point in the history
Supports:
- Cropping
- Adjustments (Brightness, Contrast..)
- Filters
- Markup (Drawing)

Also adds tablet/landscape optimised layout

Fixes Image editing #1
Fixes [Enhancement] Editor: Drawing #351
Fixes [BUG] Can't crop when I'm not holding makred corners #406
Fixes [Improvement] Cropping #441
Fixes [Enhancement] Please add draw support to edits #494

Signed-off-by: IacobIonut01 <[email protected]>
  • Loading branch information
IacobIonut01 committed Nov 2, 2024
1 parent 7021c43 commit 700af0f
Show file tree
Hide file tree
Showing 130 changed files with 4,726 additions and 6,268 deletions.
6 changes: 3 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ android {
applicationId = "com.dot.gallery"
minSdk = 30
targetSdk = 35
versionCode = 30120
versionCode = 30123
versionName = "3.0.1"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
Expand Down Expand Up @@ -218,8 +218,8 @@ dependencies {
// Fuzzy Search
implementation(libs.fuzzywuzzy)

// GPU Image
implementation(libs.gpuimage)
// Aire
implementation(libs.aire)

// Pinch to zoom
implementation(libs.pinchzoomgrid)
Expand Down
4 changes: 3 additions & 1 deletion app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@
-dontwarn org.bouncycastle.jsse.**
-dontwarn org.conscrypt.**
-dontwarn org.openjsse.**
-dontwarn org.slf4j.impl.StaticLoggerBinder
-dontwarn org.slf4j.impl.StaticLoggerBinder

-keep class com.dot.gallery.feature_node.presentation.edit.adjustments.** { *; }
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@
<activity
android:name=".feature_node.presentation.edit.EditActivity"
android:configChanges="keyboard|keyboardHidden|screenSize|screenLayout|smallestScreenSize|uiMode"
android:enabled="false"
android:launchMode="singleTop"
android:exported="true">
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.EDIT"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,18 +142,17 @@ fun ContentResolver.overrideImage(
displayName: String
): Boolean {
val values = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, displayName)
put(MediaStore.MediaColumns.MIME_TYPE, mimeType)
put(MediaStore.MediaColumns.RELATIVE_PATH, relativePath)
put(MediaStore.MediaColumns.DATE_MODIFIED, System.currentTimeMillis())
put(MediaStore.MediaColumns.IS_PENDING, 1)
}

return runCatching {
update(uri, values, null)
openOutputStream(uri)?.use { stream ->
if (!bitmap.compress(format, 95, stream))
if (!bitmap.compress(format, 100, stream))
throw IOException("Failed to save bitmap.")
} ?: throw IOException("Failed to open output stream.")
update(uri, values, null) > 0 && update(
update(
uri,
ContentValues().apply { put(MediaStore.MediaColumns.IS_PENDING, 0) },
null
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ data class Media(

@Stable
override fun toString(): String {
return "$id, $path, $fullDate, $mimeType, favorite=$favorite"
return "$id, $path, $fullDate, $mimeType, favorite=$favorite, $timestamp"
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.dot.gallery.feature_node.domain.model.editor

import android.graphics.Bitmap
import androidx.annotation.Keep
import com.dot.gallery.feature_node.presentation.util.sentenceCase

@Keep
interface Adjustment {
fun apply(bitmap: Bitmap): Bitmap

val name: String get() = this::class.simpleName.toString().sentenceCase()

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.dot.gallery.feature_node.domain.model.editor

import android.os.Parcelable
import androidx.compose.runtime.Immutable
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable

@Immutable
@Serializable
@Parcelize
data class CropState(
val isCropping: Boolean = false,
val showCropper: Boolean = false
) : Parcelable
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.dot.gallery.feature_node.domain.model.editor;

import androidx.annotation.Keep;
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.RotateRight
import androidx.compose.material.icons.outlined.Crop
import androidx.compose.material.icons.outlined.Flip
import androidx.compose.ui.graphics.vector.ImageVector;
import com.dot.gallery.feature_node.presentation.edit.adjustments.Flip
import com.dot.gallery.feature_node.presentation.edit.adjustments.Rotate90CW

@Keep
enum class CropperAction {
ROTATE_90, CROP, FLIP;

val icon: ImageVector
get() = when (this) {
CROP -> Icons.Outlined.Crop
ROTATE_90 -> Icons.AutoMirrored.Outlined.RotateRight
FLIP -> Icons.Outlined.Flip
}


fun asAdjustment(): Adjustment? {
return when (this) {
ROTATE_90 -> Rotate90CW(90f)
FLIP -> Flip(horizontal = true)
else -> null
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.dot.gallery.feature_node.domain.model.editor

enum class DrawMode {
Draw, Touch, Erase
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.dot.gallery.feature_node.domain.model.editor

import com.dot.gallery.feature_node.presentation.edit.adjustments.varfilter.VariableFilterTypes
import kotlinx.serialization.Serializable

@Serializable
sealed class EditorDestination {

@Serializable
data object Editor : EditorDestination()

@Serializable
data object Crop : EditorDestination()

@Serializable
data object Adjust : EditorDestination()

@Serializable
data class AdjustDetail(val adjustment: VariableFilterTypes) : EditorDestination()

@Serializable
data object Filters : EditorDestination()

@Serializable
data object Markup : EditorDestination()

@Serializable
data object MarkupDraw : EditorDestination()

@Serializable
data object MarkupDrawSize : EditorDestination()

@Serializable
data object MarkupDrawColor : EditorDestination()

@Serializable
data object MarkupErase : EditorDestination()

@Serializable
data object MarkupEraseSize : EditorDestination()

@Serializable
data object ExternalEditor : EditorDestination()

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.dot.gallery.feature_node.domain.model.editor;

import android.os.Parcelable
import androidx.annotation.Keep
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Adjust
import androidx.compose.material.icons.outlined.Crop
import androidx.compose.material.icons.outlined.Draw
import androidx.compose.material.icons.outlined.Filter
import androidx.compose.ui.graphics.vector.ImageVector
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable

@Keep
@Serializable
@Parcelize
enum class EditorItems : Parcelable {
Crop,
Adjust,
Filters,
Markup;

@IgnoredOnParcel
val icon: ImageVector
get() = when (this) {
Crop -> Icons.Outlined.Crop
Adjust -> Icons.Outlined.Adjust
Filters -> Icons.Outlined.Filter
Markup -> Icons.Outlined.Draw
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.dot.gallery.feature_node.domain.model.editor

import androidx.annotation.Keep
import androidx.compose.ui.graphics.ColorMatrix

@Keep
interface ImageFilter : Adjustment {

fun colorMatrix(): ColorMatrix?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.dot.gallery.feature_node.domain.model.editor

import android.os.Parcelable
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Redo
import androidx.compose.material.icons.automirrored.outlined.Undo
import androidx.compose.material.icons.outlined.Brush
import androidx.compose.material.icons.outlined.ColorLens
import androidx.compose.material.icons.outlined.Draw
import androidx.compose.ui.graphics.vector.ImageVector
import com.dot.gallery.ui.core.icons.Ink_Eraser
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable
import com.dot.gallery.ui.core.Icons as DotIcons

@Serializable
@Parcelize
enum class MarkupEraseItems : Parcelable {
Undo,
Size,
Redo;

@IgnoredOnParcel
val icon: ImageVector
get() = when (this) {
Size -> Icons.Outlined.Brush
Undo -> Icons.AutoMirrored.Outlined.Undo
Redo -> Icons.AutoMirrored.Outlined.Redo
}
}


@Serializable
@Parcelize
enum class MarkupDrawItems : Parcelable {
Undo,
Size,
Color,
Redo;

@IgnoredOnParcel
val icon: ImageVector
get() = when (this) {
Size -> Icons.Outlined.Brush
Color -> Icons.Outlined.ColorLens
Undo -> Icons.AutoMirrored.Outlined.Undo
Redo -> Icons.AutoMirrored.Outlined.Redo
}
}

@Serializable
@Parcelize
enum class MarkupItems : Parcelable {
Undo,
Draw,
Erase,
Redo;

@IgnoredOnParcel
val icon: ImageVector
get() = when (this) {
Draw -> Icons.Outlined.Draw
Erase -> DotIcons.Ink_Eraser
Undo -> Icons.AutoMirrored.Outlined.Undo
Redo -> Icons.AutoMirrored.Outlined.Redo
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.dot.gallery.feature_node.domain.model.editor

enum class PainterMotionEvent {
Idle, Down, Move, Up
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.dot.gallery.feature_node.domain.model.editor

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.StrokeJoin

class PathProperties(
var strokeWidth: Float = 20f,
var color: Color = Color.Red,
var alpha: Float = 1f,
var strokeCap: StrokeCap = StrokeCap.Round,
var strokeJoin: StrokeJoin = StrokeJoin.Round,
var eraseMode: Boolean = false
) {

fun copy(
strokeWidth: Float = this.strokeWidth,
color: Color = this.color,
alpha: Float = this.alpha,
strokeCap: StrokeCap = this.strokeCap,
strokeJoin: StrokeJoin = this.strokeJoin,
eraseMode: Boolean = this.eraseMode
) = PathProperties(
strokeWidth, color, alpha, strokeCap, strokeJoin, eraseMode
)

fun copyFrom(properties: PathProperties) {
this.strokeWidth = properties.strokeWidth
this.color = properties.color
this.strokeCap = properties.strokeCap
this.strokeJoin = properties.strokeJoin
this.eraseMode = properties.eraseMode
}
}
Loading

0 comments on commit 700af0f

Please sign in to comment.