PDFlib Cookbook

cookbook

color/softmask_effects updated

Create a soft mask based on arbitrary geometric objects.

Download Java Code  Switch to PHP Code  Show Output 

/*
 * Soft mask effects:
 * Create a template as luminosity soft mask in an extended gstate. These
 * soft masks are very powerful and more general than simple clipping operations.
 * 
 * The following soft mask effects are demonstrated:
 * - For comparison the original image is shown first
 * - Colorize image with soft mask: 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 10
 * Required data: none
 */
package com.pdflib.cookbook.pdflib.color;

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

public class softmask_effects {
    public static void main(String argv[]) {
        /* This is where the data files are. Adjust if necessary. */
        String searchpath = "../input";
        String outfile = "softmask_effects.pdf";
        String imageFilename = "nesrin.jpg";
        String title = "Soft mask effects";

        final double page_size = 400;
        final double border = 20;
        int exitcode = 0;
        
        pdflib p = null;

        try {
            int templ;
            double image_box_llx, image_box_lly;
            double image_llx, image_lly;
            double image_width;
            String image_fit_options;
            int textflow, gstate_softmask;
            String font_options =
                "fontname=NotoSerif-Regular fontsize=12 leading=125% alignment=center fillcolor=black";
            int image, bbox;
        
            p = new pdflib();

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

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

            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 = (int) p.info_image(image, "boundingbox", image_fit_options);


            // ------------------- For comparison: the original image
            p.begin_page_ext(page_size, page_size, "");
            
            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("");

            /*
             * 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.
             * 
             * Templates which will be used as softmasks must be created with
             * a transparency group and a suitable colorspace.
             */
            templ = p.begin_template_ext(page_size, page_size, "transparencygroup={colorspace=sRGB}");
                // 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);

            // ------------------- Colorize image with soft mask: color appears in the light areas
            p.begin_page_ext(page_size, page_size, "");
            
            // Create a gstate with luminosity soft mask based on the template;
            // Initialize transparent background.
            gstate_softmask = p.create_gstate(
                    "softmask={template=" + templ + " type=luminosity backdropcolor={0 0 0.000001} }");
            
            // 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 soft mask: 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, "");
            
            // Create a gstate with luminosity soft mask based on the template
            // Initialize transparent background and invert black/white polarity
            gstate_softmask = p.create_gstate("softmask={type=luminosity template=" + templ + " backdropcolor=transparent invert}");

            // 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 inverted softmask: color appears in the dark areas.",
                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, "");

            // Create template and fill it with axial shading from black to white.
            // Templates which will be used as softmasks must be created with
            // a transparency group and a suitable colorspace.
            templ = p.begin_template_ext(page_size, page_size, "transparencygroup={colorspace=sRGB}");
    
                /*
                 * 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.
                 */
                int 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");
    
                int 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
            // Initialize transparent background
            gstate_softmask = p.create_gstate("softmask={template=" + templ + " type=luminosity backdropcolor=transparent}");

            // Place the image while applying the gstate
            p.fit_image(image, image_box_llx, image_box_lly, image_fit_options + " gstate=" + gstate_softmask);
            
            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("");
        }
        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);
        }
    }
}