65.9K
CodeProject 正在变化。 阅读更多。
Home

在.NET应用程序中托管8bf插件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.82/5 (14投票s)

2014年8月26日

Ms-PL

6分钟阅读

viewsIcon

38524

downloadIcon

1448

一个C#库,用于在.NET 2.0及更高版本中托管Photoshop兼容滤镜

目录

引言

许多图像编辑器和查看器允许用户使用效果或滤镜插件调整图像。其中最常见的类型是Adobe® Photoshop®以及其他实现Photoshop插件API的软件使用的8bf滤镜插件。

该库允许使用.NET 2.0及更高版本构建的应用程序使用第三方8bf滤镜。它可以运行32位或64位滤镜,并支持处理8位或16位每通道的灰度和RGBA图像,具体取决于所选滤镜支持的图像类型。对于16位每通道图像,由于GDI+中缺乏对16位图像的可靠支持,因此必须使用.NET 3.0及更高版本中基于WIC的类。

演示应用程序是使用.NET 4.5.2构建的,为了使该库与.NET 3.5及更早版本配合使用,您必须使用适当的目标框架重新构建PSFilterHost项目。

该库的最新版本可以通过NuGet或从Codeplex上的项目页面下载。

背景

Adobe® Photoshop® SDK允许第三方开发人员创建导入、导出、滤镜、格式和其他类型的插件。尽管它不旨在帮助开发人员编写插件主机,但它也被用作在其他应用程序中托管插件的指南。

该库基于Photoshop SDK 5.0版本,版本7.0及更高版本具有许可协议,禁止其他主机应用程序的开发人员使用其中包含的信息。因此,必须使用PiPL资源加载和属性套件调用的调试输出来解码新的PiPL和属性套件值。

Using the Code

搜索目录中的滤镜

第一步是搜索目录(以及可选的任何子目录)以查找8bf滤镜。搜索的目录可能包含滤镜和指向其他位置的滤镜快捷方式。

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

在不支持的图像模式下禁用滤镜

许多滤镜不支持处理WIC可以加载的所有PixelFormat。例如,某些滤镜可能不支持灰度或16位每通道图像。主机应用程序可以在加载新图像时禁用不支持处理当前PixelFormat的滤镜。

private void EnableFiltersForImageFormat()
{
    if (this.srcImage != null)
    {
        System.Windows.Media.PixelFormat format = this.srcImage.Format;

        ToolStripItemCollection items = this.filtersToolStripMenuItem.DropDownItems;
        for (int i = 0; i < items.Count; i++)
        {
            ToolStripMenuItem menu = (ToolStripMenuItem)items[i];

            if (menu.HasDropDownItems)
            {
                ToolStripItemCollection nodes = menu.DropDownItems;
                int nCount = nodes.Count;
                List<bool> catEnabled = new List<bool>(nCount);

                for (int j = 0; j < nCount; j++)
                {
                    PluginData data = (PluginData)nodes[j].Tag;

                    bool enabled = data.SupportsImageMode(format);
                    catEnabled.Add(enabled);
                    nodes[j].Enabled = enabled;
                }

                menu.Enabled = catEnabled.Contains(true);
            }
            else
            {
                PluginData data = (PluginData)menu.Tag;

                menu.Enabled = data.SupportsImageMode(format);
            }
        }
    }
    else
    {
        // An image has not been loaded so disable all menus.
        ToolStripItemCollection items = filtersToolStripMenuItem.DropDownItems;
        for (int i = 0; i < items.Count; i++)
        {
            items[i].Enabled = false;
        }
    }
}

可选的回调、方法、事件和属性

回调

中止回调允许主机向滤镜发出信号以取消任何当前正在进行的渲染。滤镜将在长时间操作期间轮询此回调,如果它返回true,则停止处理。

private bool AbortFilterCallback()
{
    return escapePressed;
}

颜色选择器回调允许主机在滤镜请求用户选择颜色时显示自己的颜色选择器,而不是Windows颜色对话框。滤镜可以为用户指定一个提示(例如请选择一种颜色:),如果滤镜没有设置提示,则这将是一个空string。红色、绿色和蓝色参数指定滤镜希望在主机颜色对话框中选择的初始颜色。

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

方法

SetColorProfiles方法允许主机指定用于对滤镜显示的预览图像应用颜色校正的文档和监视器的国际颜色联盟 (ICC) 颜色配置文件。

this.hostColorProfiles = new HostColorManagement(documentProfile, monitorProfilePath);

事件

UpdateProgress事件允许滤镜通知主机其渲染进度。

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

属性

HostInfo属性允许滤镜从主机检索有关当前文档的信息,例如标题和首选标尺测量单位。

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

PseudoResources属性允许滤镜存储将在当前会话中持久存在的数据,这可用于滤镜之间的通信。

PseudoResourceCollection pseudoResources = null;

执行滤镜

用户选择要运行的滤镜后,可以通过以下步骤执行:

  1. 调用PSFilterHost构造函数重载之一。
  2. 可选地设置中止回调、颜色选择器回调、进度事件处理程序和其他属性。
  3. 设置FilterParameters属性以恢复上次使用的设置(如果有)。
  4. 使用要执行的滤镜的PluginData调用RunFilter重载之一。
  5. 更新输出图像并保存滤镜可能已修改的FilterParameters和其他属性。

FilterParameters设置为执行具有先前会话设置的滤镜时,RunFilter(PluginData)方法将不显示用户界面。RunFilter(PluginData, Boolean)重载允许主机显示初始化为先前设置的滤镜用户界面。除非是通过“重复滤镜”命令调用的,否则主机应显示滤镜用户界面。

using (PSFilterHost host = new PSFilterHost(source, foreColor, backColor, selection, owner))
{
    host.SetAbortCallback(new AbortFunc(AbortFilterCallback));
    host.SetPickColorCallback(new PickColor(PickColorCallback));
    host.UpdateProgress += new EventHandler(UpdateProgress);

    if (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 (this.hostColorProfiles != null)
    {
        host.SetColorProfiles(this.hostColorProfiles);
    }
 
    if (host.RunFilter(pluginData, showUI))
    {
        this.destinationImage = host.Dest;
 
        if (showUI)
        {
            // Add or update the last used parameters of the filter. 
            if (this.filterParameters.ContainsKey(pluginData))
            {
                this.filterParameters[pluginData] = host.FilterParameters;
            }
            else
            {
                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;
        }
    }
}

显示滤镜“关于”框

ShowAboutBox函数显示滤镜的“关于”框(如果有)。

PSFilterHost.ShowAboutDialog(pluginData, parentWindowHandle);

关注点

Photoshop API使用16位有符号整数作为图像尺寸,因此此库支持最大宽度和/或高度为32,000像素,Photoshop 7.0及更早版本限制为30,000像素,Photoshop CS及更高版本增加到300,000像素。

EXIF和XMP元数据作为指向EXIF的TIFF容器开头或XMP的XML数据包开头的指针暴露给滤镜。

5.0 PICA套件仅对某些滤镜启用,因为许多滤镜在使用可能未实现的套件之前不检查返回代码。

自.NET 3.5发布以来,C#和VB.NET编译器为32位应用程序启用了数据执行保护。由于许多滤镜不兼容,您必须使用editbin或类似工具清除IMAGE_DLLCHARACTERISTICS_NX_COMPAT标志(有关更多信息,请参阅NXCOMPAT和C#编译器)。

参考文献

历史

12-27-2015

  • 更新了源代码和演示应用程序以匹配Codeplex上的1.4.0.0版本
  • 在“可选回调、事件和属性”部分添加了方法标题
  • 更新了“执行滤镜”部分以使用新的SetColorProfiles(HostColorManagement)方法

10-19-2015

  • 更新了源代码和演示应用程序以匹配Codeplex上的1.3.0.0版本
  • 更改了“执行滤镜”部分以使用新的RunFilter(PluginData, Boolean)重载

04-12-2015

  • 更新了源代码和演示应用程序以匹配Codeplex上的1.2.0.0版本
  • 更改了“搜索目录中的滤镜”示例代码以使用新的System.IO.SearchOption重载

12-03-2014

  • 更新了源代码和演示应用程序以匹配Codeplex上的1.1.0.6版本

11-08-2014

  • 添加了一个描述如何禁用不支持当前图像模式的滤镜的部分
  • 更新了源代码和演示应用程序以匹配Codeplex上的1.1.0.5版本

09-28-2014

  • 添加了一个描述可选回调、事件和属性的部分

08-30-2014

  • 添加了一些关于32位主机应用程序和数据执行保护的信息
  • 更新了源代码和演示应用程序以匹配Codeplex上的1.1.0.4版本

08-25-2014

  • 原文
© . All rights reserved.