如果 PDF 不包含任何图像或流,则压缩 PDF

问题描述 投票:0回答:1

嘿开发者

我正在寻找一种压缩 PDF 的解决方案,即不包含任何图像的 pdf(一个简单的平面 PDF,其中仅包含文本)。

我使用下面的代码片段来压缩 PDF,但这适用于包含图像的 PDF。但如果 PDF 不包含图像,那么它不会压缩它,有时会压缩,但只有 100KB 到 200KB。

代码

 (context as AppCompatActivity).lifecycleScope.launch(Dispatchers.IO) {
        try {
            val reader = PdfReader(inputPath, password.toByteArray())
            //pdfOptimize(reader)
            compressReader(reader)
            saveReader(reader)
            reader.close()

            onPDFCompletion(outputPath)
        } catch (e: IOException) {
            Log.d("PDFCompressionActivityTEST", "execute: ${e.message}")
            onPDFFailed(e.message)
        } catch (e: DocumentException) {
            onPDFFailed(e.message)
        } catch (e: Exception) {
            onPDFFailed(e.message)
        }

    }


 @Throws(IOException::class)
private fun compressReader(reader: PdfReader) {
    val n = reader.xrefSize
    var `object`: PdfObject?
    var stream: PRStream
    for (i in 0 until n) {
        `object` = reader.getPdfObject(i)
        if (`object` == null || !`object`.isStream) continue
        stream = `object` as PRStream
        compressStream(stream)
    }
    reader.removeUnusedObjects()
}

 @Throws(IOException::class)
private fun compressStream(stream: PRStream) {
    val pdfSubType = stream[PdfName.SUBTYPE]
    println(stream.type())
    if (pdfSubType != null && pdfSubType.toString() == PdfName.IMAGE.toString()) {
        val image = PdfImageObject(stream)
        val imageBytes = image.imageAsBytes
        val bmp: Bitmap =
            BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size) ?: return
        val width = bmp.width
        val height = bmp.height
        val outBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val outCanvas = Canvas(outBitmap)
        outCanvas.drawBitmap(bmp, 0f, 0f, null)
        val imgBytes = ByteArrayOutputStream()
        outBitmap.compress(Bitmap.CompressFormat.JPEG, quality, imgBytes)
        stream.clear()
        stream.setData(imgBytes.toByteArray(), false, PRStream.BEST_COMPRESSION)
        stream.put(PdfName.TYPE, PdfName.XOBJECT)
        stream.put(PdfName.SUBTYPE, PdfName.IMAGE)
        stream.put(PdfName.FILTER, PdfName.DCTDECODE)
        stream.put(PdfName.WIDTH, PdfNumber(width))
        stream.put(PdfName.HEIGHT, PdfNumber(height))
        stream.put(PdfName.BITSPERCOMPONENT, PdfNumber(8))
        stream.put(PdfName.COLORSPACE, PdfName.DEVICERGB)
    }
}


  @Throws(DocumentException::class, IOException::class)
private fun saveReader(reader: PdfReader) {
    val stamper = PdfStamper(reader, FileOutputStream(outputPath))
    stamper.setFullCompression()
    stamper.close()
}

任何帮助将不胜感激。我从 1 周开始尝试,但没有得到任何解决方案。我在 Play Store 上看到了一些应用程序,它们都能够压缩 pdf(不包含图像)。但我的逻辑做不到。请帮助我。

谢谢...

android kotlin pdf itext compression
1个回答
0
投票

在基于文本的 PDF 中,很多尺寸通常是由于嵌入字体造成的。

某些字体包含多种语言的字形和特殊字符,导致 PDF 文件有 3000 多个字形,增加了数百 Kb。

虽然您的 PDF 可能仅使用 ASCII 范围内的字符(最多 127 个或更少)

因此,您可以通过使用“稀疏”字形集(仅文本中使用的字符的字形)来减小文件大小。

请注意,现在这种做法不太常见,因为某些字体的许可证不允许您修改字体,但某些工具仍然可以这样做(忽略任何可能的法律问题)

另外制作字体的“稀疏”版本可能会使其在不更改嵌入字体的情况下无法编辑,因为它没有新字符的字形。

但是对于您知道拥有允许您修改字体的许可证的字体,并且您不担心可编辑性,那么您可以生成稀疏版本。

抱歉,没有代码可以执行此操作,但许多执行稀疏字体的工具都使用 Google 工具来执行此操作,称为“sfntly”,它确实有一个 java 包。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.