Rudimentary thumbnail pixels-based autocrop detection.

A better solution would be using element bounds, but that requires a higher API level so I need a working fallback.
This commit is contained in:
Luke Hubmayer-Werner 2024-08-14 22:18:06 +09:30
parent 9a2b5ce297
commit a74ccdcfcb
5 changed files with 20 additions and 39 deletions

View File

@ -9,7 +9,7 @@ android {
defaultConfig { defaultConfig {
applicationId = "com.lhw.pdf" applicationId = "com.lhw.pdf"
minSdk = 25 minSdk = 26
targetSdk = 35 targetSdk = 35
versionCode = 1 versionCode = 1
versionName = "1.0" versionName = "1.0"

View File

@ -28,51 +28,33 @@ import androidx.core.view.WindowInsetsCompat
import com.lhw.pdf.databinding.ActivityMainBinding import com.lhw.pdf.databinding.ActivityMainBinding
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.InputStream
import kotlin.math.min
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
private lateinit var fileCached: File
private lateinit var renderer: PdfRenderer
private val thumbnailWidth = 500 private val thumbnailWidth = 500
private val thumbnailHeight = 700 private val thumbnailHeight = 700
private val bitmapThumbnails = mutableMapOf<Int, Bitmap>() private lateinit var pdfDocument: PdfDocument
// private val bitmapPagesMain = mutableMapOf<Int, Bitmap>()
private val bitmapPagesPresentation = mutableMapOf<Int, Bitmap>()
private val testPdf = R.raw.testpdf
private lateinit var presentationScroll: HorizontalScrollView private lateinit var presentationScroll: HorizontalScrollView
private lateinit var presentationLayout: LinearLayout private lateinit var presentationLayout: LinearLayout
private fun initializeRenderer() { private fun inputStreamToCache(outputFilename: String, inputStream: InputStream): File {
val fileCached = File(cacheDir, outputFilename)
val output = FileOutputStream(fileCached) val output = FileOutputStream(fileCached)
val inputStream = resources.openRawResource(testPdf)
while (inputStream.available() > 0) { while (inputStream.available() > 0) {
inputStream.copyTo(output) inputStream.copyTo(output)
} }
inputStream.close() inputStream.close()
output.close() output.close()
val pfd = ParcelFileDescriptor.open(fileCached, ParcelFileDescriptor.MODE_READ_ONLY) return fileCached
renderer = PdfRenderer(pfd)
} }
private fun renderPagesToMap(map: MutableMap<Int, Bitmap>, width: Int, height: Int) { private fun initializePdfDocument() {
map.clear() val inputStream = resources.openRawResource(R.raw.testpdf)
val numPages = renderer.pageCount pdfDocument = PdfDocument(inputStreamToCache("cached.pdf", inputStream), true)
for (i in 0..<numPages) {
map[i] = renderPage(i, width, height)
}
}
private fun renderThumbnails() {
renderPagesToMap(bitmapThumbnails, thumbnailWidth, thumbnailHeight)
}
private fun renderPage(index: Int, width: Int, height: Int): Bitmap {
val page = renderer.openPage(index)
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
page.close()
return bitmap
} }
class MyPresentation(outerContext: Context, display: Display) : Presentation(outerContext, display) { class MyPresentation(outerContext: Context, display: Display) : Presentation(outerContext, display) {
@ -93,11 +75,11 @@ class MainActivity : AppCompatActivity() {
val metrics = DisplayMetrics() val metrics = DisplayMetrics()
presentationDisplay.getMetrics(metrics) presentationDisplay.getMetrics(metrics)
val maxHeight = metrics.heightPixels val maxHeight: Int = metrics.heightPixels
val maxWidth = maxHeight * 5 / 7 val maxWidth: Int = min(maxHeight*5/7, metrics.widthPixels)
renderPagesToMap(bitmapPagesPresentation, maxWidth, maxHeight) pdfDocument.renderPagesPresentation(maxWidth, maxHeight)
presentationLayout = LinearLayout(presentation.context) presentationLayout = LinearLayout(presentation.context)
for (bitmap in bitmapPagesPresentation.values) { for (bitmap in pdfDocument.bitmapPagesPresentation.values) {
val img = ImageView(this) val img = ImageView(this)
img.setImageBitmap(bitmap) img.setImageBitmap(bitmap)
presentationLayout.addView(img) presentationLayout.addView(img)
@ -138,11 +120,10 @@ class MainActivity : AppCompatActivity() {
setupActionBarWithNavController(navController, appBarConfiguration) setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController) navView.setupWithNavController(navController)
fileCached = File(cacheDir, "cached.pdf") initializePdfDocument()
initializeRenderer() pdfDocument.renderThumbnails(thumbnailWidth, thumbnailHeight)
renderThumbnails()
val container = findViewById<LinearLayout>(R.id.thumbnails_layout) val container = findViewById<LinearLayout>(R.id.thumbnails_layout)
for (bitmap in bitmapThumbnails.values) { for (bitmap in pdfDocument.bitmapThumbnails.values) {
val img = ImageView(this) val img = ImageView(this)
img.setImageBitmap(bitmap) img.setImageBitmap(bitmap)
container.addView(img) container.addView(img)

View File

@ -23,7 +23,7 @@ class GalleryFragment : Fragment() {
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
val galleryViewModel = val galleryViewModel =
ViewModelProvider(this).get(GalleryViewModel::class.java) ViewModelProvider(this)[GalleryViewModel::class.java]
_binding = FragmentGalleryBinding.inflate(inflater, container, false) _binding = FragmentGalleryBinding.inflate(inflater, container, false)
val root: View = binding.root val root: View = binding.root

View File

@ -23,7 +23,7 @@ class HomeFragment : Fragment() {
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
val homeViewModel = val homeViewModel =
ViewModelProvider(this).get(HomeViewModel::class.java) ViewModelProvider(this)[HomeViewModel::class.java]
_binding = FragmentHomeBinding.inflate(inflater, container, false) _binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root val root: View = binding.root

View File

@ -23,7 +23,7 @@ class SlideshowFragment : Fragment() {
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
val slideshowViewModel = val slideshowViewModel =
ViewModelProvider(this).get(SlideshowViewModel::class.java) ViewModelProvider(this)[SlideshowViewModel::class.java]
_binding = FragmentSlideshowBinding.inflate(inflater, container, false) _binding = FragmentSlideshowBinding.inflate(inflater, container, false)
val root: View = binding.root val root: View = binding.root