PDFlib Cookbook

cookbook

color/blendmode_effects updated

Demonstrate various color effects with blend modes.

Download PHP Code  Switch to Java Code  Show Output 

<?php
/*
 * 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 10
 * Required data: PDF, fonts
 */

/*
    * Create a template which demonstrates a particular effect
    */
function create_blendmode_sample($p, $color_bg, $page, $blendmode, $color_fg){
    
    $fitoptlist = "";

    // Retrieve size of the placed object (PDF, SVG, image or other)
    $width  = $p->info_pdi_page($page, "width",  $fitoptlist);
    $height = $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.
    $bbox = $p->info_pdi_page($page, "boundingbox", $fitoptlist);

    // Create template (only required to conveniently place the result in a table cell)
    $templ = $p->begin_template_ext($width, $height, "");

        // 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
        $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;
}

/* This is where the data files are. Adjust as necessary. */
$searchpath = dirname(__FILE__,3) . "/input";

/* By default annotations are also imported. In some cases this
 * requires the Noto fonts for creating annotation appearance streams.
 * We therefore set the searchpath to also point to the font directory.
 */
$fontpath = dirname(__FILE__,3)."/resource/font";
$inputPDFFileName = "nesrin.pdf";
$outFileName = "";
$title = "Blendmode effects";
$exitcode = 0;

class testcase {
    function __construct($color_bg, $name, $color_fg, $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 */
$testcases = array(
    // 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();
    $tf = 0; $tbl = 0;

    $pagewidth = 842; $pageheight = 595;
    $MARGIN = 6; $ROWHEIGHT = 100;

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

    $p->set_option("searchpath={" . $searchpath . "}");

    $p->set_option("searchpath={" . $fontpath . "}");

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

    if ($p->begin_document($outFileName, "") == 0)
        throw new Exception("Error: " + $p->get_errmsg());

    $p->set_info("Creator", "PDFlib Cookbook");
    $p->set_info("Title", $title);

    /*
        * Open the PDF input document
        */
    $doc = $p->open_pdi_document($inputPDFFileName, "");
    $page = $p->open_pdi_page($doc, 1, "");
    
    // Path object handle for the bounding box of the imported page
    $bbox = $p->info_pdi_page($page, "boundingbox", "");

    /*
        * ----------------------------------
        * Create table header for ----------
        */

    // Set some general text options shared among all cells
    $textoptlist = "fittextline={fontname=NotoSerif-Bold 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
        * ------------------------------------------------
        */
    $tf_optlist = "fontname=NotoSerif-Regular fontsize=" . $fontsize;
    $textoptlist = " fittextline={" . $tf_optlist . " position={center}} " . " margin=" . $MARGIN;
    
    for ($i = 0, $row = 2; $i < count($testcases); $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
            * -------------------------------------------------------------
            */
        $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(0, $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.
        * -----------------------------------------------------------------
        */
    $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, "");
        
        /* Place the table instance */
        $result = $p->fit_table($tbl, $border, $border, $pagewidth - $border,
            $pageheight - $border, $tableoptlist);
        if ($result == "_error")
            throw new Exception(
                "Couldn't place table : " . $p->get_errmsg());

        $p->end_page_ext("");
    }
    while ($result == "_boxfull");

    /* Check the result; "_stop" means all is ok. */
    if ($result != "_stop") {
        if ($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("");
    $buf = $p->get_buffer();
    $len = strlen($buf);
    
    header("Content-type: application/pdf");
    header("Content-Length: $len");
    header("Content-Disposition: inline; filename=blendmode_effects.pdf");
    print $buf;
}
catch (PDFlibException $e) {
    echo ("PDFlib exception occurred:\n" . "[" . $e->get_errnum() . "] " .
                        $e->get_apiname() . ": " . $e->get_errmsg() . "\n");
    exit(1);
}
catch (Throwable $e) {
    echo ("PHP exception occurred: " . $e->getMessage() . "\n");
    exit(1);
}

$p = 0;
?>