@@ -2,6 +2,7 @@ package com.dan.perspective
22
33import android.content.Intent
44import android.graphics.Bitmap
5+ import android.graphics.BitmapFactory
56import android.graphics.Point
67import android.graphics.PointF
78import android.media.MediaScannerConnection
@@ -17,10 +18,8 @@ import org.opencv.core.Core.mean
1718import org.opencv.core.Core.minMaxLoc
1819import org.opencv.core.CvType.*
1920import org.opencv.core.Mat
20- import org.opencv.core.MatOfInt
2121import org.opencv.core.Scalar
2222import org.opencv.core.Size
23- import org.opencv.imgcodecs.Imgcodecs
2423import org.opencv.imgproc.Imgproc.*
2524import org.opencv.xphoto.Xphoto
2625import java.io.File
@@ -39,9 +38,6 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
3938
4039 const val INTENT_OPEN_IMAGE = 2
4140
42- const val ALPHA_8_TO_16 = 256.0
43- const val ALPHA_16_TO_8 = 1.0 / ALPHA_8_TO_16
44-
4541 const val AUTO_DETECT_WORK_SIZE = 1024
4642
4743 fun show (activity : MainActivity ) {
@@ -65,7 +61,7 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
6561 menuSave?.isEnabled = ! inputImage.empty()
6662
6763 menuPrevPerspective = menu.findItem(R .id.prevPerspective)
68- menuPrevPerspective?.isEnabled = ! inputImage.empty() && activity. settings.prevHeight > 0
64+ menuPrevPerspective?.isEnabled = ! inputImage.empty() && settings.prevHeight > 0
6965 }
7066
7167 override fun onDestroyOptionsMenu () {
@@ -92,24 +88,24 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
9288 }
9389
9490 R .id.prevPerspective -> {
95- if (activity. settings.prevHeight < 1 ) return true
91+ if (settings.prevHeight < 1 ) return true
9692 if (inputImage.empty()) return true
9793
9894 binding.imageEdit.setPerspective(
99- PointF (activity. settings.prevLeftTopX * inputImage.width() / activity. settings.prevWidth,
100- activity. settings.prevLeftTopY * inputImage.height() / activity. settings.prevHeight
95+ PointF (settings.prevLeftTopX * inputImage.width() / settings.prevWidth,
96+ settings.prevLeftTopY * inputImage.height() / settings.prevHeight
10197 ),
10298 PointF (
103- activity. settings.prevRightTopX * inputImage.width() / activity. settings.prevWidth,
104- activity. settings.prevRightTopY * inputImage.height() / activity. settings.prevHeight
99+ settings.prevRightTopX * inputImage.width() / settings.prevWidth,
100+ settings.prevRightTopY * inputImage.height() / settings.prevHeight
105101 ),
106102 PointF (
107- activity. settings.prevLeftBottomX * inputImage.width() / activity. settings.prevWidth,
108- activity. settings.prevLeftBottomY * inputImage.height() / activity. settings.prevHeight
103+ settings.prevLeftBottomX * inputImage.width() / settings.prevWidth,
104+ settings.prevLeftBottomY * inputImage.height() / settings.prevHeight
109105 ),
110106 PointF (
111- activity. settings.prevRightBottomX * inputImage.width() / activity. settings.prevWidth,
112- activity. settings.prevRightBottomY * inputImage.height() / activity. settings.prevHeight
107+ settings.prevRightBottomX * inputImage.width() / settings.prevWidth,
108+ settings.prevRightBottomY * inputImage.height() / settings.prevHeight
113109 )
114110 )
115111
@@ -139,28 +135,6 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
139135 startActivityForResult(intent, INTENT_OPEN_IMAGE )
140136 }
141137
142- private fun convertToDepth (image : Mat , depth : Int ) : Mat {
143- when ( depth ) {
144- Settings .DEPTH_8_BITS -> {
145- if (CV_16UC3 == image.type()) {
146- val newImage = Mat ()
147- image.convertTo(newImage, CV_8UC3 , ALPHA_16_TO_8 )
148- return newImage
149- }
150- }
151-
152- Settings .DEPTH_16_BITS -> {
153- if (CV_8UC3 == image.type()) {
154- val newImage = Mat ()
155- image.convertTo(newImage, CV_16UC3 , ALPHA_8_TO_16 )
156- return newImage
157- }
158- }
159- }
160-
161- return image
162- }
163-
164138 private fun matToBitmap (image : Mat ): Bitmap ? {
165139 if (image.empty()) return null
166140
@@ -170,7 +144,7 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
170144 Bitmap .Config .ARGB_8888
171145 )
172146
173- Utils .matToBitmap( convertToDepth( image, Settings . DEPTH_8_BITS ) , bitmap)
147+ Utils .matToBitmap( image, bitmap)
174148 return bitmap
175149 }
176150
@@ -220,93 +194,70 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
220194 binding.checkBoxInpaint.isEnabled = enabled
221195
222196 menuSave?.isEnabled = enabled
223- menuPrevPerspective?.isEnabled = enabled && activity. settings.prevHeight > 0
197+ menuPrevPerspective?.isEnabled = enabled && settings.prevHeight > 0
224198 }
225199
226200 private fun loadImage (uri : Uri ) : Mat {
227- // Can't create MatOfByte from kotlin ByteArray, but works correctly from java byte[]
228- val image = OpenCVLoadImageFromUri .load(uri, activity.contentResolver)
229- if (null == image || image.empty()) return Mat ()
230-
231- inputUri = uri
232- val imageRGB = Mat ()
233-
234- when (image.type()) {
235- CV_8UC3 , CV_16UC3 -> cvtColor(image, imageRGB, COLOR_BGR2RGB )
236- CV_8UC4 , CV_16UC4 -> cvtColor(image, imageRGB, COLOR_BGRA2RGB )
237- else -> return Mat ()
201+ try {
202+ val inputStream = requireContext().contentResolver.openInputStream(uri) ? : return Mat ()
203+ val bitmap = BitmapFactory .decodeStream(inputStream)
204+ val image = Mat ()
205+ Utils .bitmapToMat(bitmap, image)
206+ inputStream.close()
207+ return image
208+ } catch (e: Exception ) {
209+ e.printStackTrace()
238210 }
239211
240- return convertToDepth(imageRGB, activity.settings.engineDepth )
212+ return Mat ( )
241213 }
242214
243215 private fun saveImageAsync () {
244216 if (inputImage.empty()) return
245217
246218 warpImageAsync( binding.checkBoxInpaint.isChecked )
247219 if (outputImage.empty()) return
220+ val bitmap = matToBitmap(outputImage) ? : return
248221
249222 setBusyDialogTitleAsync(MSG_SAVE )
250223
251- val outputExtension = activity.settings.outputExtension()
252-
253224 try {
254- var fileName = " ${outputName} .${outputExtension} "
255- var fileFullPath = Settings .SAVE_FOLDER + " / " + fileName
225+ var fileName = " ${outputName} .jpg "
226+ var file = File ( Settings .SAVE_FOLDER , fileName)
256227 var counter = 0
257- while (File (fileFullPath) .exists() && counter < 998 ) {
228+ while (file .exists() && counter < 998 ) {
258229 counter++
259230 val counterStr = " %03d" .format(counter)
260- fileName = " ${outputName} _${counterStr} .${outputExtension} "
261- fileFullPath = Settings .SAVE_FOLDER + " / " + fileName
231+ fileName = " ${outputName} _${counterStr} .jpg "
232+ file = File ( Settings .SAVE_FOLDER , fileName)
262233 }
263234
264- val outputRGB = Mat ()
265- cvtColor(outputImage, outputRGB, COLOR_BGR2RGB )
266-
267- var outputDepth = Settings .DEPTH_AUTO
268-
269- if (Settings .OUTPUT_TYPE_JPEG == activity.settings.outputType
270- || (Settings .OUTPUT_TYPE_PNG == activity.settings.outputType && Settings .DEPTH_8_BITS == activity.settings.pngDepth)
271- || (Settings .OUTPUT_TYPE_TIFF == activity.settings.outputType && Settings .DEPTH_8_BITS == activity.settings.tiffDepth)
272- ) {
273- outputDepth = Settings .DEPTH_8_BITS
274- } else if ((Settings .OUTPUT_TYPE_PNG == activity.settings.outputType && Settings .DEPTH_16_BITS == activity.settings.pngDepth)
275- || (Settings .OUTPUT_TYPE_TIFF == activity.settings.outputType && Settings .DEPTH_16_BITS == activity.settings.tiffDepth)
276- ) {
277- outputDepth = Settings .DEPTH_16_BITS
278- }
279-
280- File (fileFullPath).parentFile?.mkdirs()
281-
282- val outputParams = MatOfInt ()
283-
284- if (Settings .OUTPUT_TYPE_JPEG == activity.settings.outputType) {
285- outputParams.fromArray(Imgcodecs .IMWRITE_JPEG_QUALITY , activity.settings.jpegQuality)
286- }
235+ file.parentFile?.mkdirs()
287236
288- Imgcodecs .imwrite(fileFullPath, convertToDepth(outputRGB, outputDepth), outputParams)
237+ val outputStream = file.outputStream()
238+ bitmap.compress(Bitmap .CompressFormat .JPEG , settings.jpegQuality, outputStream)
239+ outputStream.close()
289240
290241 inputUri?.let { uri ->
291- ExifTools .copyExif( activity.contentResolver, uri, fileFullPath )
242+ ExifTools .copyExif( activity.contentResolver, uri, file )
292243 }
293244
294245 runOnUiThread {
295246 // Add it to gallery
296- MediaScannerConnection .scanFile(context, arrayOf(fileFullPath ), null , null )
247+ MediaScannerConnection .scanFile(context, arrayOf(file.absolutePath ), null , null )
297248
298249 val perspectivePoints = binding.imageEdit.getPerspective()
299- activity. settings.prevWidth = outputImage.width()
300- activity. settings.prevHeight = outputImage.height()
301- activity. settings.prevLeftTopX = perspectivePoints.pointLeftTop.x
302- activity. settings.prevLeftTopY = perspectivePoints.pointLeftTop.y
303- activity. settings.prevRightTopX = perspectivePoints.pointRightTop.x
304- activity. settings.prevRightTopY = perspectivePoints.pointRightTop.y
305- activity. settings.prevLeftBottomX = perspectivePoints.pointLeftBottom.x
306- activity. settings.prevLeftBottomY = perspectivePoints.pointLeftBottom.y
307- activity. settings.prevRightBottomX = perspectivePoints.pointRightBottom.x
308- activity. settings.prevRightBottomY = perspectivePoints.pointRightBottom.y
309- activity. settings.saveProperties()
250+ settings.prevWidth = outputImage.width()
251+ settings.prevHeight = outputImage.height()
252+ settings.prevLeftTopX = perspectivePoints.pointLeftTop.x
253+ settings.prevLeftTopY = perspectivePoints.pointLeftTop.y
254+ settings.prevRightTopX = perspectivePoints.pointRightTop.x
255+ settings.prevRightTopY = perspectivePoints.pointRightTop.y
256+ settings.prevLeftBottomX = perspectivePoints.pointLeftBottom.x
257+ settings.prevLeftBottomY = perspectivePoints.pointLeftBottom.y
258+ settings.prevRightBottomX = perspectivePoints.pointRightBottom.x
259+ settings.prevRightBottomY = perspectivePoints.pointRightBottom.y
260+ settings.saveProperties()
310261
311262 menuPrevPerspective?.isEnabled = true
312263 }
@@ -433,7 +384,7 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
433384
434385 val image = Mat ()
435386 resize(
436- convertToDepth( inputImage, Settings . DEPTH_8_BITS ) ,
387+ inputImage,
437388 image,
438389 Size ( AUTO_DETECT_WORK_SIZE .toDouble(), AUTO_DETECT_WORK_SIZE .toDouble()) ,
439390 0.0 ,
0 commit comments