Add eye dropper

This commit is contained in:
Paul Akhamiogu 2021-12-27 20:10:14 +00:00
parent 6c3c7dd193
commit 1dd61c9ab0
5 changed files with 139 additions and 4 deletions

View File

@ -13,8 +13,8 @@ import android.view.Menu
import android.view.MenuItem
import android.view.WindowManager
import android.webkit.MimeTypeMap
import android.widget.ImageView
import android.widget.SeekBar
import androidx.core.content.ContextCompat
import androidx.print.PrintHelper
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
import com.simplemobiletools.commons.dialogs.ConfirmationAdvancedDialog
@ -30,6 +30,7 @@ import com.simplemobiletools.draw.pro.BuildConfig
import com.simplemobiletools.draw.pro.R
import com.simplemobiletools.draw.pro.dialogs.SaveImageDialog
import com.simplemobiletools.draw.pro.extensions.config
import com.simplemobiletools.draw.pro.helpers.EyeDropper
import com.simplemobiletools.draw.pro.helpers.JPG
import com.simplemobiletools.draw.pro.helpers.PNG
import com.simplemobiletools.draw.pro.helpers.SVG
@ -60,10 +61,17 @@ class MainActivity : SimpleActivity(), CanvasListener {
private var savedPathsHash = 0L
private var lastSavePromptTS = 0L
private var isEraserOn = false
private var isEyeDropperOn = false
private var isImageCaptureIntent = false
private var isEditIntent = false
private var lastBitmapPath = ""
private val eyeDropper by lazy {
EyeDropper(my_canvas) { selectedColor ->
setColor(selectedColor)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
@ -88,6 +96,7 @@ class MainActivity : SimpleActivity(), CanvasListener {
true
}
redo.setOnClickListener { my_canvas.redo() }
eye_dropper.setOnClickListener { eyeDropperClicked() }
checkIntents()
if (!isImageCaptureIntent) {
@ -184,7 +193,8 @@ class MainActivity : SimpleActivity(), CanvasListener {
val faqItems = arrayListOf(
FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons),
FAQItem(R.string.faq_6_title_commons, R.string.faq_6_text_commons),
FAQItem(R.string.faq_7_title_commons, R.string.faq_7_text_commons))
FAQItem(R.string.faq_7_title_commons, R.string.faq_7_text_commons)
)
startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, false)
}
@ -317,7 +327,7 @@ class MainActivity : SimpleActivity(), CanvasListener {
}
private fun updateEraserState() {
eraser.setImageDrawable(resources.getDrawable(if (isEraserOn) R.drawable.ic_eraser_on else R.drawable.ic_eraser_off))
eraser.setImageDrawable(ContextCompat.getDrawable(this, if (isEraserOn) R.drawable.ic_eraser_on else R.drawable.ic_eraser_off))
my_canvas.toggleEraser(isEraserOn)
}
@ -335,6 +345,16 @@ class MainActivity : SimpleActivity(), CanvasListener {
}
}
private fun eyeDropperClicked() {
isEyeDropperOn = !isEyeDropperOn
if (isEyeDropperOn) {
eyeDropper.start()
} else {
eyeDropper.stop()
}
eye_dropper.setImageDrawable(ContextCompat.getDrawable(this, if (isEyeDropperOn) R.drawable.ic_colorise_off_vector else R.drawable.ic_colorize_vector))
}
private fun confirmImage() {
when {
isEditIntent -> {
@ -496,6 +516,7 @@ class MainActivity : SimpleActivity(), CanvasListener {
undo.applyColorFilter(contrastColor)
eraser.applyColorFilter(contrastColor)
redo.applyColorFilter(contrastColor)
eye_dropper.applyColorFilter(contrastColor)
if (isBlackAndWhiteTheme()) {
stroke_width_bar.setColors(0, contrastColor, 0)
}

View File

@ -0,0 +1,85 @@
package com.simplemobiletools.draw.pro.helpers
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.Matrix
import android.graphics.drawable.BitmapDrawable
import android.view.View
import android.view.View.DRAWING_CACHE_QUALITY_LOW
import android.widget.ImageView
// forked from https://github.com/Madrapps/EyeDropper
class EyeDropper(private val view: View, private val onColorSelected: ((Int) -> Unit)) {
companion object {
private const val NO_COLOR = Color.TRANSPARENT
private val INVERT_MATRIX = Matrix()
}
private var viewTouchListener = View.OnTouchListener { _, event ->
notifyColorSelection(event.x.toInt(), event.y.toInt())
true
}
fun start() {
enableDrawingCache()
view.setOnTouchListener(viewTouchListener)
}
fun stop() {
disableDrawingCache()
view.setOnTouchListener(null)
}
private fun enableDrawingCache() {
if (view.shouldDrawingCacheBeEnabled()) {
view.isDrawingCacheEnabled = true
view.drawingCacheQuality = DRAWING_CACHE_QUALITY_LOW
}
}
private fun disableDrawingCache() {
if (view.shouldDrawingCacheBeEnabled()) {
view.isDrawingCacheEnabled = false
}
}
private fun notifyColorSelection(x: Int, y: Int) {
val colorAtPoint = getColorAtPoint(x, y)
onColorSelected.invoke(colorAtPoint)
}
private fun getColorAtPoint(x: Int, y: Int): Int {
return when (view) {
is ImageView -> handleIfImageView(view, x, y)
else -> getPixelAtPoint(view.drawingCache, x, y)
}
}
private fun handleIfImageView(view: ImageView, x: Int, y: Int): Int {
return when (val drawable = view.drawable) {
is BitmapDrawable -> {
view.imageMatrix.invert(INVERT_MATRIX)
val mappedPoints = floatArrayOf(x.toFloat(), y.toFloat())
INVERT_MATRIX.mapPoints(mappedPoints)
getPixelAtPoint(drawable.bitmap, mappedPoints[0].toInt(), mappedPoints[1].toInt())
}
else -> {
NO_COLOR
}
}
}
private fun getPixelAtPoint(bitmap: Bitmap, x: Int, y: Int): Int {
if (bitmap.isValidCoordinate(x, y)) {
return bitmap.getPixel(x, y)
}
return NO_COLOR
}
private fun Bitmap.isValidCoordinate(x: Int, y: Int): Boolean {
return x in 1 until width && y in 1 until height
}
private fun View.shouldDrawingCacheBeEnabled(): Boolean = (this !is ImageView) && !isDrawingCacheEnabled
}

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12.126,8.125l1.937,-1.937 3.747,3.747 -1.937,1.938zM20.71,5.63l-2.34,-2.34a1,1 0,0 0,-1.41 0l-1.83,1.83 3.75,3.75L20.71,7a1,1 0,0 0,0 -1.37zM2,5l6.63,6.63L3,17.25V21h3.75l5.63,-5.62L18,21l2,-2L4,3 2,5z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M20.71,5.63l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-3.12,3.12 -1.93,-1.91 -1.41,1.41 1.42,1.42L3,16.25V21h4.75l8.92,-8.92 1.42,1.42 1.41,-1.41 -1.92,-1.92 3.12,-3.12c0.4,-0.4 0.4,-1.03 0.01,-1.42zM6.92,19L5,17.08l8.06,-8.06 1.92,1.92L6.92,19z"/>
</vector>

View File

@ -23,10 +23,19 @@
android:id="@+id/eraser"
android:layout_width="@dimen/normal_icon_size"
android:layout_height="@dimen/normal_icon_size"
android:layout_toStartOf="@+id/color_picker"
android:layout_toStartOf="@+id/eye_dropper"
android:padding="@dimen/normal_margin"
android:src="@drawable/ic_eraser_off" />
<ImageView
android:id="@+id/eye_dropper"
android:layout_width="@dimen/normal_icon_size"
android:layout_height="@dimen/normal_icon_size"
android:layout_toStartOf="@+id/color_picker"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_colorize_vector"
android:visibility="visible" />
<ImageView
android:id="@+id/color_picker"
android:layout_width="@dimen/normal_icon_size"