PDFlib Cookbook

cookbook

color/softmask_effects

Create a soft mask based on arbitrary geometric objects.

Download PHP Code  Switch to Java Code  Show Output 

<?php
/*
 * Softmask effects:
 * Create a template as luminosity softmask in an extended gstate. These
 * softmasks are very powerful and more general than simple clipping operations.
 * 
 * The following softmask effects are demonstrated:
 * - For comparison the original image is shown first
 * - Colorize image with softmask: color appears in the light areas
 * - Invert and colorize image: color appears in the dark areas
 * - Apply opacity gradient to an image (fade-out effect)
 *
 * Required software: PDFlib/PDFlib+PDI/PPS 9
 * Required data: none

 */

/* This is where the data files are. Adjust if necessary. */
$searchpath = dirname(__FILE__,3) . "/input";
$title = "Softmask effects";
$outfile = "";
$imageFilename = "nesrin.jpg";

$page_size = 400;
$border = 20;


try {
    $font_options =
        "fontname=NotoSerif-Regular encoding=unicode fontsize=12 leading=125% alignment=center fillcolor=black";
    
    $p = new pdflib();

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

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

    $p->begin_document($outfile, "");

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

    /* Load content which will be colorized; this could be a raster
     * image, SVG graphics, PDF page or other contents.
     */
    $image = $p->load_image("auto", $imageFilename, "");
    
    /*
     * The image is placed centered on the page, the fitbox being
     * half the width and height of the page.
     */
    $image_box_llx = $page_size / 4;
    $image_box_lly = $page_size / 4;
    $image_fit_options = "boxsize={" . ($page_size / 2) . " "
        . ($page_size / 2) . "} fitmethod=meet position=center";
    
    // Determine position and size of the placed image
    $image_width = $p->info_image($image, "width", $image_fit_options);
    
    $image_llx = $image_box_llx + $p->info_image($image, "x1", $image_fit_options);
    $image_lly = $image_box_lly + $p->info_image($image, "y1", $image_fit_options);
    
    // 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_image($image, "boundingbox", $image_fit_options);


    // ------------------- For comparison: the original image
    $p->begin_page_ext($page_size, $page_size, "transparencygroup={colorspace=sRGB}");
    
    $textflow = $p->create_textflow(
        "For comparison: the original image", $font_options);
    
    $p->fit_image($image, $image_box_llx, $image_box_lly, $image_fit_options);
    
    $p->fit_textflow($textflow,
        $border, $border, $page_size - $border, $page_size / 5,
        "fitmethod=auto");
    $p->delete_textflow($textflow);
    
    $p->end_page_ext("");

    
    // ------------------- Colorize image with softmask: color appears in the light areas
    $p->begin_page_ext($page_size, $page_size, "transparencygroup={colorspace=sRGB}");

    /*
     * Create a template that will be used for the soft mask gstate.
     * 
     * The soft mask is defined by the image contents, where light
     * areas let the fill color pass through, while dark areas block
     * the fill color. You can add arbitrary content (e.g. text)
     * to the soft mask template.
     * 
     * This technique can be used to create clipping areas by
     * adding multiple areas, which is not possible with the clip()
     * operation.
     */
    $templ = $p->begin_template_ext($page_size, $page_size,
                    "transparencygroup={colorspace=DeviceGray}");
        
        $p->set_graphics_option("fillcolor=white");
        $p->rect(0, 0, $page_size, $page_size);
        $p->fill();
        
        // Place the image which will act as soft mask
        $p->fit_image($image, $image_box_llx, $image_box_lly, $image_fit_options);
    
    $p->end_template_ext(0, 0);
    
    // Create a gstate with luminosity soft mask based on the template
    $gstate_softmask = $p->create_gstate("softmask={template=" . $templ . " type=luminosity}");
    
    // Fill the bounding box with color while applying the gstate
    $p->draw_path($bbox, $image_box_llx, $image_box_lly, "fill fillcolor=blue gstate=" . $gstate_softmask);
    
    $textflow = $p->create_textflow(
        "Colorize image with softmask: color appears in the light areas. " .
        "Since dark areas block the color the image appears inverted.",
        $font_options);
    
    $p->fit_textflow($textflow,
        $border, $border, $page_size - $border, $page_size / 5,
        "fitmethod=auto");
    $p->delete_textflow($textflow);
    
    $p->end_page_ext("");


    // ----------- Invert and colorize image: color appears in the dark areas
    $p->begin_page_ext($page_size, $page_size, "transparencygroup={colorspace=sRGB}");

    // Create the template which will be used to define the soft mask
    $templ = $p->begin_template_ext($page_size, $page_size,
                "transparencygroup={colorspace=sRGB}");

        $p->set_graphics_option("fillcolor=white");
        $p->rect(0, 0, $page_size, $page_size);
        $p->fill();

        /* Place arbitrary contents, e.g. image */
        $p->fit_image($image, $image_box_llx, $image_box_lly, $image_fit_options);

        // Create a gstate with blend mode for color inversion to preserve dark and light areas
        $gstate_invert = $p->create_gstate("blendmode=Difference");
        
        // Fill the bounding box with white while applying the inverting gstate
        $p->draw_path($bbox, $image_box_llx, $image_box_lly, "fill fillcolor=white gstate=" . $gstate_invert);
    
    $p->end_template_ext(0, 0);
    
    // Create a gstate with luminosity soft mask based on the template
    $gstate_softmask = $p->create_gstate("softmask={type=luminosity template=" . $templ . "}");

    // Fill the bounding box with color while applying the gstate
    $p->draw_path($bbox, $image_box_llx, $image_box_lly, "fill fillcolor=blue gstate=" . $gstate_softmask);

    $textflow = $p->create_textflow(
        "Invert and colorize image: color appears in the dark areas. " .
        "Image inversion is compensated with blendmode Difference.",
        $font_options);
    
    $p->fit_textflow($textflow,
        $border, $border, $page_size - $border, $page_size / 5,
        "fitmethod=auto");
    $p->delete_textflow($textflow);

    $p->end_page_ext("");

    
    // ----- Apply opacity gradient to an image (fade-out effect)
    $p->begin_page_ext($page_size, $page_size, "transparencygroup={colorspace=sRGB}");

    /*
     * Create template and fill it with axial shading from black to white.
     */
    $templ = $p->begin_template_ext($page_size, $page_size,
                    "transparencygroup={colorspace=sRGB}");

        $p->set_graphics_option("fillcolor=white");
        $p->rect(0, 0, $page_size, $page_size);
        $p->fill();

        /*
         * The axial shading reaches full white a little bit before the
         * right border of the image and extends beyond that point with
         * full white so we get the image clearly without any transparency
         * at the right edge.
         */
        $sh = $p->shading("axial",
                $image_llx, $image_lly,
                $image_llx + 0.9 * $image_width, $image_lly,
                0.0, 0.0, 0.0, 0.0, "startcolor={gray 0} endcolor={gray 1} extend1=true");

        $shp = $p->shading_pattern($sh, "");
        
        // Fill the bounding box with the shading pattern
        $p->draw_path($bbox, $image_box_llx, $image_box_lly, "fill fillcolor={pattern " . $shp . "}");
    
    $p->end_template_ext(0, 0);
    
    // Create a gstate with luminosity soft mask based on the template
    $gstate_softmask = $p->create_gstate("softmask={template=" . $templ . " type=luminosity}");

    // Place the image while applying the gstate           
    $p->set_gstate($gstate_softmask);
    $p->fit_image($image, $image_box_llx, $image_box_lly, $image_fit_options);
    
    $textflow = $p->create_textflow(
        "Apply opacity gradient to an image (fade-out effect). " .
        "Dark gradient areas at the left block the color, making " .
        "the image transparent.",
        $font_options);
    
    $p->fit_textflow($textflow,
        $border, $border, $page_size - $border, $page_size / 5,
        "fitmethod=auto");
    $p->delete_textflow($textflow);

    $p->end_page_ext("");
    
    $p->close_image($image);
    
    $p->end_document("");
    
    $buf = $p->get_buffer();
    $len = strlen($buf);
    
    header("Content-type: application/pdf");
    header("Content-Length: $len");
    header("Content-Disposition: inline; filename=softmask.pdf");
    print $buf;
}
catch (PDFlibException $e) {
    echo ("PDFlib exception occurred:\n" . "[" . $e->get_errnum() . "] " .
                     $e->get_apiname() . ": " . $e->get_errmsg() . "\n");
    exit(1);
}
catch (Exception $e) {
    echo ($e->getMessage());
    exit(1);
}

$p = 0;

?>