org.faceless.pdf2

## Class OutputProfiler

- java.lang.Object
- - org.faceless.pdf2.OutputProfiler

- All Implemented Interfaces:
    Runnable

      public class OutputProfiler
      extends Object
      implements Runnable

  An `OutputProfiler` is used to create an `OutputProfile` for a PDF or to attempt to apply a new OutputProfile, modifying the PDF in the process. This can be a basic OutputProfile, which is very quick to create, or a full OutputProfile which involves scanning the entire PDF, and takes much longer.

  This class now underlies the `PDF.getBasicOutputProfile()` and `PDF.getFullOutputProfile()` methods, and brings several advantages; you can re-run the profile when you know the PDF has changed, you can create the profile in one thread and monitor its progress in another, and you can make structural changes to the PDF (such as substituting fonts or colors) that aren't possible with the previous API.

  To create a new profile with the same information as `PDF.getBasicOutputProfile()`:

       OutputProfiler profiler = new OutputProfiler(pdf);
       OutputProfile profile = profiler.getProfile();

  and to duplicate the functionality of the `PDF.getFullOutputProfile()` method:

       OutputProfiler profiler = new OutputProfiler(new PDFParser(pdf));
       OutputProfile profile = profiler.getProfile();

  To duplicate the functionality of the `PDF.setOutputProfile(org.faceless.pdf2.OutputProfile)` method, you would call `apply(org.faceless.pdf2.OutputProfile)`. For example, to retrieve the full profile of the PDF, check if it's compatible with a "target" profile and attempt to convert the PDF to that profile if not:

       OutputProfiler profiler = new OutputProfiler(new PDFParser(pdf));
       OutputProfile profile = profiler.getProfile();
       OutputProfile.Feature[] list = profile.isCompatibleWith(target);
       if (list != null) {
           profiler.apply(target);
       }

  This is an oversimplified example, as typically converting a PDF to a profile (known as "preflighting") requires more information. The `OutputProfiler` class allows you to specify various actions to perform on the PDF when converting - if specified these will involve a rebuild of the entire document, which can be time- consuming.

  As an example, assume a PDF has an embedded font in it - this is not allowed in PDF/A. To try to convert the PDF to PDF/A-1b, you could run the following code:

       PDF pdf = new PDF(new PDFReader(new File("unembeddedfont.pdf")));
       OutputProfiler profiler = new OutputProfiler(new PDFParser(pdf));
       OutputProfile profile = profiler.getProfile();
       ICC_Profile icc = ICC_Profile.getInstance(ColorSpace.CS_sRGB);
       OutputProfile target = new OutputProfile(OutputProfile.PDFA1b_2005, "sRGB", null, "http://www.color.org", null, icc);
       OutputProfile.Feature[] list = profile.isCompatibleWith(target);
       if (list != null) {
           profiler.apply(target);  // This line will fail
       }

  This will fail with an `IllegalStateException` ("Denied Feature 'Unembedded TrueType Font' is set"). To fix this you need to set an action on the `OutputProfiler` before you apply the new profile. This will cause the PDF to be rebuilt internally. Here's how the above example could be modified to replace some, or all unembedded fonts with an embedded font from the OS.

       PDF pdf = new PDF(new PDFReader(new File("unembeddedfont.pdf")));
       OutputProfiler profiler = new OutputProfiler(new PDFParser(pdf));
       OutputProfile profile = profiler.getProfile();
       ICC_Profile icc = ICC_Profile.getInstance(ColorSpace.CS_sRGB);
       OutputProfile target = new OutputProfile(OutputProfile.PDFA1b_2005, "sRGB", null, "http://www.color.org", null, icc);
       OutputProfile.Feature[] list = profile.isCompatibleWith(target);
       if (list != null) {
           OutputProfiler.AutoEmbeddingFontAction fontaction = new OutputProfiler.AutoEmbeddingFontAction();
           fontaction.add(new OpenTypeFont(new FileInputStream("C:\\Windows\\Fonts\\arial.ttf"), 2));
           profiler.setFontAction(fontaction);
           profiler.apply(target);
       }

  Since:
    2.18
  See Also:
    `OutputProfile`

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `static class` | `OutputProfiler.AutoEmbeddingFontAction` The `AutoEmbeddingFontAction` class is an implementation of `OutputProfiler.FontAction` that will replace unembedded fonts with embedded ones via a "best fit" algorithm.
    `static interface` | `OutputProfiler.ColorAction` An action that can be `set` on an OutputProfiler to replace Colors.
    `static interface` | `OutputProfiler.FontAction` An action that can be `set` on an OutputProfiler to replace one font with another in the PDF.
    `static class` | `OutputProfiler.ImageType` ImageType constants are passed in to the `setMaxImageDPI` method
    `static class` | `OutputProfiler.ProcessColorAction` The `ProcessColorAction` class is an implementation of `OutputProfiler.ColorAction` which will convert any process colors into the specified ColorSpace.
    `static class` | `OutputProfiler.RenderingIntent` RenderingIntent constants are passed in to the `OutputProfiler.ProcessColorAction.setRenderingIntent(org.faceless.pdf2.OutputProfiler.RenderingIntent)` method

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `OutputProfiler()` Create a new OutputProfiler
    `OutputProfiler(PDF pdf)` Create a new OutputProfiler and call `setPDF()`
    `OutputProfiler(PDFParser parser)` Create a new OutputProfiler and call `setParser()`

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `apply(OutputProfile targetprofile)` Set the specified `OutputProfile` on the PDF.
    `void` | `cancel()` Cancel this OutputProfiler's operation - if it is being run in another thread, that thread should terminate safely shortly after this method is called.
    `OutputProfile` | `getProfile()` Return the `OutputProfile` calculated by the `run()` method.
    `float` | `getProgress()` Return the progress of the `run()` operation, or 0 if this is not being run, has completed or has been cancelled.
    `boolean` | `isCancelled()` Return true if the `cancel()` method has been called.
    `boolean` | `isDone()` Return true if the `run()` method has completed or been cancelled, false if it's still running or has not yet been started.
    `boolean` | `isRunning()` Return true if the `run()` method is running in another thread, and false if it has completed, been cancelled or not yet started.
    `void` | `run()` Analyze the PDF and generate its profile.
    `void` | `setColorAction(OutputProfiler.ColorAction action)` Set the `OutputProfiler.ColorAction` to run on the PDF.
    `void` | `setFontAction(OutputProfiler.FontAction action)` Set the `OutputProfiler.FontAction` to run on the PDF.
    `void` | `setFull(boolean full)` Sets whether the OutputProfiler will create a full OutputProfile when it is run.
    `void` | `setHairlineWidth(float width)` If `Hairlines` are denied when a new profile is `applied`, they will be changed to lines of the specified width.
    `void` | `setMaxImageDPI(OutputProfiler.ImageType imagetype, float threshold, float target)` Set the maximum image resolution to be used in the PDF.
    `void` | `setParser(PDFParser parser)` Set the PDFParser to create the OutputProfile from.
    `void` | `setPDF(PDF pdf)` Set the PDF to create the OutputProfile from.
    `OutputProfile` | `waitForProfile()` Wait for the profiling operation running in this (or another) thread to finish, and return the profile when done.

    - ### Methods inherited from class java.lang.Object

      `equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

    - #### OutputProfiler

          public OutputProfiler()

      Create a new OutputProfiler

    - #### OutputProfiler

          public OutputProfiler(PDF pdf)

      Create a new OutputProfiler and call `setPDF()`
      Parameters:
        `pdf` - the PDF

    - #### OutputProfiler

          public OutputProfiler(PDFParser parser)

      Create a new OutputProfiler and call `setParser()`
      Parameters:
        `parser` - the PDFParser

  - ### Method Detail

    - #### setPDF

          public void setPDF(PDF pdf)

      Set the PDF to create the OutputProfile from. Setting just a PDF will allow only basic OutputProfile features to be extracted. Once set it cannot be changed.
      Parameters:
        `pdf` - the PDF to scan for features
      See Also:
        `setParser(org.faceless.pdf2.PDFParser)`, `setFull(boolean)`

    - #### setParser

          public void setParser(PDFParser parser)

      Set the PDFParser to create the OutputProfile from. Setting a PDFParser will allow both basic and full OutputProfile features to be extracted. Once set, it cannot be changed, but it can be reset by passing in null
      Parameters:
        `parser` - the PDFParser containing the PDF to scan for features
      See Also:
        `setPDF(org.faceless.pdf2.PDF)`, `setFull(boolean)`

    - #### setFull

          public void setFull(boolean full)

      Sets whether the OutputProfiler will create a full OutputProfile when it is run. This method simply creates a new `PDFParser` and calls `setParser(org.faceless.pdf2.PDFParser)`
      Parameters:
        `full` - whether to extract a full profile from the PDF.

    - #### run

          public void run()

      Analyze the PDF and generate its profile. Whether this method calculates a "basic" or "full" profile depends on whether a `PDFParser` was specified on this class, either in the constructor or by calling `setParser(org.faceless.pdf2.PDFParser)`. If available a full profile will be run, which can take some time. If not, a basic profile is generated which is essentially instantaneous.
      Specified by:
        `run` in interface `Runnable`
      See Also:
        `isRunning()`, `getProfile()`

    - #### cancel

          public void cancel()

      Cancel this OutputProfiler's operation - if it is being run in another thread, that thread should terminate safely shortly after this method is called. Once this object is cancelled, it cannot be restarted.
      See Also:
        `isCancelled()`

    - #### isRunning

          public boolean isRunning()

      Return true if the `run()` method is running in another thread, and false if it has completed, been cancelled or not yet started.
      See Also:
        `run()`

    - #### isDone

          public boolean isDone()

      Return true if the `run()` method has completed or been cancelled, false if it's still running or has not yet been started.

    - #### isCancelled

          public boolean isCancelled()

      Return true if the `cancel()` method has been called.
      See Also:
        `isRunning()`

    - #### getProfile

          public OutputProfile getProfile()

      Return the `OutputProfile` calculated by the `run()` method. If `run()` has not been called already, it will be called by this method. If it has already completed, it will return the result (or `null` if it failed). If it is currently running in another thread, this method will return `null` immediately.
      See Also:
        `isRunning()`

    - #### waitForProfile

          public OutputProfile waitForProfile()

      Wait for the profiling operation running in this (or another) thread to finish, and return the profile when done. This method will also wait if the profiling has not yet started.
      See Also:
        `isRunning()`

    - #### getProgress

          public float getProgress()

      Return the progress of the `run()` operation, or 0 if this is not being run, has completed or has been cancelled.
      Returns:
        the progress of the operation, from 0 to 1
      See Also:
        `isRunning()`

    - #### setHairlineWidth

          public void setHairlineWidth(float width)

      If `Hairlines` are denied when a new profile is `applied`, they will be changed to lines of the specified width. This will rebuild the PDF. If no hairlines are present in the PDF when this method is called, no rebuild will be performed.
      Parameters:
        `width` - the width to use to replace any hairlines. Must be > 0

    - #### setFontAction

          public void setFontAction(OutputProfiler.FontAction action)

      Set the `OutputProfiler.FontAction` to run on the PDF. This can be used to replace fonts in the PDF with new fonts. Calling this method will cause the PDF to be rebuilt in `apply()`.
      Parameters:
        `action` - the FontAction

    - #### setColorAction

          public void setColorAction(OutputProfiler.ColorAction action)

      Set the `OutputProfiler.ColorAction` to run on the PDF. This can be used to replace colors in the PDF. Calling this method will cause the PDF to be rebuilt in `apply()`.
      Parameters:
        `action` - the ColorAction

    - #### setMaxImageDPI

          public void setMaxImageDPI(OutputProfiler.ImageType imagetype,
                                     float threshold,
                                     float target)

      Set the maximum image resolution to be used in the PDF. If the PDF contains an image of the specified type which is not embedded at less than the specified threshold resolution, it will be resampled to the target resolution and replaced. Calling this method will cause the PDF to be rebuilt in `apply()`.
      Parameters:
        `imagetype` - the ImageType whether this applies to one-bit, gray or color images
        `target` - the resolution to test the image against - all copies of the image embedded in the PDF must be this resolution or higher for it to be resampled.
        `target` - the resolution to resample the image to.

    - #### apply

          public void apply(OutputProfile targetprofile)

      Set the specified `OutputProfile` on the PDF. The supplied "target" profile will have a number of features `denied` and `required`, and this method will {attempt to modify the PDF to match those requirements. If it's not possible then an `IllegalStateException` will be thrown.

      If the supplied profile references any features that require a full scan and the PDF has been loaded in (rather than create from scratch), then a full profile of the existing PDF must be `run()` to determine which features are currently set. If this is already `in progress` in another thread, this method will wait for it to complete. If it hasn't yet been started, it will be started on this thread by calling `getProfile()`. If no `PDFParser` has been set (in the constructor or through the `setParser` method) then a full profile cannot be created, and an `IllegalStateException` will be thrown.

      If a `OutputProfiler.FontAction` or `OutputProfiler.ColorAction` has been set on this class or `setMaxImagePI` has been called, an extra stage will be run which rebuilds the PDF content. It is also run if the full profile shows up any `hairlines` and the `setHairlineWidth` method was calling with a non-zero value.

      After this stage, or if no actions or hairline-replacement are specified, then the method will attempt to modify the PDF to add or remove required or denied features, as specified in the target profile. If that completes successfully, the OutputIntent on the target profile will be applied to the PDF and this method will complete.

      Parameters:
        `targetprofile` - the OutputProfile that this PDF should be converted to match.

Copyright © 2001-2015 Big Faceless Organization