mirror of
https://github.com/SimpleMobileTools/Simple-Draw.git
synced 2025-02-27 08:57:40 +01:00
Add eye dropper
This commit is contained in:
parent
6c3c7dd193
commit
1dd61c9ab0
@ -13,8 +13,8 @@ import android.view.Menu
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.print.PrintHelper
|
import androidx.print.PrintHelper
|
||||||
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
|
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
|
||||||
import com.simplemobiletools.commons.dialogs.ConfirmationAdvancedDialog
|
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.R
|
||||||
import com.simplemobiletools.draw.pro.dialogs.SaveImageDialog
|
import com.simplemobiletools.draw.pro.dialogs.SaveImageDialog
|
||||||
import com.simplemobiletools.draw.pro.extensions.config
|
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.JPG
|
||||||
import com.simplemobiletools.draw.pro.helpers.PNG
|
import com.simplemobiletools.draw.pro.helpers.PNG
|
||||||
import com.simplemobiletools.draw.pro.helpers.SVG
|
import com.simplemobiletools.draw.pro.helpers.SVG
|
||||||
@ -60,10 +61,17 @@ class MainActivity : SimpleActivity(), CanvasListener {
|
|||||||
private var savedPathsHash = 0L
|
private var savedPathsHash = 0L
|
||||||
private var lastSavePromptTS = 0L
|
private var lastSavePromptTS = 0L
|
||||||
private var isEraserOn = false
|
private var isEraserOn = false
|
||||||
|
private var isEyeDropperOn = false
|
||||||
private var isImageCaptureIntent = false
|
private var isImageCaptureIntent = false
|
||||||
private var isEditIntent = false
|
private var isEditIntent = false
|
||||||
private var lastBitmapPath = ""
|
private var lastBitmapPath = ""
|
||||||
|
|
||||||
|
private val eyeDropper by lazy {
|
||||||
|
EyeDropper(my_canvas) { selectedColor ->
|
||||||
|
setColor(selectedColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
@ -88,6 +96,7 @@ class MainActivity : SimpleActivity(), CanvasListener {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
redo.setOnClickListener { my_canvas.redo() }
|
redo.setOnClickListener { my_canvas.redo() }
|
||||||
|
eye_dropper.setOnClickListener { eyeDropperClicked() }
|
||||||
|
|
||||||
checkIntents()
|
checkIntents()
|
||||||
if (!isImageCaptureIntent) {
|
if (!isImageCaptureIntent) {
|
||||||
@ -184,7 +193,8 @@ class MainActivity : SimpleActivity(), CanvasListener {
|
|||||||
val faqItems = arrayListOf(
|
val faqItems = arrayListOf(
|
||||||
FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons),
|
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_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)
|
startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, false)
|
||||||
}
|
}
|
||||||
@ -317,7 +327,7 @@ class MainActivity : SimpleActivity(), CanvasListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateEraserState() {
|
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)
|
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() {
|
private fun confirmImage() {
|
||||||
when {
|
when {
|
||||||
isEditIntent -> {
|
isEditIntent -> {
|
||||||
@ -496,6 +516,7 @@ class MainActivity : SimpleActivity(), CanvasListener {
|
|||||||
undo.applyColorFilter(contrastColor)
|
undo.applyColorFilter(contrastColor)
|
||||||
eraser.applyColorFilter(contrastColor)
|
eraser.applyColorFilter(contrastColor)
|
||||||
redo.applyColorFilter(contrastColor)
|
redo.applyColorFilter(contrastColor)
|
||||||
|
eye_dropper.applyColorFilter(contrastColor)
|
||||||
if (isBlackAndWhiteTheme()) {
|
if (isBlackAndWhiteTheme()) {
|
||||||
stroke_width_bar.setColors(0, contrastColor, 0)
|
stroke_width_bar.setColors(0, contrastColor, 0)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
10
app/src/main/res/drawable/ic_colorise_off_vector.xml
Normal file
10
app/src/main/res/drawable/ic_colorise_off_vector.xml
Normal 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>
|
10
app/src/main/res/drawable/ic_colorize_vector.xml
Normal file
10
app/src/main/res/drawable/ic_colorize_vector.xml
Normal 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>
|
@ -23,10 +23,19 @@
|
|||||||
android:id="@+id/eraser"
|
android:id="@+id/eraser"
|
||||||
android:layout_width="@dimen/normal_icon_size"
|
android:layout_width="@dimen/normal_icon_size"
|
||||||
android:layout_height="@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:padding="@dimen/normal_margin"
|
||||||
android:src="@drawable/ic_eraser_off" />
|
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
|
<ImageView
|
||||||
android:id="@+id/color_picker"
|
android:id="@+id/color_picker"
|
||||||
android:layout_width="@dimen/normal_icon_size"
|
android:layout_width="@dimen/normal_icon_size"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user