Click here to Skip to main content
Click here to Skip to main content

Hosting 8bf plugins in a .NET Application

, 29 Sep 2014 Ms-PL
Rate this:
Please Sign up or sign in to vote.
A C# library to host Photoshop-compatible filters in .NET 2.0 and later



Many image editors and viewers allow the user to adjust the image using effect or filter plugins. One of the most common types is the 8bf filter plugin used by Adobe® Photoshop® and other software that implements the Photoshop plugin API.

This library allows applications built with .NET 2.0 and later to use 3rd party 8bf filters. It can run either 32-bit or 64-bit filters and supports processing grayscale and RGBA images in 8 or 16 bits per channel depending on the supported image types of the selected filter. For 16 bit per channel images the WIC-based classes in .NET 3.0 and later must be used due to the lack of reliable support for 16-bit images in GDI+.

The demo application is built with .NET 4.0, in order for the library work with .NET 3.5 and earlier you must rebuild the PSFilterHost project with the appropriate target framework.

The latest version of this library can be downloaded using NuGet or from the project page on Codeplex.


The Adobe® Photoshop® SDK allows 3rd party developers to create Import, Export, Filter, Format and other types of plugins. Although it was not intended to help developers write a plugin host it has also been used as a guide to hosting plugins in other applications.

This library is based on version 5.0 of the Photoshop SDK version 7.0 and later have a license agreement that prevents developers of other host applications from using the information that they contain. Because of this the new PiPL and Property suite values must be decoded using the debug output from the PiPL resource loading and Property suite calls.

Using the code

Searching a directory for filters

The first step is to search a directory (and optionally any sub directories) for 8bf filters. The directories that are searched may contain both filters and shortcuts to filters in other locations.

Dictionary<string, ToolStripItem> filters = new Dictionary<string, ToolStripItem>();
List<ToolStripItem> aboutMenuItems = new List<ToolStripItem>();
foreach (PluginData pluginData in PSFilterHost.EnumerateFilters(path, true))
    ToolStripMenuItem child = new ToolStripMenuItem(pluginData.Title, null, RunFilter_Click);
    child.Name = pluginData.Title;
    child.Tag = pluginData;
    ToolStripMenuItem about = new ToolStripMenuItem(pluginData.Title, null, ShowAboutDialog);
    about.Tag = pluginData;
    if (filters.ContainsKey(pluginData.Category))
        ToolStripMenuItem parent = filters[pluginData.Category];
        if (!parent.DropDownItems.ContainsKey(pluginData.Title))
            if (pluginData.HasAboutBox)
        ToolStripMenuItem parent = new ToolStripMenuItem(pluginData.Category, null, child);
        filters.Add(pluginData.Category, parent);
        if (pluginData.HasAboutBox)

Optional callbacks, events and properties


The abort callback allows the host to signal the filter to cancel any rendering currently in progress. The filter will poll this callback during long operations and stop processing if it returns true.

private bool AbortFilterCallback()
    return escapePressed;

The color picker callback allows the host to show it's own color picker in place of the Windows color dialog when a filter requests that the user choose a color. The filter may specify a prompt for the user (e.g. Please choose a color: ), if the filter does not set a prompt this will be an empty string. The red, green and blue parameters specify the initial color that the filter wants selected in the host's color dialog.

private ColorPickerResult PickColorCallback(string prompt, byte red, byte green, byte blue)
    ColorPickerResult color = null;

    using (ColorPickerForm dialog = new ColorPickerForm(prompt))
        dialog.SetDefaultColor(red, green, blue);

        if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            color = new ColorPickerResult(dialog.UserPrimaryColor);

    return color;


The UpdateProgress event allows the filter to inform the host of it's rendering progress.

private void UpdateProgress(object sender, FilterProgressEventArgs e)
    this.toolStripProgressBar1.Value = e.Progress;


The HostInfo property allows the filter to retrieve information about the current document from the host, such as the title and preferred ruler measurement unit.

this.hostInfo = new HostInformation();
this.hostInfo.Title = this.imageFileName;
this.hostInfo.RulerUnit = HostRulerUnit.Inches;

The PseudoResources property allows the filter to store data which will persist for the current session, this can be used for communication between filters.

PseudoResourceCollection pseudoResources = null;

Executing a filter

After the user selects a filter to run it can be executed with the following steps:

  1. Calling one of the PSFilterHost constructor overloads.
  2. Optionally set the abort callback, progress event handler, color picker callback and other properties.
  3. If the filter is called by a "Repeat Filter" command set the ParameterData that contains the previous settings to execute the filter without showing it's dialog.
  4. Calling the RunFilter method with the PluginData of the filter you want to execute.
  5. Update the output image and save the ParameterData and other properties that the filter may have modified.
using (PSFilterHost host = new PSFilterHost(source, foreColor, backColor, selection, owner))
    host.SetAbortCallback(new AbortFunc(AbortFilterCallback));
    host.UpdateProgress += new EventHandler(UpdateProgress);
    host.SetPickColorCallback(new PickColor(PickColorCallback));
    if (repeatFilter && this.filterParameters.ContainsKey(pluginData))
        host.FilterParameters = this.filterParameters[pluginData];
    if ((this.pseudoResources != null) && this.pseudoResources.Count > 0)
        host.PseudoResources = this.pseudoResources;
    host.HostInfo = this.hostInfo;
    if (host.RunFilter(pluginData))
        this.destinationImage = host.Dest;
        if (!repeatFilter)
            // Add or update the  last used parameters of the filter. 
            if (this.filterParameters.ContainsKey(pluginData))
                this.filterParameters[pluginData] = host.FilterParameters;
                this.filterParameters.Add(pluginData, host.FilterParameters);
            // Save the other information that may have been changed by the filter.
            this.pseudoResources = host.PseudoResources;
            this.hostInfo = host.HostInfo;

Displaying the filter about box

The ShowAboutBox function displays the filter's about box (if it has one).

PSFilterHost.ShowAboutDialog(pluginData, parentWindowHandle);

Points of Interest

The Photoshop API uses 16-bit signed integers for the image dimensions so this library supports a maximum of 32,000 pixels in width and/or height, Photoshop 7.0 and earlier were limited to 30,000 pixels which was increased to 300,000 pixels in Photoshop CS and later.

The EXIF and XMP metadata is exposed to the filters as a pointer to the start of the TIFF container for EXIF or the start of the XML packet for XMP.

The 5.0 PICA suites are only enabled for certain filters due to the fact that many filters do not check the return code before using a suite that may not be implemented.

Since the release of .NET 3.5 the C# and VB.NET compilers enable Data Execution Prevention for 32-bit applications, as many filters are not compatible with it you must use editbin or a similar tool to clear the IMAGE_DLLCHARACTERISTICS_NX_COMPAT flag (see NXCOMPAT and the C# compiler for more information).


Photoshop 2.0 Filter reference

Adobe Photoshop 3.0.4 SDK Guide



  • Added a section describing the optional callbacks, events and properties.


  • Added some information about 32-bit host applications and Data Execution Prevention.
  • Updated source code and demo application to match the release on Codeplex.


  • Original article


This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


About the Author


United States United States
No Biography provided

Comments and Discussions

GeneralMy vote of 5 PinprofessionalVolynsky Alex27-Aug-14 13:25 
QuestionDowload files are missing Pinmemberjlopez78826-Aug-14 5:17 
AnswerRe: Dowload files are missing Pinmember0xC000005426-Aug-14 12:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.141022.2 | Last Updated 29 Sep 2014
Article Copyright 2014 by 0xC0000054
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid