Search code examples
javapdfitextgrayscale

iText: Change Colour of existing PDF to Grayscale


We are using an old Version of iText (2.x) with Java 6 at the moment.

What we now try to do is to open an existing PDF and change its Color to grayscale. I found the method PdfWriter.setDefaultColorspace(PdfName key, PdfObject cs) but I'm not really sure how to use it.

Can anyone tell me, how to use it in the right way? Or maybe anybody knows how to change PDF to grayscale in another way with this old iText version.

Many thanks in advance!


Solution

  • I implemented the code here using iText 5.5.14 but it should also work with iText 2.1.7 with minimal changes.

    There are two ways to remove color from PDF pages,

    • either one actually iterates through all color related instructions of its content streams and replaces the colors set therein by an equivalent gray
    • or one appends instructions to each page content stream which remove the color saturation of all that the existing instructions create.

    The former option is beyond the scope of a stack overflow answer (there are many different kinds of colors in PDFs, embedded bitmaps also bring color along, and one has to also consider the effects of transparency and blend modes used) but the latter option is fairly easy to implement by overlaying the page with a grayscale color in blend mode Saturation:

    void dropSaturation(PdfStamper pdfStamper) {
        PdfGState gstate = new PdfGState();
        gstate.setBlendMode(PdfName.SATURATION);
        PdfReader pdfReader = pdfStamper.getReader();
        for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
            PdfContentByte canvas = pdfStamper.getOverContent(i);
            canvas.setGState(gstate);
            Rectangle mediaBox = pdfReader.getPageSize(i);
            canvas.setColorFill(BaseColor.BLACK);
            canvas.rectangle(mediaBox.getLeft(), mediaBox.getBottom(), mediaBox.getWidth(), mediaBox.getHeight());
            canvas.fill();
            canvas = pdfStamper.getUnderContent(i);
            canvas.setColorFill(BaseColor.WHITE);
            canvas.rectangle(mediaBox.getLeft(), mediaBox.getBottom(), mediaBox.getWidth(), mediaBox.getHeight());
            canvas.fill();
        }
    }
    

    (ColorToGray method)

    You can apply it like this:

    PdfReader pdfReader = new PdfReader(SOURCE_PDF);
    PdfStamper pdfStamper = new PdfStamper(pdfReader, RESULT_STREAM);
    dropSaturation(pdfStamper);
    pdfStamper.close();
    

    Beware, this is a proof-of-concept. For a complete solution you actually have to do the same to all annotations of the pages.