Лучшее сжатие, чем LosslessFactory в PDFBox? - PullRequest
0 голосов
/ 23 сентября 2018

Без потерь в швах PDFBox очень плохо справляется со сжатием PNG.Глядя на код, кажется, что он не делает то, что говорит Javadoc (используйте LZW) [1], но я могу ошибаться.

Любые идеи о том, как передать двоичный поток PNG с exec через, например, pngquantа затем создать PDImageXObject из полученного двоичного файла?

images-001-000.png PNG 2480x3508 2480x3508+0+0 8-bit sRGB 1.261MB 0.000u 0:00.000

Сокращение пикселей, запись его в PDFBox, извлечение с помощью pdffiles и использование идентификаторов возврата

images-shrink-001-000.png PNG 874x1237 874x1237+0+0 8-bit sRGB 1.038MB 0.000u 0:00.000

Хотя количество пикселей очень многонамного меньше, изображение только немного меньше.

Используя квантование, чтобы показать максимально возможное уменьшение, я использую pngquant для сравнения,

images-quant-001-000.png PNG 874x1237 874x1237+0+0 8-bit sRGB 256c 673KB 0.000u 0:00.000

[1]

    /**
     * Create a PDImageXObject while making a decision whether not to 
     * compress, use Flate filter only, or Flate and LZW filters.
     * 
     * @param document The document.
     * @param byteArray array with data.
     * @param width the image width
     * @param height the image height
     * @param bitsPerComponent the bits per component
     * @param initColorSpace the color space
     * @return the newly created PDImageXObject with the data compressed.
     * @throws IOException 
     */
    private static PDImageXObject prepareImageXObject(PDDocument document, 
            byte [] byteArray, int width, int height, int bitsPerComponent, 
            PDColorSpace initColorSpace) throws IOException
    {
        //pre-size the output stream to half of the input
        ByteArrayOutputStream baos = new ByteArrayOutputStream(byteArray.length/2);

        Filter filter = FilterFactory.INSTANCE.getFilter(COSName.FLATE_DECODE);
        filter.encode(new ByteArrayInputStream(byteArray), baos, new COSDictionary(), 0);

        ByteArrayInputStream encodedByteStream = new ByteArrayInputStream(baos.toByteArray());
        return new PDImageXObject(document, encodedByteStream, COSName.FLATE_DECODE, 
                width, height, bitsPerComponent, initColorSpace);
    }
...