Hey developers,
I am looking for a solution to Compress PDFs, pdfs which don’t contains any images ( a simple plane PDFs which will have only text in it ).
I am using below code snippet to Compress PDFs but this is for PDFs which contains the Images. but if PDF’s dont contains the images then it does not compress it, sometimes it does but to only 100KB to 200KB only.
Code
(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()
}
Any help will be appreciated. I am trying from 1 week but I did not get any solution of this. I saw some apps on Play Store, all are able to compress pdfs (which don’t contains the images). But my logic does not able to do it. Pls help me out.
Thanks…