소스 검색

Implement export booklet pdf

Wayne 6 년 전
부모
커밋
393109e972

+ 1 - 0
build.gradle

@@ -48,6 +48,7 @@ dependencies {
     implementation project(':Bomo_for_Android_cloudModule')
     implementation project(':Bomo_for_Android_encodeModule')
     implementation project(':uikit')
+    implementation project(':pdfexport')
 
     implementation 'com.squareup.picasso:picasso:2.71828'
 }

+ 3 - 0
src/main/java/com/bomostory/sceneeditmodule/Config.kt

@@ -4,10 +4,13 @@ import android.os.Environment
 import java.io.File
 
 object Config {
+    private val ROOT = File(Environment.getExternalStorageDirectory(), "Bomo")
     private const val ASSETS_FOLDER_PATH = "/Android/yuheng"
     private const val PROJECTS_FOLDER_PATH = "/Android/yuheng/project"
     private const val IMAGE_FOLDER_PATH = "/Android/yuheng/image"
     val IMAGE_FOLDER = File(Environment.getExternalStorageDirectory(), IMAGE_FOLDER_PATH)
     val ASSETS_FOLDER = File(Environment.getExternalStorageDirectory(), ASSETS_FOLDER_PATH)
     val PROJECTS_FOLDER = File(Environment.getExternalStorageDirectory(), PROJECTS_FOLDER_PATH)
+
+    val PDF_FOLDER = File(ROOT, "pdf")
 }

+ 62 - 2
src/main/java/com/bomostory/sceneeditmodule/MovieEditActivity.kt

@@ -19,6 +19,7 @@ import com.bomostory.sceneeditmodule.basicdata.DataParser
 import com.bomostory.sceneeditmodule.basicdata.Music
 import com.bomostory.sceneeditmodule.basicdata.Project
 import com.bomostory.sceneeditmodule.basicdata.Scene
+import com.bomostory.sceneeditmodule.share.ExportPdfDialog
 import com.bomostory.sceneeditmodule.share.ShareDialog
 import com.bomostory.sceneeditmodule.utils.MoviePlayer
 import com.bomostory.sceneeditmodule.utils.MusicPlayer
@@ -272,8 +273,67 @@ class MovieEditActivity : AppCompatActivity(),
             name = project?.name ?: ""
             author = project?.author ?: ""
             onClickMore = Runnable { saveMovie() }
-        }
-                .show(supportFragmentManager)
+            onClickExportPdf = Runnable { onClickExportPdf() }
+        }.show(supportFragmentManager)
+    }
+
+    private fun onClickExportPdf() {
+        ExportPdfDialog().also { exportPdfDialog ->
+            exportPdfDialog.image1Path = project?.scene1File?.path ?: ""
+            exportPdfDialog.image2Path = project?.scene2File?.path ?: ""
+            exportPdfDialog.onClickPrint = Runnable {
+                when (exportPdfDialog.type) {
+                    ExportPdfDialog.Type.Standard -> {
+
+                    }
+                    ExportPdfDialog.Type.Booklet -> {
+                        val name = "bookelet_${project?.name}_${System.currentTimeMillis()}.pdf"
+                        if (!Config.PDF_FOLDER.exists()) {
+                            Config.PDF_FOLDER.mkdirs()
+                        }
+                        val file = File(Config.PDF_FOLDER, name)
+                        file.createNewFile()
+                        val pd = ProgressDialog(this@MovieEditActivity).apply {
+                            setCancelable(false)
+                        }
+                        PdfMaker.makeBooklet(this@MovieEditActivity, project!!, file)
+                                .subscribeOn(Schedulers.io())
+                                .observeOn(AndroidSchedulers.mainThread())
+                                .doOnSubscribe { pd.show() }
+                                .doFinally {
+                                    pd.dismiss()
+                                    exportPdfDialog.dismiss()
+                                }
+                                .subscribe({
+                                    val progress = (it * 100).toInt()
+                                    val msg = if (progress >= 100) {
+                                        "processing ..."
+                                    } else {
+                                        "$progress%"
+                                    }
+                                    pd.setMessage(msg)
+                                }, {
+                                }, {
+                                    AlertDialog.Builder(this@MovieEditActivity)
+                                            .setMessage("Complete")
+                                            .setPositiveButton("View") { _, _ ->
+                                                val uri = Uri.parse(file.absolutePath)
+                                                val intent = Intent(Intent.ACTION_VIEW, uri).apply {
+                                                    setDataAndType(uri, "application/pdf")
+                                                }
+                                                if (intent.resolveActivity(packageManager) != null) {
+                                                    Intent.createChooser(intent, "").apply {
+                                                        startActivity(this)
+                                                    }
+                                                } else {
+                                                    Toast.makeText(this@MovieEditActivity, "No app can view pdf", Toast.LENGTH_SHORT).show()
+                                                }
+                                            }.show()
+                                })
+                    }
+                }
+            }
+        }.show(supportFragmentManager)
     }
 
     private fun saveMovie() {

+ 71 - 0
src/main/java/com/bomostory/sceneeditmodule/PdfMaker.kt

@@ -0,0 +1,71 @@
+package com.bomostory.sceneeditmodule
+
+import android.content.Context
+import android.graphics.*
+import com.bomostory.pdfexport.PdfBookWriter
+import com.bomostory.sceneeditmodule.basicdata.Project
+import com.example.tfat.myapplication.R
+import io.reactivex.Observable
+import java.io.File
+
+object PdfMaker {
+    fun makeBooklet(context: Context, project: Project, file: File): Observable<Float> {
+        return Observable.create { emitter ->
+            val total = (2 + project.story?.scenes?.size!!).toFloat()
+            var progress = 0
+            val width = 1920 / 2
+            val height = 1080
+            val name = project?.name ?: ""
+            val author = project?.author ?: ""
+            val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
+                color = Color.WHITE
+                textSize = 100f
+                textAlign = Paint.Align.CENTER
+                flags += Paint.FAKE_BOLD_TEXT_FLAG
+            }
+            emitter.onNext(progress++ / total)
+            /** front **/
+            val front = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444).apply {
+                Canvas(this).apply {
+                    drawColor(Color.parseColor("#faa600"))
+                    val marginBottom = height / 20
+                    val rect = Rect(0, height - height / 3 - marginBottom, width, height - marginBottom)
+                    val p = Paint(Paint.ANTI_ALIAS_FLAG).apply {
+                        color = Color.parseColor("#66ffffff")
+                        style = Paint.Style.FILL_AND_STROKE
+                    }
+                    drawRect(rect, p)
+                    drawText(name, rect.centerX().toFloat(), rect.centerY().toFloat(), paint)
+                }
+            }
+            emitter.onNext(progress++ / total)
+            /** back **/
+            val back = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444).apply {
+                Canvas(this).apply {
+                    drawColor(Color.parseColor("#faa600"))
+                    val drawable = context.getDrawable(R.drawable.ic_logo_full_white)
+                    val marginBottom = this.height / 10
+                    val w = this.width / 3
+                    val scale = w.toFloat() / drawable.intrinsicWidth.toFloat()
+                    val h = drawable.intrinsicHeight * scale
+                    val left = (this.width - w) / 2
+                    val top = (this.height - h) - marginBottom
+                    val right = (this.width + w) / 2
+                    val bottom = (this.height) - marginBottom
+                    drawable.setBounds(left, top.toInt(), right, bottom)
+                    drawable.draw(this)
+                }
+            }
+            emitter.onNext(progress++ / total)
+            /** pages **/
+            val pdfBookWriter = PdfBookWriter(file, front, back)
+            project.story?.scenes?.forEach {
+                val bitmap = SceneDrawer.drawScene(it, 0, width, height) ?: return@forEach
+                pdfBookWriter.addImage(bitmap)
+                emitter.onNext(progress++ / total)
+            }
+            pdfBookWriter.finish()
+            emitter.onComplete()
+        }
+    }
+}

+ 35 - 0
src/main/java/com/bomostory/sceneeditmodule/SceneDrawer.kt

@@ -0,0 +1,35 @@
+package com.bomostory.sceneeditmodule
+
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Canvas
+import android.graphics.Paint
+import com.bomostory.sceneeditmodule.basicdata.Scene
+import kotlin.math.pow
+
+object SceneDrawer {
+    fun drawScene(scene: Scene, trackX: Int, scaleWidth: Int, scaleHeight: Int): Bitmap? {
+        var sceneBitmap: Bitmap? = null
+
+        scene?.apply {
+            sceneBitmap = BitmapFactory.decodeFile(backgroundPath)
+            sceneBitmap = Bitmap.createScaledBitmap(sceneBitmap, scaleWidth, scaleHeight, true)
+
+            val canvas = Canvas(sceneBitmap)
+            for (layer in layers) {
+                for (actor in layer.actors) {
+                    var actorBitmap = BitmapFactory.decodeFile(actor.resourcePath)
+                    actorBitmap = Bitmap.createScaledBitmap(actorBitmap, actor.sideLength, actor.sideLength, true)
+
+                    canvas.save()
+                    canvas.translate(trackX / 2f.pow(layers.indexOf(layer)), 0f)
+                    canvas.drawBitmap(actorBitmap, actor.positionX.toFloat(), actor.positionY.toFloat(), Paint())
+                    canvas.restore()
+
+                    actorBitmap.recycle()
+                }
+            }
+        }
+        return sceneBitmap
+    }
+}

+ 3 - 31
src/main/java/com/bomostory/sceneeditmodule/SuperMovieMaker.kt

@@ -1,9 +1,6 @@
 package com.bomostory.sceneeditmodule
 
 import android.graphics.Bitmap
-import android.graphics.BitmapFactory
-import android.graphics.Canvas
-import android.graphics.Paint
 import android.util.Log
 import com.bomostory.sceneeditmodule.MovieEditActivity.Companion.FPS
 import com.bomostory.sceneeditmodule.basicdata.Music
@@ -21,7 +18,6 @@ import java.util.concurrent.Semaphore
 import kotlin.collections.ArrayList
 import kotlin.collections.LinkedHashMap
 import kotlin.collections.set
-import kotlin.math.pow
 
 class SuperMovieMaker {
 
@@ -53,7 +49,7 @@ class SuperMovieMaker {
                 Completable.create {
                     project?.story?.apply {
                         val scene = scenes[frameData.sceneIndex]
-                        val bitmap = drawScene(scene, frameData.x, scaleWidth, scaleHeight)
+                        val bitmap = SceneDrawer.drawScene(scene, frameData.x, scaleWidth, scaleHeight)
                         movieBuilder.addImage(i, bitmap!!).blockingSubscribe()
                     }
                     it.onComplete()
@@ -128,7 +124,7 @@ class SuperMovieMaker {
         return Observable.create<AbstractMap.SimpleEntry<Int, Bitmap>> {
             scene?.apply {
                 record?.apply {
-                    var bitmap = drawScene(scene, 0, scaleWidth, scaleHeight)
+                    var bitmap = SceneDrawer.drawScene(scene, 0, scaleWidth, scaleHeight)
                     var bitmapIndex = 0
                     var trackPosition = -1
 
@@ -138,7 +134,7 @@ class SuperMovieMaker {
                                 preBitmap = bitmap
                                 preBitmap?.recycle()
 
-                                bitmap = drawScene(scene, track.positionX, scaleWidth, scaleHeight)
+                                bitmap = SceneDrawer.drawScene(scene, track.positionX, scaleWidth, scaleHeight)
                                 trackPosition = tracks.indexOf(track)
                             }
                         }
@@ -153,30 +149,6 @@ class SuperMovieMaker {
         }
     }
 
-    private fun drawScene(scene: Scene, trackX: Int, scaleWidth: Int, scaleHeight: Int): Bitmap? {
-        var sceneBitmap: Bitmap? = null
-
-        scene?.apply {
-            sceneBitmap = BitmapFactory.decodeFile(backgroundPath)
-            sceneBitmap = Bitmap.createScaledBitmap(sceneBitmap, scaleWidth, scaleHeight, true)
-
-            val canvas = Canvas(sceneBitmap)
-            for (layer in layers) {
-                for (actor in layer.actors) {
-                    var actorBitmap = BitmapFactory.decodeFile(actor.resourcePath)
-                    actorBitmap = Bitmap.createScaledBitmap(actorBitmap, actor.sideLength, actor.sideLength, true)
-
-                    canvas.save()
-                    canvas.translate(trackX / 2f.pow(layers.indexOf(layer)), 0f)
-                    canvas.drawBitmap(actorBitmap, actor.positionX.toFloat(), actor.positionY.toFloat(), Paint())
-                    canvas.restore()
-
-                    actorBitmap.recycle()
-                }
-            }
-        }
-        return sceneBitmap
-    }
 
     data class FrameData(val sceneIndex: Int, val x: Int, var repeat: Int)
 }

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 76 - 0
src/main/res/drawable/ic_logo_full_white.xml