From 97c3f597416c4c52f9129a8960e1360d34298ecd Mon Sep 17 00:00:00 2001 From: dece Date: Fri, 1 May 2020 19:52:09 +0200 Subject: [PATCH] Init --- .gitignore | 14 ++ .idea/codeStyles/Project.xml | 122 +++++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/gradle.xml | 19 ++ .idea/misc.xml | 9 + .idea/runConfigurations.xml | 12 ++ .idea/vcs.xml | 6 + app/.gitignore | 1 + app/build.gradle | 36 ++++ app/proguard-rules.pro | 21 +++ .../zmingz/ExampleInstrumentedTest.kt | 24 +++ app/src/main/AndroidManifest.xml | 21 +++ .../dev/lowrespalmtree/zmingz/MainActivity.kt | 145 +++++++++++++++ .../drawable-v24/ic_launcher_foreground.xml | 30 +++ .../res/drawable/ic_launcher_background.xml | 170 +++++++++++++++++ app/src/main/res/layout/activity_main.xml | 104 +++++++++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3593 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5339 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2636 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3388 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4926 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7472 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7909 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 11873 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 10652 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 16570 bytes app/src/main/res/values/colors.xml | 6 + app/src/main/res/values/strings.xml | 6 + app/src/main/res/values/styles.xml | 11 ++ build.gradle | 28 +++ gradle.properties | 21 +++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 ++++++++++++++++++ gradlew.bat | 84 +++++++++ settings.gradle | 2 + 38 files changed, 1085 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 .idea/vcs.xml create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/dev/lowrespalmtree/zmingz/ExampleInstrumentedTest.kt create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/dev/lowrespalmtree/zmingz/MainActivity.kt create mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..603b140 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..88ea3aa --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,122 @@ + + + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+ + +
+
\ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..440480e --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..37a7509 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..bc3ccd2 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,36 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.2" + + defaultConfig { + applicationId "dev.lowrespalmtree.zmingz" + minSdkVersion 26 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.core:core-ktx:1.2.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + + implementation 'com.arthenica:mobile-ffmpeg-full:4.3.2' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/dev/lowrespalmtree/zmingz/ExampleInstrumentedTest.kt b/app/src/androidTest/java/dev/lowrespalmtree/zmingz/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..20c99e0 --- /dev/null +++ b/app/src/androidTest/java/dev/lowrespalmtree/zmingz/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package dev.lowrespalmtree.zmingz + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("dev.lowrespalmtree.zmingz", appContext.packageName) + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..7c5663c --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/dev/lowrespalmtree/zmingz/MainActivity.kt b/app/src/main/java/dev/lowrespalmtree/zmingz/MainActivity.kt new file mode 100644 index 0000000..1835ddc --- /dev/null +++ b/app/src/main/java/dev/lowrespalmtree/zmingz/MainActivity.kt @@ -0,0 +1,145 @@ +package dev.lowrespalmtree.zmingz + +import android.content.Intent +import android.graphics.BitmapFactory +import android.os.AsyncTask +import android.os.Bundle +import android.provider.MediaStore +import android.util.Log +import android.view.View +import androidx.appcompat.app.AppCompatActivity +import com.arthenica.mobileffmpeg.Config.RETURN_CODE_CANCEL +import com.arthenica.mobileffmpeg.Config.RETURN_CODE_SUCCESS +import com.arthenica.mobileffmpeg.FFmpeg +import kotlinx.android.synthetic.main.activity_main.* +import java.io.File +import java.io.FileOutputStream +import java.lang.ref.WeakReference + +class MainActivity: AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + } + + fun openFile(v: View) { + val req: Int + val pickIntent = when (v.id) { + buttonImage.id -> { + req = REQ_PICK_IMG + Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) + } + buttonVideo.id -> { + req = REQ_PICK_VID + Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI) + } + else -> return + } + startActivityForResult(pickIntent, req) + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + when (requestCode) { + REQ_PICK_IMG, REQ_PICK_VID -> handlePickResult(requestCode, resultCode, data) + else -> super.onActivityResult(requestCode, resultCode, data) + } + } + + @Suppress("UNUSED_PARAMETER") + private fun handlePickResult(requestCode: Int, resultCode: Int, data: Intent?) { + val uri = data?.data + ?: return Unit .also { Log.e(TAG, "No intent or data.") } + val uriPath = uri.path + ?: return Unit .also { Log.e(TAG, "No path in URI") } + val extension = getFileExtension(uriPath) + + // Copy picked file to cache dir for FFmpeg. + val inputFile = File.createTempFile("input", ".$extension", cacheDir) + contentResolver.openInputStream(uri).use { inputStream -> + if (inputStream == null) + return Unit .also { Log.e(TAG, "Could not open input file") } + FileOutputStream(inputFile).use { fos -> + fos.buffered().write(inputStream.buffered().readBytes()) + } + } + + val outputFile1 = File.createTempFile("output1", ".$extension", cacheDir) + MirrorTask(WeakReference(this), requestCode, 1) + .execute(inputFile.canonicalPath, outputFile1.canonicalPath, VF1) + val outputFile2 = File.createTempFile("output2", ".$extension", cacheDir) + MirrorTask(WeakReference(this), requestCode, 2) + .execute(inputFile.canonicalPath, outputFile2.canonicalPath, VF2) + } + + class MirrorTask( + private val activity: WeakReference, + private val requestCode: Int, + private val index: Int + ): AsyncTask() { + private lateinit var outputPath: String + + override fun doInBackground(vararg params: String?): Boolean { + val inputPath = params[0]!! + outputPath = params[1]!! + val vf = params[2]!! + val command = "-i $inputPath -vf \"$vf\" -y $outputPath" + return when (val rc = FFmpeg.execute(command)) { + RETURN_CODE_SUCCESS -> true. also { Log.d(TAG, "ffmpeg success") } + RETURN_CODE_CANCEL -> false .also { Log.d(TAG, "ffmpeg canceled") } + else -> false .also { Log.d(TAG, "ffmpeg failed with rc $rc") } + } + } + + override fun onPostExecute(result: Boolean?) { + if (result == true) { + activity.get()?.updateViews(requestCode, index, outputPath) + } + } + + } + + internal fun updateViews(requestCode: Int, viewIndex: Int, outputPath: String) { + if (requestCode == REQ_PICK_IMG) { + if (imageLayout.visibility != View.VISIBLE) { + videoLayout.visibility = View.GONE + imageLayout.visibility = View.VISIBLE + } + val mirrored = BitmapFactory.decodeFile(outputPath) + val view = when (viewIndex) { + 1 -> imageView1 + 2 -> imageView2 + else -> return + } + view.setImageBitmap(mirrored) + } else if (requestCode == REQ_PICK_VID) { + if (videoLayout.visibility != View.VISIBLE) { + imageLayout.visibility = View.GONE + videoLayout.visibility = View.VISIBLE + } + val view = when (viewIndex) { + 1 -> videoView1 + 2 -> videoView2 + else -> return + } + view.setVideoPath(outputPath) + view.setOnPreparedListener { mp -> mp.isLooping = true } + view.start() + } + } + + companion object { + private const val TAG = "ZMINGZ" + private const val REQ_PICK_IMG = 1 + private const val REQ_PICK_VID = 2 + private const val VF1 = "crop=iw/2:ih:0:0,split[left][tmp];[tmp]hflip[right];[left][right] hstack" + private const val VF2 = "crop=iw/2:ih:iw/2:0,split[left][tmp];[tmp]hflip[right];[right][left] hstack" + + private fun getFileExtension(path: String): String { + if (!path.contains('.')) + return "" + return path.substring(path.lastIndexOf('.') + 1) + } + } + +} diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..26342be --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + +