PDFlib Cookbook

cookbook

color/blendmode_effects

Demonstrate all blend modes available in PDF.

Download Java Code  Switch to PHP Code  Show Output 

/*
 * Blend mode effects:
 * Demonstrate various color effects with blend modes
 * 
 * Place an object (PDF page, image, SVG graphics) on the page and paint
 * some color on top of it with a suitable blend mode.
 * 
 * Required software: PDFlib+PDI/PPS 9
 * Required data: PDF, fonts
 */
package com.pdflib.cookbook.pdflib.color;

import com.pdflib.pdflib;
import com.pdflib.PDFlibException;

public class blendmode_effects {

    /*
     * Create a template which demonstrates a particular effect
     */
    static int create_blendmode_sample(pdflib p,
        String color_bg, int page, String blendmode, String color_fg)
        throws PDFlibException {
        
        String fitoptlist = "";

        // Retrieve size of the placed object (PDF, SVG, image or other)
        double width  = (int) p.info_pdi_page(page, "width",  fitoptlist);
        double height = (int) p.info_pdi_page(page, "height", fitoptlist);

        // Retrieve path handle for the bounding box of the placed object.
        // This is convenient for filling the path with a single command.
        int bbox = (int) p.info_pdi_page(page, "boundingbox", fitoptlist);

        // Create template (only required to conveniently place the result in a table cell)
        int templ = p.begin_template_ext(width, height, "transparencygroup={colorspace=sRGB isolated}");

            // Layer 1: white background (only required for transparent objects)
            if (color_bg != "")
                p.draw_path(bbox, 0, 0, "close fill fillcolor=" + color_bg);
            
            // Layer 2: the actual object to be colorized
            p.fit_pdi_page(page, 0, 0, fitoptlist);
            
            // Layer 3: apply blendmode and paint color on top of the object to colorize it
            int gstate_blendmode = p.create_gstate("blendmode=" + blendmode);
            p.draw_path(bbox, 0, 0, "close fill fillcolor=" + color_fg + " gstate=" + gstate_blendmode);

        p.end_template_ext(0, 0);

        return templ;
    }
    
    public static void main(String argv[]) {
        /* This is where the data files are. Adjust as necessary. */
        String searchpath = "../input";
        String inputPDFFileName = "nesrin.pdf";
        String outFileName = "blendmode_effects.pdf";
        String title = "Blendmode effects";
        int exitcode = 0;
        pdflib p = null;

        class testcase {
            String color_bg;
            String name;
            String color_fg;
            String description;

            testcase(String color_bg, String name, String color_fg, String description) {
                this.color_bg = color_bg;
                this.name = name;
                this.color_fg = color_fg;
                this.description = description;
            }
        }

        /* Test cases with various combinations of background color, blend mode and foreground color */
        final testcase testcases[] = {
            // The white background is only required for transparent objects and some blend modes
            new testcase("white", "Color",      "red",          "colorize object: white remains, other colors become foreground color"),
            new testcase("",      "Multiply",   "red",          "colorize object: white becomes foreground color"),
            new testcase("white", "Hue",        "red",          "colorize object: gray levels remain, other colors become foreground color"),
            new testcase("white", "Difference", "white",        "invert object colors: black and white are reversed"),
            new testcase("",      "Color",      "white",        "decolorize object: colors become gray levels"),
        };

        try {
            p = new pdflib();
            int i, row, col;
            int tf = -1, tbl = -1;
            String cellopts, result;

            final double pagewidth = 842, pageheight = 595;
            final double MARGIN = 6, ROWHEIGHT = 100;

            /* Borders for the table fitbox */
            final double border = 30;            
            final double fontsize = 10;

            p.set_option("searchpath={" + searchpath + "}");

            /* This means that errors throw an exception */
            p.set_option("errorpolicy=exception");

            if (p.begin_document(outFileName, "") == -1)
                throw new Exception("Error: " + p.get_errmsg());

            p.set_info("Creator", "PDFlib Cookbook");
            p.set_info("Title", title);

            /*
             * Open the PDF input document
             */
            int doc = p.open_pdi_document(inputPDFFileName, "");
            int page = p.open_pdi_page(doc, 1, "transparencygroup={colorspace=sRGB isolated}");
            
            // Path object handle for the bounding box of the imported page
            int bbox = (int) p.info_pdi_page(page, "boundingbox", "");

            /*
             * ----------------------------------
             * Create table header for all cells
             * ----------------------------------
             */

            // Set some general text options shared among all cells
            String textoptlist = "fittextline={fontname=NotoSerif-Bold encoding=unicode fontsize="
                + fontsize + " position={center}} " + " margin=" + MARGIN;

            row = 1;
            col = 1;
            tbl = p.add_table_cell(tbl, col++, row, "background color", textoptlist + " colwidth=20%");

            tbl = p.add_table_cell(tbl, col++, row, "+ object", textoptlist + " colwidth=20%");

            tbl = p.add_table_cell(tbl, col++, row, "+ blendmode", textoptlist);
            
            tbl = p.add_table_cell(tbl, col++, row, "+ foreground ", textoptlist + " colwidth=20%");
            
            tbl = p.add_table_cell(tbl, col++, row, "= result", textoptlist +  " colwidth=20%");
            
            tbl = p.add_table_cell(tbl, col++, row, "description", textoptlist);

            
            /*
             * ------------------------------------------------
             * Add a table row for each test case
             * ------------------------------------------------
             */
            String tf_optlist = "fontname=NotoSerif-Regular encoding=unicode fontsize=" + fontsize;
            textoptlist = " fittextline={" + tf_optlist + " position={center}} " + " margin=" + MARGIN;
            
            for (i = 0, row = 2; i < testcases.length; i++, row++) {
                /*
                 * -------------------------------------------------------------
                 * Column 1: background color if present
                 * -------------------------------------------------------------
                 */
                cellopts = "margin=" + MARGIN;
                col = 1;
                
                if (testcases[i].color_bg == "")
                    tbl = p.add_table_cell(tbl, col, row, "(none)",
                        cellopts + textoptlist);                   
                else
                    tbl = p.add_table_cell(tbl, col, row, "",
                        cellopts + " path=" + bbox +
                        " fitpath={close stroke linewidth=0.5 strokecolor=black fill fillcolor=" + testcases[i].color_bg + " fitmethod=meet position={center}}");

                /*
                 * ---------------------------------------------
                 * Column 2: object (PDF page)
                 * ---------------------------------------------
                 */
                cellopts =  "margin=" + MARGIN;
                col++;
                tbl = p.add_table_cell(tbl, col, row, "",
                    cellopts + " pdipage=" + page + " fitpdipage={fitmethod=meet position={center}}");

                /*
                 * -------------------------------------------------------------
                 * Column 3: blend mode name
                 * -------------------------------------------------------------
                 */

                col++;
                tbl = p.add_table_cell(tbl, col, row, "blendmode=" + testcases[i].name, textoptlist);

                /*
                 * -------------------------------------------------------------
                 * Column 4: foreground color
                 * -------------------------------------------------------------
                 */
                cellopts =  "margin=" + MARGIN;
                col++;
                tbl = p.add_table_cell(tbl, col, row, "",
                    cellopts  + " path=" + bbox +
                    " fitpath={close stroke linewidth=0.5 strokecolor=black fill fillcolor=" + testcases[i].color_fg + " fitmethod=meet position={center}}");

                /*
                 * -------------------------------------------------------------
                 * Column 5: blended result
                 * -------------------------------------------------------------
                 */
                int templ = create_blendmode_sample(p, testcases[i].color_bg, page, testcases[i].name, testcases[i].color_fg);
                col++;

                cellopts = "rowheight=" + ROWHEIGHT + " margin=" + MARGIN;
                tbl = p.add_table_cell(tbl, col, row, "",
                    cellopts + " image=" + templ + " fitimage={fitmethod=meet position={center}}");
                
                /*
                 * -------------------------------------------------------------
                 * Column 6: description
                 * -------------------------------------------------------------
                 */
                tf = p.add_textflow(-1, testcases[i].description,
                    tf_optlist + " lastalignment=center alignment=center leading=125%");

                cellopts = textoptlist + " textflow=" + tf;
                col++;
                tbl = p.add_table_cell(tbl, col, row, "", cellopts); 
            } /* for */

            /*
             * -----------------------------------------------------------------
             * Fit the table. With "header=1" the table header consists of the
             * first line. Using "line=horother linewidth=0.3" the ruling is
             * specified with a line width of 0.3 for all horizontal lines.
             * -----------------------------------------------------------------
             */
            String tableoptlist =
                "showgrid header=1 stroke={ {line=horother linewidth=0.3}}";

            do {
                // The transparency group avoids color shifts when transparency is involved
                p.begin_page_ext(pagewidth, pageheight, "transparencygroup={colorspace=sRGB}");
                
                /* Place the table instance */
                result = p.fit_table(tbl, border, border, pagewidth - border,
                    pageheight - border, tableoptlist);
                if (result.equals("_error"))
                    throw new Exception(
                        "Couldn't place table : " + p.get_errmsg());

                p.end_page_ext("");
            }
            while (result.equals("_boxfull"));

            /* Check the result; "_stop" means all is ok. */
            if (!result.equals("_stop")) {
                if (result.equals("_error")) {
                    throw new Exception(
                        "Error when placing table: " + p.get_errmsg());
                }
            }

            /* This also deletes Textflow handles used in the table */
            p.delete_table(tbl, "");

            p.close_pdi_page(page);
            p.close_pdi_document(doc);

            p.end_document("");
        }
        catch (PDFlibException e) {
            System.err.println("PDFlib exception occurred:");
            System.err.println("[" + e.get_errnum() + "] " + e.get_apiname() +
                ": " + e.get_errmsg());
            exitcode = 1;
        }
        catch (Exception e) {
            System.err.println(e);
            exitcode = 1;
        }
        finally {
            if (p != null) {
                p.delete();
            }
            System.exit(exitcode);
        }
    }
}