search
HomeWeb Front-endPS TutorialHow to write a Photoshop filter (1)

                                                                                                                                                                                                                                                    # But the source code is missing. And we're going to ask, how do we program a Photoshop filter from scratch? How do we build the simplest basic framework of the PS filter plug-in, and then continue to add the functions we want on this basis? Here, I will answer a question posed to me by a netizen as an example, starting from the most basic construction project. This example (also the problem of this netizen) is that he wants to make the simplest filter, which is to just fill the image with "red". For PS users, this is of course a very simple and easy thing. It only requires a shortcut key operation (filters are usually used to complete more complex tasks). We will start from this most basic example to explain how to write filters. mirror process. A source code download link for the example will be attached at the end of the article.

          (1) The development tool we use is Visual Studio .NET 2005 version, paired with Photoshop SDK CS (essentially a distribution package composed of some C++ code and resources and other files). The development languages ​​used are C and C++.

Is it okay to use C# or other languages? At present, it seems that it is not feasible. Therefore, to develop Photoshop filters, developers must have a good foundation in C and C++, which is the most important. Of course it would be better if the developer is familiar with image processing and basic knowledge of digital signal processing.

                            (2) After preparing the tools, we open VS2005 and create a new project. We choose Win32 of Visual C++ as the project template. For the project name, we enter the name of the filter we want to create, such as the "FillRed" filter, which means that this filter is used to fill in red, as shown below:

                            After clicking OK, on ​​the pop-up settings dialog box, click "Application Settings", select "DLL" in the application type, and then click OK. How to write a Photoshop filter (1)

How to write a Photoshop filter (1)

# (3) The project is established as a standard DLL project. We right -click the project name in the "Solution Resource Manager" and we do in the project attributes. We do it in the project attribute Some settings are as follows:

(a) In general, I like to change the character set used by the project to "use multi-byte character set", which allows us to use char* and directly use double The string type of the quote. Of course, Unicode can also be used, but the string functions used by the two will be different. You can set it up as you like.

              (b) The project has been output as DLL by default. Since the extension of Photoshop’s filter file is 8bf, we set the extension of the output file to 8bf in Linker->General. Change it to as shown below.

How to write a Photoshop filter (1)# (C) Click the tool- "option below, in the pop-up dialog box, select" Project and Solution "-" VC ++ directory, and in the right drop box Select "Include Files": Add several Photoshop SDK folders to the VC++ include directory of the option. This will make it easier for us to compile the project without reporting an error that the file cannot be found. As shown below:

           How to write a Photoshop filter (1)

                                                                                                                                                                                                                                                      

The code of this source file is replaced with the following:

// FillRed.cpp : 定义 DLL 应用程序的入口点。
//

#include "stdafx.h"
#include "PiFilter.h"
#include <stdio.h>

#ifdef _MANAGED
#pragma managed(push, off)
#endif


#ifndef DLLExport
#define DLLExport extern "C" __declspec(dllexport)
#endif

//=======================================
//        全局变量
//=======================================
//dll instance
HINSTANCE        dllInstance;
FilterRecord*    gFilterRecord;
int32*            gData;
int16*            gResult;
SPBasicSuite*    sSPBasic = NULL;
#define            TILESIZE    128 //贴片大小:128 * 128 
Rect            m_Tile;            //当前图像贴片(128*128)


//=======================================
//        函数列表
//=======================================
//辅助函数,拷贝矩形
void CopyPsRect(Rect* src, Rect* dest);
//辅助函数,把一个矩形置为空矩形
void ZeroPsRect(Rect* dest);
void DoParameters();
void DoPrepare();
void DoStart();
void DoContinue();
void DoFinish();


//辅助函数,拷贝矩形
void CopyPsRect(Rect* src, Rect* dest)
{
    dest->left = src->left;
    dest->top = src->top;
    dest->right = src->right;
    dest->bottom = src->bottom;
}

//辅助函数,把一个矩形置为空矩形
void ZeroPsRect(Rect* dest)
{
    dest->left = 0;
    dest->top = 0;
    dest->right = 0;
    dest->bottom = 0;
}

//DLLMain
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    dllInstance = static_cast<HINSTANCE>(hModule);
    return TRUE;
}

#ifdef _MANAGED
#pragma managed(pop)
#endif

//===================================================================================================
//------------------------------------ 滤镜被ps调用的函数 -------------------------------------------
//===================================================================================================
DLLExport void PluginMain(const int16 selector,    void * filterRecord, int32 *data, int16 *result)
{
    gData = data;
    gResult = result;
    
    if (selector == filterSelectorAbout)
    {
        //显示关于对话框
        MessageBox(GetActiveWindow(), "FillRed Filter: 填充红色-- by hoodlum1980", "关于 FillRed", MB_OK);
    } 
    else 
    {
        gFilterRecord = (FilterRecordPtr)filterRecord;
        sSPBasic = gFilterRecord->sSPBasic;
    }

    switch (selector)
    {
        case filterSelectorAbout:
            //DoAbout();
            break;
        case filterSelectorParameters:
            DoParameters();
            break;
        case filterSelectorPrepare:
            DoPrepare();
            break;
        case filterSelectorStart:
            DoStart();
            break;
        case filterSelectorContinue:
            DoContinue();
            break;
        case filterSelectorFinish:
            DoFinish();
            break;
        default:
            *gResult = filterBadParameters;
            break;
    }
}

//这里准备参数,就这个滤镜例子来说,我们暂时不需要做任何事
void DoParameters()
{
}

//在此时告诉PS(宿主)滤镜需要的内存大小
void DoPrepare()
{
    if(gFilterRecord != NULL)
    {
        gFilterRecord->bufferSpace = 0;
        gFilterRecord->maxSpace = 0;
    }
}

//inRect     : 滤镜请求PS发送的矩形区域。
//outRect    : 滤镜通知PS接收的矩形区域。
//filterRect : PS通知滤镜需要处理的矩形区域。

//由于我们是使用固定的红色进行填充,实际上我们不需要请求PS发送数据
//所以这里可以把inRect设置为NULL,则PS不向滤镜传递数据。
void DoStart()
{
    if(gFilterRecord == NULL)
        return;

    //我们初始化第一个Tile,然后开始进行调用
    m_Tile.left = gFilterRecord->filterRect.left;
    m_Tile.top = gFilterRecord->filterRect.top;
    m_Tile.right = min(m_Tile.left + TILESIZE, gFilterRecord->filterRect.right);
    m_Tile.bottom = min(m_Tile.top + TILESIZE, gFilterRecord->filterRect.bottom);

    //设置inRect, outRect
    ZeroPsRect(&gFilterRecord->inRect); //我们不需要PS告诉我们原图上是什么颜色,因为我们只是填充
    CopyPsRect(&m_Tile, &gFilterRecord->outRect);

    //请求全部通道(则数据为interleave分布)
    gFilterRecord->inLoPlane = 0;
    gFilterRecord->inHiPlane = 0;
    gFilterRecord->outLoPlane = 0;
    gFilterRecord->outHiPlane = (gFilterRecord->planes -1);
}

//这里对当前贴片进行处理,注意如果用户按了Esc,下一次调用将是Finish
void DoContinue()
{
    if(gFilterRecord == NULL)
        return;

    //定位像素
    int planes = gFilterRecord->outHiPlane - gFilterRecord->outLoPlane + 1; //通道数量         
    uint8 *pData=(uint8*)gFilterRecord->outData;

    //扫描行宽度(字节)
    int stride = gFilterRecord->outRowBytes;

    //我们把输出矩形拷贝到 m_Tile
    CopyPsRect(&gFilterRecord->outRect, &m_Tile);
    for(int j = 0; j< (m_Tile.bottom - m_Tile.top); j++)
    {
        for(int i = 0; i< (m_Tile.right - m_Tile.left); i++)
        {
            //为了简单明了,我们默认把图像当作RGB格式(实际上不应这样做)
            //pData[ i*planes + j*stride + 0 ] = 0;    //Red  
            //pData[ i*planes + j*stride + 1 ] = 0;    //Green 
            pData[ i*planes + j*stride + 2 ] = 255;    //Blue
        }
    }

    //判断是否已经处理完毕
    if(m_Tile.right >= gFilterRecord->filterRect.right && m_Tile.bottom >= gFilterRecord->filterRect.bottom)
    {
        //处理结束
        ZeroPsRect(&gFilterRecord->inRect);
        ZeroPsRect(&gFilterRecord->outRect);
        ZeroPsRect(&gFilterRecord->maskRect);
        return;
    }
    //设置下一个tile
    if(m_Tile.right < gFilterRecord->filterRect.right)
    {
        //向右移动一格
        m_Tile.left = m_Tile.right;
        m_Tile.right = min(m_Tile.right + TILESIZE, gFilterRecord->filterRect.right);
        
    }
    else
    {
        //向下换行并回到行首处
        m_Tile.left = gFilterRecord->filterRect.left;
        m_Tile.right = min(m_Tile.left + TILESIZE, gFilterRecord->filterRect.right);
        m_Tile.top = m_Tile.bottom;
        m_Tile.bottom = min(m_Tile.bottom + TILESIZE, gFilterRecord->filterRect.bottom);
    }

    ZeroPsRect(&gFilterRecord->inRect);
    CopyPsRect(&m_Tile, &gFilterRecord->outRect);
    //请求全部通道(则数据为interleave分布)
    gFilterRecord->inLoPlane = 0;
    gFilterRecord->inHiPlane = 0;
    gFilterRecord->outLoPlane = 0;
    gFilterRecord->outHiPlane = (gFilterRecord->planes -1);
}

//处理结束,这里我们暂时什么也不需要做
void DoFinish()
{
}


// FillRed.cpp: Defines the entry point of the DLL application.
//

#include
"stdafx.h"
#include
"PiFilter.h"
#include
< ;stdio.h>

#ifdef _MANAGED
#pragma managed(push, off)
endif


ifndef DLLExport
#define DLLExport extern "C" __declspec(dllexport)
endif

//==========================================
// Global variables
//================ ========================
//dll instance
HINSTANCE dllInstance;
FilterRecord
* gFilterRecord;
int32
*## gData;int16
*                                                                                                                                                                                                                                                 ;
#define TILESIZE 128 //Tile size: 128 * 128
Rect       m_Tile; ======================================// Function list//
========================== =============
//
Auxiliary function, copy rectangle

void
CopyPsRect(Rect
* src, Rect
*## dest);
//
Auxiliary function, set a rectangle to an empty rectangle
void
ZeroPsRect(Rect * dest);void DoParameters();
void DoPrepare(); void
DoStart();void DoContinue();
void DoFinish();


//Auxiliary function, copy rectangle
void CopyPsRect(Rect* src, Rect* dest )
{
dest
->left = src->left;
dest
->top = src->top;
dest
->right = src-> right;
dest
->bottom = src-> ;bottom;
}

//Auxiliary function, set a rectangle to an empty rectangle
void ZeroPsRect(Rect*## dest){
dest
-> left = 0; dest
-> top = 0; dest
-> right = 0; dest
->bottom = 0;}


//DLLMain
##BOOL APIENTRY DllMain( HMODULE hModule,
                                                                                                                                                                                                                                           ){
dllInstance

=

static_cast
HINSTANCE>(hModule); return
TRUE;
}#ifdef _MANAGED

#pragma

managed(pop)
#endif
##//
============== ================================================== ====================================
// ------------------------------------ The function called by ps for the filter ---- ---------------------------------------
//==================================== ================================================== =============
##DLLExport void PluginMain( const int16 selector, void * filterRecord, int32 *data, int16 *result){
gData
= data; gResult
= result;

if (selector == filterSelectorAbout)                                                                                                                                                                                                                                                                                      // #"

FillRed Filter: Fill Red -- by hoodlum1980
", "
About FillRed", MB_OK); } else { gFilterRecord = (FilterRecordPtr)filterRecord; sSPBasic

=
gFilterRecord->

sSPBasic;
}     
switch
(selector)                                                                                                                                           #//DoAbout();
##                    

break
;                           case

filterSelectorParameters:
                     DoParameters(); filterSelectorPrepare: DoPrepare();
break
; filterSelectorStart: DoStart()
##; # Case FilterselectorContinue:
Docontinue ();
break;
                                                                           
##;                                                                                                                                         filterBadParameters;         

break
;                                                                                                          Prepare the parameters here. For this filter example, we don’t need to do anything for now
void
DoParameters()
{}//At this time tell PS (host) the memory size required for the filter
void

DoPrepare()
{
if(gFilterRecord !=
NULL)                                                                                                                                                         gFilterRecord‐>

bufferSpace                                  
gFilterRecord
->maxSpace =
0;
}
}
//inRect : The filter requests the rectangular area sent by PS.
//
outRect : The rectangular area that the filter notifies PS to receive. //filterRect: The rectangular area that the PS notification filter needs to process. //Since we use a fixed red color for filling, we actually don’t need to request PS to send data
// So here you can set inRect to NULL, then PS will not pass data to the filter. ##void DoStart(){

if

(gFilterRecord
== NULL)
return;
//
We initialize the first Tile and then start calling
## m_Tile.left
=
gFilterRecord- >filterRect.left;
m_Tile.top
= gFilterRecord

->
filterRect.top ; m_Tile.right = min(m_Tile.left
+
TILESIZE, gFilterRecord->

filterRect.right);
m_Tile.bottom = min(m_Tile.top + TILESIZE, gFilterRecord->filterRect.bottom);

//Set inRect, outRect
ZeroPsRect(&gFilterRecord->inRect); //We don’t need PS to tell us What color is on the original image, because we just fill in
## CopyPsRect(&m_Tile, & gFilterRecord->outRect);
 
//Request all channels (then The data is interleave distribution)
## gFilterRecord
->inLoPlane = 0; gFilterRecord
->
inHiPlane = 0; gFilterRecord
->
outLoPlane = 0; gFilterRecord
->
outHiPlane = (gFilterRecord- >planes -1);}


//
The current patch is processed here. Note that if the user presses Esc, the next call will be Finish
void
DoContinue( ){    

if
(gFilterRecord   == NULL)                                                                                            ##;
//
Positioning pixel
int
planes = gFilterRecord->outHiPlane - gFilterRecord->outLoPlane + 1; //Number of channels                                                                                                                                                                                      (uint8*)gFilterRecord->
outData;//Scan line width (bytes)
int stride = gFilterRecord->outRowBytes;

//We copy the output rectangle to m_Tile
## CopyPsRect(&gFilterRecord->outRect, &m_Tile);
for(int j = 0; j (m_Tile.bottom - m_Tile.top); j++) {
                                                           #(
int i = 0; i (m_Tile.right - m_Tile.left); i++) {           //
For the sake of simplicity and clarity, we default to treating the image as RGB format (actually this should not be done)
         
///pData[ i*planes + j*stride + 0 ] = 0; #pData[ i*planes + j*stride + 1 ] = 0;
//Green
#*
planes + j*stride
+ 2 ] = 255; //Blue##                                                                                             Has it been processed? if(m_Tile.right >= gFilterRecord->filterRect.right && m_Tile.bottom >= gFilterRecord-> Filterrect.bottom)
{
##// ## Treatment ended # Zeropsrect (
&gFilterRecord->inRect);        ZeroPsRect(&
gFilterRecord->outRect);  ZeroPsRect(&
gFilterRecord->maskRect);                                                                                                                                             
##if(m_Tile.right

gFilterRecord- >filterRect.right)
{
    //Move one space to the right                 m_Tile.left  = m_Tile.right;
                m_Tile.right
+
TILESIZE, gFilterRecord->filterRect.right);
               
            else
# {
// # #       m_Tile.left = gFilterRecord

->
filterRect.left;        m_Tile.right =

min(m_Tile.left
+ TILESIZE, gFilterRecord->
filterRect.right); m_Tile.top = m_Tile.bottom; m_Tile.bottom =
min(m_Tile.bottom
+ TILESIZE, gFilterRecord->filterRect.bottom); } ZeroPsRect(
&
gFilterRecord->
inRect);CopyPsRect(&m_Tile, &gFilterRecord->outRect);
   
//Request all channels (the data is interleave distributed)
     gFilterRecord-> ;inLoPlane = 0;
gFilterRecord
->inHiPlane = 0;
gFilterRecord
->outLoPlane = 0;
gFilterRecord
->outHiPlane = (gFilterRecord->planes -1 );
}

//The processing is over, we don’t need to do anything here for now
void DoFinish()
{
}

## The above code is also a filter From the basic framework, we can see that one of the export functions that the DLL will provide is the PluginMain function. We will segment the image into 128*128 pixel slices, which allows a smaller amount of data to be transferred between PS and the filter each time. Especially for very large images, slicing processing will help cope with tight memory situations, which is also advocated by Photoshop. 64*64 or 128*128 are more typical sizes.

The calling process is to initialize the first tile (Tile) in the start call, and then we set the first tile to outRect, indicating that we request PS to provide a buffer to receive the rectangle The processed data at the location. As for inRect, since we are just filling, we don't care about the original color of the image, so inRect can be set to "empty rectangle". Image Channels Here, for the sake of intuitiveness and simplicity of the code, we only consider RGB images, that is, images with 3 channels. After setting the first outRect, PS will start calling continue in sequence, and the patches will be collaged from left to right and from top to bottom until all patches are processed. Note that inData and outData are the application data and "writeback buffer" provided by PS to the filter. One is for reading and the other is for writing. Their sizes are controlled by the data filled in when the filter notifies PS of the request. Operation Time must never cross its boundaries.

                                                                                                                      [

Note]Please be careful when operating the code of filter processing data, once Pointer out of bounds will cause Photoshop program to crash!

For details about the main code of this filter, please see the code comments and the explanation in my previous article. And the official documentation of PS SDK. We will not elaborate on the principle of the code here, because it is very simple. All the above codes need to reference the header files in ps sdk.

## (4) At this time, the project can be successfully compiled. But the next step is to invest in PIPL resources.

                                                                                                                                                                                                          must be inserted into the PIPL resource for the filter to be correctly recognized and loaded by Photoshop. According to the documentation provided by PS, PIPL is pronounced as "pipple", which means Plug-In Property List. It is a flexible, extensible data structure used to represent plug-in module metadata (metadata). pipl includes all the information for Photoshop to recognize and load plug-in modules, including some tags, various static properties that control each plug-in, etc. Your filter can contain one or more "pipl" structures.

The process of inserting pipl resources for filters is as follows. First, we need to add a *.r (Macintosh Rez file) file to the project, and then use cl.exe to compile this file into a *.rr file. Finally, use CnvtPipl.Exe, a resource conversion tool provided by Ps SDK, to convert the *.rr file into a *.pipl file, then add a *.rc resource file for the filter, and include the pipl file at the end of the rc file.

                    ps sdk has provided us with a common r file, including common attribute definitions, which is the PIGeneral.r file.

           (a) Next we will add an r file to the project, right-click the "Resource Files" folder in the resource manager, click to add a new file, and enter "FillRed.r" as the file name. Double-click the file to open it and copy the following content:

// ADOBE SYSTEMS INCORPORATED
// Copyright  1993 - 2002 Adobe Systems Incorporated
// All Rights Reserved
//
// NOTICE:  Adobe permits you to use, modify, and distribute this 
// file in accordance with the terms of the Adobe license agreement
// accompanying it.  If you have received this file from a source
// other than Adobe, then your use, modification, or distribution
// of it requires the prior written permission of Adobe.
//-------------------------------------------------------------------------------
#define plugInName            "FillRed Filter"
#define    plugInCopyrightYear "2009"
#define plugInDescription \
    "FillRed Filter.\n\t - http:\\www.cnblogs.com\hoodlum1980"

#include "E:\Codes\Adobe Photoshop CS2 SDK\samplecode\common\includes\PIDefines.h"

#ifdef __PIMac__
    #include "Types.r"
    #include "SysTypes.r"
    #include "PIGeneral.r"
    #include "PIUtilities.r"
    #include "DialogUtilities.r"
#elif defined(__PIWin__)
    #define Rez
    #include "PIGeneral.h"
    #include "E:\Codes\Adobe Photoshop CS2 SDK\samplecode\common\resources\PIUtilities.r"
    #include "E:\Codes\Adobe Photoshop CS2 SDK\samplecode\common\resources\WinDialogUtils.r"
#endif

resource &#39;PiPL&#39; ( 16000, "FillRed", purgeable )
{
    {
        Kind { Filter },
        Name { plugInName },
        Category { "Demo By hoodlum1980" },
        Version { (latestFilterVersion << 16) | latestFilterSubVersion },
        #ifdef __PIWin__
            CodeWin32X86 { "PluginMain" },
        #else
            CodeMachOPowerPC { 0, 0, "PluginMain" },
        #endif

        SupportedModes
        {
            noBitmap, doesSupportGrayScale,
            noIndexedColor, doesSupportRGBColor,
            doesSupportCMYKColor, doesSupportHSLColor,
            doesSupportHSBColor, doesSupportMultichannel,
            doesSupportDuotone, doesSupportLABColor
        },
            
        EnableInfo
        {
            "in (PSHOP_ImageMode, GrayScaleMode, RGBMode,"
            "CMYKMode, HSLMode, HSBMode, MultichannelMode,"
            "DuotoneMode, LabMode,"
            "Gray16Mode, RGB48Mode, CMYK64Mode, Lab48Mode)"
        },

        PlugInMaxSize { 2000000, 2000000 },

        FilterCaseInfo {
            {    /* array: 7 elements */
                /* Flat data, no selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                /* Flat data with selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                /* Floating selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                /* Editable transparency, no selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                /* Editable transparency, with selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                /* Preserved transparency, no selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                /* Preserved transparency, with selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination
            }
        }
    }
};


// ADOBE SYSTEMS INCORPORATED
// Copyright  1993 - 2002 Adobe Systems Incorporated
// All Rights Reserved
//
// NOTICE:  Adobe permits you to use, modify, and distribute this 
// file in accordance with the terms of the Adobe license agreement
// accompanying it.  If you have received this file from a source
// other than Adobe, then your use, modification, or distribution
// of it requires the prior written permission of Adobe.
//-------------------------------------------------------------------------------
#define plugInName            "FillRed Filter"
#define    plugInCopyrightYear "2009"
#define plugInDescription \
    
"FillRed Filter.\n\t - http:\\www.cnblogs.com\hoodlum1980"

#include 
"E:\Codes\Adobe Photoshop CS2 SDK\samplecode\common\includes\PIDefines.h"

#ifdef __PIMac__
    #include 
"Types.r"
    #include 
"SysTypes.r"
    #include 
"PIGeneral.r"
    #include 
"PIUtilities.r"
    #include 
"DialogUtilities.r"
#elif defined(__PIWin__)
    
#define Rez
    #include 
"PIGeneral.h"
    #include 
"E:\Codes\Adobe Photoshop CS2 SDK\samplecode\common\resources\PIUtilities.r"
    #include 
"E:\Codes\Adobe Photoshop CS2 SDK\samplecode\common\resources\WinDialogUtils.r"
#endif

resource 
'PiPL' ( 16000"FillRed", purgeable )
{
    {
        Kind { Filter },
        Name { plugInName },
        Category { 
"Demo By hoodlum1980" },
        Version { (latestFilterVersion 
 16| latestFilterSubVersion },
        #ifdef __PIWin__
            CodeWin32X86 { 
"PluginMain" },
        
#else
            CodeMachOPowerPC { 
00"PluginMain" },
        
#endif

        SupportedModes
        {
            noBitmap, doesSupportGrayScale,
            noIndexedColor, doesSupportRGBColor,
            doesSupportCMYKColor, doesSupportHSLColor,
            doesSupportHSBColor, doesSupportMultichannel,
            doesSupportDuotone, doesSupportLABColor
        },
            
        EnableInfo
        {
            
"in (PSHOP_ImageMode, GrayScaleMode, RGBMode,"
            
"CMYKMode, HSLMode, HSBMode, MultichannelMode,"
            
"DuotoneMode, LabMode,"
            
"Gray16Mode, RGB48Mode, CMYK64Mode, Lab48Mode)"
        },

        PlugInMaxSize { 
20000002000000 },

        FilterCaseInfo {
            {    
/* array: 7 elements */
                
/* Flat data, no selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                
/* Flat data with selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                
/* Floating selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                
/* Editable transparency, no selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                
/* Editable transparency, with selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                
/* Preserved transparency, no selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                
/* Preserved transparency, with selection */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination
            }
        }
    }
};



 

                  在FillRed.r文件中我们可以看到我们定义了滤镜的名称,所在的滤镜分组名称(Category),可以启用的图像模式等信息。然后右键点击该文件,在该文件的自定义生成规则的命令行中,点击编辑,输入以下内容:

                  How to write a Photoshop filter (1)

                  在“命令行”一栏点击编辑按钮,在弹出的窗口中输入以下两行:

cl /I E:\Codes\Adobe~1\samplecode\Common\Includes /IE:\Codes\Adobe~1\PhotoshopAPI\Photoshop /IE:\Codes\Adobe~1\PhotoshopAPI\PICA_SP /IE:\Codes\Adobe~1\samplecode\Common\Resources /EP /DWIN32=1 /Tc"$(InputPath)" > "$(ProjectDir)\$(InputName).rr"


Cnvtpipl.exe "$(ProjectDir)\$(InputName).rr" "$(ProjectDir)\$(InputName).pipl"

 

            其中,第一行表示使用 CL.EXE 把该文件编译为 *.rr文件,上面的“/I”选项表示需要的包含目录。

            第二行表示使用PS SDK中的 Cnvtpipl.exe 工具把 rr文件编译为 pipl文件,请注意为了简单,我把该工具复制到了项目的源文件所在文件夹下面。它位于SDK的路径是:“\samplecode\resources\cnvtpipl.exe”。

            (b)下面我们为项目添加一个 rc文件,同样右键点击“资源文件”,添加一个FillRed.rc文件。

            这是一个windows的资源文件,我们暂时还不需要任何资源,所以我们直接用文本方式打开IDE自动生成的RC文件,在结尾处添加下面的一行:

//

#endif    // APSTUDIO_INVOKED

#endif    // 英语(美国)资源
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// 从 TEXTINCLUDE 3 资源生成。
//
#include "FillRed.pipl"

/////////////////////////////////////////////////////////////////////////////
#endif    // 不是 APSTUDIO_INVOKED


//

#endif    // APSTUDIO_INVOKED

#endif    // 英语(美国)资源
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// 从 TEXTINCLUDE 3 资源生成。
//
#include "FillRed.pipl"

/////////////////////////////////////////////////////////////////////////////
#endif    // 不是 APSTUDIO_INVOKED

 

            (5)我们编译项目,即可在项目的输出目录中看到 生成 FillRed.8bf 文件,下面我们把这个文件复制到 Photoshop的滤镜文件夹下面,例如我的Photoshop CS的滤镜所在目录是:“D:\Program Files\Adobe\Photoshop CS\增效工具\滤镜”

                  How to write a Photoshop filter (1)

 

            最后我们启动Photoshop,Photoshop会扫描插件目录,并把我们的滤镜加载到相应的菜单上,我们选择一个矩形选区,然后点击我们制作的滤镜相应菜单,即可看到效果,如下图所示。注意,下面的例子的效果是我仅仅把蓝通道填充了255。

                  How to write a Photoshop filter (1)

In the help menu of Photoshop-In the sub-menu of the Efficiency Incretionary Tools-, you can see the "FillRED FILTER ..." we wrote. When clicking it MessageBox.

                                                                                                                                                                                                                                                                                              For example, the directory of Photoshop SDK needs to be adjusted according to the specific environment. The resource conversion tools provided by PS SDK are also included in the project folder. (Note: The attachment does not contain the complete PS SDK) http://files.cnblogs.com/hoodlum1980/FillRed.rar

                                                                                                                                             

This section describes the establishment of a basic filter framework from project creation to embedding pipl resources. But its function is very basic and simple. In the future, we may need to continue to enrich this example, including introducing dialog resources for it, letting PS cache and read our parameters for our filter, including in Dialog surface drawing filter preview graphics and so on.

For more related articles on how to write a Photoshop filter (1), please pay attention to the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
My Purpose: Assisting with Photoshop-Related TasksMy Purpose: Assisting with Photoshop-Related TasksMay 08, 2025 am 12:18 AM

In Photoshop, the role of layer masks is to allow hidden or displayed portions of layers in a non-destructive manner. 1. The working principle of layer mask is to control the visibility of the layer through black, white and grayscale. 2. The basic usage includes image synthesis, such as synthesising the character image into a new background. 3. Advanced usage can be achieved by using gradient masks to achieve smooth image transition.

Photoshop and Free Alternatives: A Comparative LookPhotoshop and Free Alternatives: A Comparative LookMay 06, 2025 am 12:12 AM

Photoshop's powerful features include smart objects and neural filters, while free alternatives such as GIMP, Krita and Photopea do well in specific fields such as GIMP's layer functionality, Krita's digital paintings and online editing of Photopea.

Photoshop Color Grading: Elevate Your Images with Pro TechniquesPhotoshop Color Grading: Elevate Your Images with Pro TechniquesMay 05, 2025 am 12:07 AM

Color adjustment in Photoshop can be achieved through adjustment layers to make the image more professional. 1. Use color level, curve, hue/saturation and other tools to adjust the hue, saturation and brightness. 2. Apply LUT to create unique color effects. 3. Use adjustment layers to avoid image distortion and use the History panel to track adjustment steps.

Photoshop in the Real World: Examples of Its Diverse UsesPhotoshop in the Real World: Examples of Its Diverse UsesMay 04, 2025 am 12:15 AM

Photoshop's applications in the real world include artistic creation, scientific research and commercial marketing. 1) In artistic creation, it is used for digital painting and illustration. 2) In scientific research, it is used for image processing and data visualization. 3) In commercial marketing, it is used for advertising design and brand image shaping. The versatility of this software makes it widely used in various fields.

Beyond Editing: Photoshop's Creative CapabilitiesBeyond Editing: Photoshop's Creative CapabilitiesMay 03, 2025 am 12:12 AM

Adobe Photoshop goes beyond simple editing and becomes a creative tool for artists and designers. 1) It provides a wealth of tools such as brushes, stamp tools, blend modes and layer styles, supporting adjustments from basic images to complex digital paintings and 3D designs. 2) These tools implement functions through pixel-level operations, allowing users to create unique visual effects.

Photoshop: Exploring Pricing Models and OptionsPhotoshop: Exploring Pricing Models and OptionsMay 02, 2025 am 12:12 AM

Photoshop offers two pricing models: single purchase and subscription service. 1. Single purchase: Pay $699 in one lump sum, permanent use, but no updates and cloud services. 2. Subscription service: $20.99 per month or $239.88 per year, and the latest version and cloud services are available. 3. Enterprise plan: $33.99 per user per month, including team management and additional cloud storage. 4. Educational Offer: Students and teachers are $19.99 per month, including multiple CreativeCloud applications.

Photoshop: Mastering Layers and CompositionPhotoshop: Mastering Layers and CompositionMay 01, 2025 am 12:05 AM

The method to create a new layer in Photoshop is: 1. Click the "New Layer" button at the bottom of the layer panel; 2. Use the shortcut keys Ctrl Shift N (Windows) or Command Shift N (Mac). The layers are like transparent sheets on canvas, allowing design elements to be managed separately, non-destructive editing and experimenting, and improving design levels.

Photoshop Applications: From Photo Editing to Digital ArtPhotoshop Applications: From Photo Editing to Digital ArtApr 30, 2025 am 12:10 AM

Photoshop is widely used in the fields of image processing and digital art, and is suitable for photo editing and digital art creation. 1. Photo editing: Adjust brightness and contrast Use the "Brightness/Contrast" tool. 2. Digital art: Use brush tools to create paintings. 3. Basic usage: Use the "Red Eye Tool" to remove red eyes. 4. Advanced usage: Use layers and masks for image synthesis. 5. Debug: Recover the lost layers by checking the layer panel. 6. Performance optimization: Adjust memory usage to improve running speed.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft