Skip to content
This repository has been archived by the owner on Sep 15, 2023. It is now read-only.

Commit

Permalink
Merge pull request #234 from admin-ch/feature/pdf-import-improvements
Browse files Browse the repository at this point in the history
Feature/pdf import improvements
  • Loading branch information
benz-ubique authored Aug 4, 2021
2 parents fd8d8cc + 9d40953 commit 43efbfb
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,23 @@ import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Rect
import android.graphics.pdf.PdfRenderer
import android.os.ParcelFileDescriptor
import com.google.zxing.*
import com.google.zxing.common.HybridBinarizer
import java.io.File
import java.lang.Integer.min
import java.util.*
import kotlin.math.roundToInt

object QRCodeReaderHelper {

object QRCodeReaderHelper {
private val hints = mapOf(
DecodeHintType.POSSIBLE_FORMATS to arrayListOf(BarcodeFormat.QR_CODE),
DecodeHintType.TRY_HARDER to true,
)

private const val PDF_PAGE_LIMIT = 5
private val reader = MultiFormatReader().apply { setHints(hints) }

fun decodeQrCode(bitmap: Bitmap): String? {
Expand All @@ -52,36 +54,45 @@ object QRCodeReaderHelper {
return decoded
}

fun pdfToBitmap(context: Context, pdfFile: File): ArrayList<Bitmap> {
fun pdfToBitmaps(context: Context, pdfFile: File): ArrayList<Bitmap> {
val bitmaps = arrayListOf<Bitmap>()
try {
val renderer = PdfRenderer(ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY))
var bitmap: Bitmap?
val pageCount = renderer.pageCount

for (i in 0 until min(pageCount, 5)) {
for (i in 0 until min(pageCount, PDF_PAGE_LIMIT)) {
val page: PdfRenderer.Page = renderer.openPage(i)
val width = context.resources.displayMetrics.densityDpi / 72 * page.width
val height = context.resources.displayMetrics.densityDpi / 72 * page.height
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)

val canvas = Canvas(bitmap)
canvas.drawColor(Color.WHITE)
canvas.drawBitmap(bitmap, 0.0f, 0.0f, null)
// PDF width/height are given in "points pt" such that 1 pt = 1/72 inch
// => 72 "dots-per-inch dpi" <==> scale = 1
val scale: Float = context.resources.displayMetrics.densityDpi / 72f
val pixelWidth = (scale * page.width).roundToInt()
val pixelHeight = (scale * page.height).roundToInt()

val r = Rect(0, 0, width, height)
page.render(bitmap, r, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT)
bitmaps.add(bitmap)
// Try both the scaled and the unscaled version
bitmaps.add(page.renderToBitmap(pixelWidth, pixelHeight))
bitmaps.add(page.renderToBitmap(page.width, page.height))

page.close()
}
renderer.close()

} catch (ex: Exception) {
ex.printStackTrace()
}

return bitmaps
}

private fun PdfRenderer.Page.renderToBitmap(pixelWidth: Int, pixelHeight: Int): Bitmap {
val bitmap = Bitmap.createBitmap(pixelWidth, pixelHeight, Bitmap.Config.ARGB_8888)

// Make sure the bitmap's background is not transparent (which can cause issues for QR code detection)
bitmap.eraseColor(Color.WHITE)

// Draw the page onto the bitmap. Internally, this will scale the page to fit the bitmap (unless transform != null).
this.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT)

return bitmap
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class PdfViewModel(application: Application) : AndroidViewModel(application) {
val outputFile: File = File.createTempFile("certificate", PDF_FILE_EXTENSION, getApplication<Application>().cacheDir)
inputStream?.copyTo(outputFile.outputStream())

val bitmaps = QRCodeReaderHelper.pdfToBitmap(getApplication<Application>(), outputFile)
val bitmaps = QRCodeReaderHelper.pdfToBitmaps(getApplication<Application>(), outputFile)

for (bitmap in bitmaps) {
val decode = QRCodeReaderHelper.decodeQrCode(bitmap)
Expand All @@ -86,14 +86,14 @@ class PdfViewModel(application: Application) : AndroidViewModel(application) {
return@launch
}
}

outputFile.delete()
} catch (e: Exception) {
e.printStackTrace()
}

pdfImportMutableLiveData.postValue(
PdfImportState.DONE(DecodeState.ERROR(StateError(PdfErrorCodes.NO_QR_CODE_FOUND, "The PDF was not be imported")))
PdfImportState.DONE(DecodeState.ERROR(StateError(PdfErrorCodes.NO_QR_CODE_FOUND, "No QR found in the PDF")))
)
}
}
Expand Down

0 comments on commit 43efbfb

Please sign in to comment.