@@ -8,10 +8,13 @@ import android.graphics.PointF
88import android.media.MediaScannerConnection
99import android.net.Uri
1010import android.os.Bundle
11+ import android.os.Environment
1112import android.os.Parcelable
13+ import android.provider.MediaStore
1214import android.util.Log
1315import android.view.*
1416import androidx.appcompat.app.AppCompatActivity
17+ import androidx.core.content.FileProvider
1518import androidx.documentfile.provider.DocumentFile
1619import com.dan.perspective.databinding.MainFragmentBinding
1720import org.opencv.android.Utils
@@ -21,6 +24,8 @@ import org.opencv.core.Rect
2124import org.opencv.core.Size
2225import org.opencv.imgproc.Imgproc.*
2326import java.io.File
27+ import java.text.SimpleDateFormat
28+ import java.util.*
2429import kotlin.math.PI
2530import kotlin.math.abs
2631import kotlin.math.max
@@ -29,12 +34,12 @@ import kotlin.math.min
2934
3035class MainFragment (activity : MainActivity ) : AppFragment(activity) {
3136 companion object {
32- const val MSG_LOAD = " Loading"
3337 const val MSG_AUTO_DETECT = " Auto detect"
3438 const val MSG_WARP = " Warping"
3539 const val MSG_SAVE = " Saving"
3640
3741 const val INTENT_OPEN_IMAGE = 2
42+ const val INTENT_TAKE_PHOTO = 3
3843
3944 const val AUTO_DETECT_WORK_SIZE = 1024
4045
@@ -49,6 +54,7 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
4954 private var menuSave: MenuItem ? = null
5055 private var menuPrevPerspective: MenuItem ? = null
5156 private val sharedParams = SharedParams ()
57+ private lateinit var tmpPhotoFile: File
5258
5359 private lateinit var binding: MainFragmentBinding // : ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) }
5460 private var outputName = Settings .DEFAULT_NAME
@@ -85,6 +91,11 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
8591 return true
8692 }
8793
94+ R .id.takePhoto -> {
95+ startActivityToTakePhoto()
96+ return true
97+ }
98+
8899 R .id.save -> {
89100 saveImage()
90101 return true
@@ -127,8 +138,20 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
127138 override fun onActivityResult (requestCode : Int , resultCode : Int , data : Intent ? ) {
128139 super .onActivityResult(requestCode, resultCode, data)
129140
130- if (resultCode == AppCompatActivity .RESULT_OK && requestCode == INTENT_OPEN_IMAGE ) {
131- data?.data?.let { uri -> setImage(uri) }
141+ if (resultCode == AppCompatActivity .RESULT_OK && null != data) {
142+ when (requestCode) {
143+ INTENT_OPEN_IMAGE -> {
144+ data.data?.let { uri -> setImage(uri) }
145+ }
146+
147+ INTENT_TAKE_PHOTO -> {
148+ if (tmpPhotoFile.exists()) {
149+ val name = SimpleDateFormat (" yyyyMMdd_HHmmss_SSS" , Locale .US ).format(Date (System .currentTimeMillis()))
150+ setImage( Uri .fromFile(tmpPhotoFile), name )
151+ tmpPhotoFile.delete()
152+ }
153+ }
154+ }
132155 }
133156 }
134157
@@ -143,6 +166,18 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
143166 startActivityForResult(intent, INTENT_OPEN_IMAGE )
144167 }
145168
169+ private fun startActivityToTakePhoto () {
170+ val tmpUri = FileProvider .getUriForFile(
171+ requireContext(),
172+ " com.dan.perspective.provider" ,
173+ tmpPhotoFile)
174+
175+ val intent = Intent (MediaStore .ACTION_IMAGE_CAPTURE )
176+ .putExtra(MediaStore .EXTRA_OUTPUT , tmpUri)
177+
178+ startActivityForResult(intent, INTENT_TAKE_PHOTO )
179+ }
180+
146181 private fun matToBitmap (image : Mat ): Bitmap ? {
147182 if (image.empty()) return null
148183
@@ -156,41 +191,41 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
156191 return bitmap
157192 }
158193
159- private fun setImage (uri : Uri ) {
160- runAsync(MSG_LOAD ) {
161- inputImage = loadImage(uri)
162- val bitmap = matToBitmap(inputImage)
163-
164- runOnUiThread {
165- binding.imageEdit.setBitmap(bitmap)
194+ private fun setImage (uri : Uri , suggestedName : String? = null) {
195+ val matAndBitmap = loadImage(uri)
196+ if (null == matAndBitmap) {
197+ showToast(" Failed to load the image" )
198+ return
199+ }
166200
167- if (null == bitmap) {
168- showToast(" Failed to load the image" )
169- } else {
170- outputName = Settings .DEFAULT_NAME
171-
172- try {
173- DocumentFile .fromSingleUri(
174- requireContext(),
175- uri
176- )?.name?.let { name ->
177- if (name.isNotEmpty()) {
178- val fields = name.split(' .' )
179- outputName = fields[0 ]
180- }
181- }
182- } catch (e: Exception ) {
183- e.printStackTrace()
201+ inputImage = matAndBitmap.first
202+ binding.imageEdit.setBitmap(matAndBitmap.second)
203+
204+ if (null != suggestedName) {
205+ outputName = suggestedName
206+ } else {
207+ outputName = Settings .DEFAULT_NAME
208+
209+ try {
210+ DocumentFile .fromSingleUri(
211+ requireContext(),
212+ uri
213+ )?.name?.let { name ->
214+ if (name.isNotEmpty()) {
215+ val fields = name.split(' .' )
216+ outputName = fields[0 ]
184217 }
185218 }
219+ } catch (e: Exception ) {
220+ e.printStackTrace()
221+ }
222+ }
186223
187- clearOutputImage()
188- updateButtons()
224+ clearOutputImage()
225+ updateButtons()
189226
190- if (settings.autoDetectOnOpen) {
191- autoDetectPerspective()
192- }
193- }
227+ if (settings.autoDetectOnOpen) {
228+ autoDetectPerspective()
194229 }
195230 }
196231
@@ -208,19 +243,19 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
208243 menuPrevPerspective?.isEnabled = enabled && settings.prevHeight > 0
209244 }
210245
211- private fun loadImage (uri : Uri ) : Mat {
246+ private fun loadImage (uri : Uri ) : Pair < Mat , Bitmap > ? {
212247 try {
213- val inputStream = requireContext().contentResolver.openInputStream(uri) ? : return Mat ()
248+ val inputStream = requireContext().contentResolver.openInputStream(uri) ? : return null
214249 val bitmap = BitmapFactory .decodeStream(inputStream)
215250 val image = Mat ()
216251 Utils .bitmapToMat(bitmap, image)
217252 inputStream.close()
218- return image
253+ return Pair ( image, bitmap)
219254 } catch (e: Exception ) {
220255 e.printStackTrace()
221256 }
222257
223- return Mat ()
258+ return null
224259 }
225260
226261 private fun saveImageAsync () {
@@ -539,6 +574,8 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
539574 container : ViewGroup ? ,
540575 savedInstanceState : Bundle ?
541576 ): View {
577+ tmpPhotoFile = File (requireContext().getExternalFilesDir(Environment .DIRECTORY_PICTURES ), " tmp.jpg" )
578+
542579 binding = MainFragmentBinding .inflate(inflater)
543580
544581 updateButtons()
0 commit comments