android pdf框架-5,生成pdf

前面的文章都是如何展示pdf,这篇关于如何生成pdf文件.

使用图片生成pdf

原来我以为是高宽的问题,所以作了裁剪,后来发现是png的问题,一张png大小1000*1000左右,500k左右,生成的pdf达到5m,png转为jpg后会缩小到400k的图片,但生成的pdf会大大减小到600k左右.

在不使用分割法去加载页面,使用长图片生成的pdf如果不切割,那么读取的时候,解码可能内存溢出.这是使用recyclerview时发生的问题.所以我在代码里面作了切割.超过6000的高就切割分断,当然这样的pdf在其它的app看体验不太好.我把分割线去了,看着就像连续的图片.

使用vudroid查看器,因为它是根据页面分割法去加载,所以没有内存溢出的状况.但是现在自动切边还没有实现.使用recyclerview加载一整张图片,很容易实现自动切边.

使用mupdf生成

对于图片,生成pdf时,如果没有考虑内存的问题就比较容易了,如果考虑到内存可能会溢出,那么只能对图片切割处理,然后再生成页面.

切割后可以尽量以大的区域去展示pdf.

定义一个方法

fun createPdfFromImages(pdfPath: String?, imagePaths: List<String>): Boolean 

pdf存储的路径,与图片的路径,要支持多张图片生成pdf

假如生成的页面高宽值是8.3 * 72 * 2与11.7 * 72 * 2,就是8*11英寸的页面.好像是a2

那么生成页面时要处理图片大于这个高宽的情况.

以目前手机普遍在1080*1920的分辨率之上,所以我定义了最大的高为2160.当图片的高大于这个高度,比如微博里面有好多图片是长图,那么就要进行切割.

var mDocument: PDFDocument? = null
        try {
            mDocument = PDFDocument.openDocument(pdfPath) as PDFDocument
        } catch (e: Exception) {
            Log.d("TAG", "could not open:$pdfPath")
        }
        if (mDocument == null) {
            mDocument = PDFDocument()
        }

pdf的路径可以是新的,可以是旧的,所以先读取,如果没有读取到,可能是新的地址.如果是旧的地址,图片生成新的部分是追加到旧的后面的.

val resultPaths = processLargeImage(imagePaths)

        //空白页面必须是-1,否则会崩溃,但插入-1的位置的页面会成为最后一个,所以追加的时候就全部用-1就行了.
        var index = -1
        for (path in resultPaths) {
            val page = addPage(path, mDocument, index++)

            mDocument.insertPage(-1, page)
        }
        mDocument.save(pdfPath, OPTS);
private const val OPTS = "compress-images;compress;incremental;linearize;pretty;compress-fonts"

大体的流程就是这样的.剩下的就是处理图片切割的方式了.

图片切割
private fun processLargeImage(imagePaths: List<String>): List<String> {
        val options = BitmapFactory.Options()
        //默认值为false,如果设置成true,那么在解码的时候就不会返回bitmap,即bitmap = null。
        options.inJustDecodeBounds = true
        val maxHeight = PAPER_HEIGHT

        val result = arrayListOf<String>()
        for (path in imagePaths) {
            try {
                BitmapFactory.decodeFile(path, options)
                if (options.outHeight > maxHeight) {
                    //split image,maxheight=PAPER_HEIGHT
                    splitImages(result, path, options.outWidth, options.outHeight)
                } else {
                    //result.add(path)
                    val bitmapPath = compressImageFitPage(path, options.outWidth, options.outHeight)
                    result.add(bitmapPath)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        return result
    }

这里处理了两种,一种是大于高的图片,肯定切割,另一种是不大于高,但图片可能比较大,比如正方形的1400*1400的这种,如果直接使用它的高宽,生成的pdf会比较大,所以进行了屏幕如1080宽的适配操作.生成的pdf就不那么大了.

splitImages切割就是从图片顶点开始,按高度切割,然后保存在临时目录里面.

var top = 0f
        val right = 0 + width
        var bottom = PAPER_HEIGHT

        while (bottom < height) {
            val rect = android.graphics.Rect()
            rect.set(0, top.toInt(), right, bottom.toInt())
            splitImage(path, rect, result)

            top = bottom
            bottom += PAPER_HEIGHT
        }
        if (top < height) {
            val rect = android.graphics.Rect()
            rect.set(0, top.toInt(), right, height)
            splitImage(path, rect, result)
        }

切割图片后,与不切割的图片一样,做一次宽度适配

val mDecoder = BitmapRegionDecoder.newInstance(path, true)
        val bm: Bitmap = mDecoder.decodeRegion(rect, null)
        val file =
            File(
                PDFUtils.getExternalCacheDir(App.instance).path
                        //FileUtils.getStorageDirPath() + "/amupdf"
                        + File.separator + "create" + File.separator + System.currentTimeMillis() + ".jpg"
            )
        PDFUtils.saveBitmapToFile(bm, file, Bitmap.CompressFormat.JPEG, 100)
        Log.d("TAG", "new file:height:${rect.bottom - rect.top}, path:${file.absolutePath}")

        //result.add(file.absolutePath)
        //splitPaths.add(file)
        val bitmapPath = compressImageFitPage(file.absolutePath, bm.width, bm.height)
        result.add(bitmapPath)

这是宽度处理

private fun compressImageFitPage(
        path: String,
        width: Int,
        height: Int,
    ): String {
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = false
        options.outWidth = PDF_PAGE_WIDTH.toInt()
        options.outHeight = (height * PDF_PAGE_WIDTH / width).toInt()
        val bitmap = BitmapFactory.decodeFile(path, options)
        val file =
            File(
                PDFUtils.getExternalCacheDir(App.instance).path
                        + File.separator + "create" + File.separator + System.currentTimeMillis() + ".jpg"
            )
        PDFUtils.saveBitmapToFile(bitmap, file, Bitmap.CompressFormat.JPEG, 100)
        Log.d(
            "TAG",
            "bitmap.width:$width, height:$height,:${options.outWidth},${options.outHeight}, path:${file.absolutePath}"
        )
        return file.absolutePath
    }

到这,切割就完成了,图片的高宽处理也完成了.剩下的就是将这些图片添加到页面上.

添加页面addPage
private fun addPage(
        path: String,
        mDocument: PDFDocument,
        index: Int
    ): PDFObject? {
        val image = Image(path)
        val resources = mDocument.newDictionary()
        val xobj = mDocument.newDictionary()
        val obj = mDocument.addImage(image)
        xobj.put("I", obj)
        resources.put("XObject", xobj)

        val w = image.width
        val h = image.height
        val mediabox = Rect(0f, 0f, w.toFloat(), h.toFloat())
        val contents = "q $w 0 0 $h 0 0 cm /I Do Q\n"
        val page = mDocument.addPage(mediabox, 0, resources, contents)
        Log.d("TAG", String.format("index:%s,page,%s", index, contents))
        return page
    }

mupdf的语法都是类似的,js,c也都是这个规则.创建image对象.

contents要注意的点,这里设置了高宽,如果要添加内容,就要额外的操作了.否则这段应该是固定的.

在添加页面时,如果是-1,表示追加,追加时如果是空的文档自然就放到第一页了.

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android框架是一种用于开发移动设备应用程序的软件框架。它提供了应用程序开发所需的基本功能和工具,包括用户界面设计、应用程序管理、网络通信、数据存储、多媒体处理等。Android框架的设计理念是基于一种面向对象的编程模型,它允许开发人员使用Java编写应用程序,以便在不同的Android设备上运行。 Android框架的核心是它的应用程序框架,它是一个强大的、可扩展的软件层,用于构建Android应用程序的组件。应用程序框架是由一系列库、运行时环境和工具组成,它提供了许多重要功能,例如活动管理、应用程序生命周期管理、资源管理、安全性等。 超清PDF是指具有非常高的分辨率和图像质量的PDF文档。在Android框架中,可以使用一些库和工具来实现生成超清PDF。例如,可以使用Android的图形库和绘图工具来绘制高分辨率的图像,然后将其导出为PDF文档。此外,还可以使用一些开源的PDF生成库,如iText或PDFBox,来生成超清PDF。 要实现超清PDF,首先需要准备好高质量的图像资源。然后,可以使用Android的绘图工具和字体库来创建PDF页面,并将图像和文本添加到页面中。接下来,可以使用PDF生成库来将页面合并为PDF文档,并设置PDF的分辨率和图像质量。最后,可以使用Android的文件管理工具将生成PDF文档保存到设备上的存储空间中。 总的来说,Android框架是一个功能强大的开发工具,可以用于构建各种类型的移动应用程序。而在Android框架生成超清PDF需要使用一些绘图工具和PDF生成库来实现,以便提供高质量的图像和文本显示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值