Hey guys! We have this existing API exclusively us...
# compose
j
Hey guys! We have this existing API exclusively used only on iOS before. All of the asset/icon urls (hundreds of them) are in PDF format, which is a struggle now that I am implementing the Android app. Is there an easy way to support rendering PDF inside an image using
coil-compose
? Could you share some references? (perhaps a custom fetcher implementation or a forked github repository) Just want to look for any ideas before going to the last resort of migrating all assets from PDF to SVG. 🙏
m
Here is some code to render PDF into an image on Android. It’s not perfect but it works for me.
Copy code
fun native_pdfBytesToImgBytes(
    pdfBytes: ByteArray,
    fitWidth: Double,
    fitHeight: Double,
    pageIndex: Int,
    imageFormat: String
): ByteArray? {
//    Why is this deprecated and hidden? It would be the perfect fit here.
//    val pfd = ParcelFileDescriptor.fromData(pdfBytes, "PDF")

    val file = File.createTempFile("scratch", "pdf")
    try {
        file.writeBytes(pdfBytes)
        val fd = ParcelFileDescriptor.open(file, MODE_READ_ONLY)
        PdfRenderer(fd).use { pdfRenderer ->
            pdfRenderer.openPage(pageIndex).use { page ->
                val fitScale = fitScale(page.width.toDouble(), page.height.toDouble(), fitWidth, fitHeight)
                val pageWidth = (page.width * fitScale).toInt()
                val pageHeight = (page.height * fitScale).toInt()
                val bitmap = Bitmap.createBitmap(pageWidth, pageHeight, Bitmap.Config.ARGB_8888)
                page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
                val inMemoryOutputStream = ByteArrayOutputStream()
                bitmap.compress(imageFormat.toCompressFormat(), compQuality[imageFormat]!!, inMemoryOutputStream)
                return inMemoryOutputStream.toByteArray()
            }
        }
    } catch (e: Exception) {
        log.error(e) { "Could not render PDF." }
        return null
    } finally {
        file.delete()
    }
}
🙌 1
j
Thank you @Michael Paus, I ended up writing a similar one still using PdfRenderer, and added it as a decoder for coil. https://gist.github.com/jermainedilao/a8ebcab85f9a537de4ef92342e9daf99
m
Just one more hint. You should set an upper bound on the image size. There are PDFs in the wild which have a very large size. This is no problem if the PDF only contains vector data and you render it with a reasonable size but if you try to create a raster image with even 4 times this size it is likely to blow up your app if a user should ever stumble over such a PDF.
1
💡 1
j
Appreciate it!