Heim >Web-Frontend >PS-Tutorial >So schreiben Sie einen Photoshop-Filter (1)

So schreiben Sie einen Photoshop-Filter (1)

高洛峰
高洛峰Original
2017-02-22 09:49:302626Durchsuche

Vor langer Zeit habe ich einen Artikel geschrieben, der kurz die Grundkonzepte der Filterentwicklung in Photoshop beschrieb, die Zusammenarbeit zwischen Filtern und PS beschrieb und auch eine Demo des Regentropfeneffektfilters bereitstellte. Aber der Quellcode fehlt. Und wir werden fragen: Wie programmieren wir einen Photoshop-Filter von Grund auf? Wie bauen wir das einfachste Grundgerüst des PS-Filter-Plug-Ins auf und fügen dann auf dieser Basis weiterhin die gewünschten Funktionen hinzu? Hier beantworte ich als Beispiel eine Frage, die mir ein Internetnutzer gestellt hat, und beginne dabei mit dem grundlegendsten Bauprojekt. Dieses Beispiel (auch das Problem dieses Internetnutzers) besteht darin, dass er den einfachsten Filter erstellen möchte, nämlich das Bild einfach mit „Rot“ zu füllen. Für PS-Benutzer ist dies natürlich eine sehr einfache und einfache Sache. Es ist nur eine Tastenkombination erforderlich (Filter werden normalerweise verwendet, um komplexere Aufgaben zu erledigen). Verfahren. Am Ende des Artikels finden Sie einen Link zum Herunterladen des Quellcodes für das Beispiel.

                                                                                                                                                                                                                       (1) Das von uns verwendete Entwicklungstool ist die Version Visual Studio .NET 2005, gepaart mit Photoshop SDK CS (im Wesentlichen ein Distributionspaket, das aus etwas C++-Code, Ressourcen und anderen Dateien besteht). Die verwendeten Entwicklungssprachen sind C und C++.

Ist es in Ordnung, C# oder andere Sprachen zu verwenden? Derzeit ist dies nicht realisierbar. Um Photoshop-Filter entwickeln zu können, müssen Entwickler daher über gute Kenntnisse in C und C++ verfügen, was am wichtigsten ist. Natürlich wäre es besser, wenn der Entwickler sich mit der Bildverarbeitung auskennt und über Grundkenntnisse der digitalen Signalverarbeitung verfügt.

       (2) Nach der Vorbereitung der Tools öffnen wir VS2005 und erstellen ein neues Projekt. Als Projektvorlage wählen wir Win32 von Visual C++. Als Projektnamen geben wir den Namen des Filters ein, den wir erstellen möchten, z. B. den Filter „FillRed“, was bedeutet, dass dieser Filter zum Ausfüllen von Rot verwendet wird, wie unten gezeigt:

Nachdem Sie auf „OK“ geklickt haben, klicken Sie im Popup-Einstellungsdialogfeld auf „Anwendungseinstellungen“, wählen Sie „DLL“ als Anwendungstyp aus und klicken Sie dann auf „OK“. So schreiben Sie einen Photoshop-Filter (1)

                                                                                                                Einige Einstellungen lauten wie folgt:

(a) Im Allgemeinen ändere ich den vom Projekt verwendeten Zeichensatz gerne auf „Mehrbyte-Zeichensatz verwenden“, was dies ermöglicht Wir verwenden char* und verwenden direkt double Der Zeichenfolgentyp des Anführungszeichens. Natürlich kann auch Unicode verwendet werden, aber die von beiden verwendeten Zeichenfolgenfunktionen sind unterschiedlich. Sie können es so einrichten, wie Sie möchten. So schreiben Sie einen Photoshop-Filter (1)

(b) Das Projekt wurde standardmäßig als DLL ausgegeben. Da die Erweiterung der Photoshop-Filterdatei 8bf ist, legen wir die Erweiterung der Ausgabedatei in Linker->Allgemein fest. Ändern Sie es wie unten gezeigt.

                                                                                                                                                                                                                                                                       Wie unten gezeigt:

             So schreiben Sie einen Photoshop-Filter (1)

 

                           wird wie folgt ersetzt:

// 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: Definiert den Einstiegspunkt der DLL-Anwendung.
//

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

#ifdef _MANAGED
#pragma verwaltet (Push, Off)
#endif


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

//====================================== ==
//Globale Variablen
//============ === ======================
//DLL-Instanz
HINSTANCE dllInstance;
FilterRecord
* gFilterRecord;
int32
* gData;
int16
* gResult;
SPBasicSuite
* sSPBasic = NULL ;
#define TILESIZE 128 //Kachelgröße: 128 * 128
Rect       m_Tile;     
//Aktuelle Bildkachel (128*128) ===================== ===============


//
Funktionsliste
//
======================== =============
/ /
Hilfsfunktion, Rechteck kopieren
void CopyPsRect(Rect*
src, Rect* dest);//Hilfsfunktion, setze ein Rechteck auf ein leeres Rechteck
void ZeroPsRect(Rect *
dest);void DoParameters();
void
DoPrepare();
void
DoStart();
void
DoContinue();
voidDoFinish();


//Hilfsfunktion, Rechteck kopieren
void CopyPsRect(Rect* src, Rect* dest )
{
dest
->left = src->left;
dest
->top = src->top;
dest
->right = src-> rechts;
dest
->unten = src-> ;unten;
}

//Hilfsfunktion, ein Rechteck auf ein leeres Rechteck setzen
void ZeroPsRect(Rect* dest)
{
dest
-> links = 0;
Ziel
-> oben = 0;
Ziel
-> rechts = 0;
Ziel
->unten = 0;
}

//DLLMain
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
dllInstance
= static_castHINSTANCE>(hModule);
 
returnTRUE;
}

#ifdef _MANAGED
#pragmamanaged(pop)
#endif

//============= = ============================================== = ==================================
// ------------------------- Die von ps aufgerufene Funktion für der Filter ---- ---------------------------------------
//=================================== == ============================================== == ============
DLLExport void PluginMain( const int16 selector, void * filterRecord, int32 *data, int16 *result)
{
gData
= data;
gResult
= Ergebnis;

if (Selektor == filterSelectorAbout )
{
                                                                          > - von Hoodlum1980
", "
Über FillRed", MB_OK);                                                                    > (FilterRecordPtr)filterRecord; sSPBasic = gFilterRecord->sSPBasic; }
 
Schalter. (Auswahl)                                                   🎜>
//
DoAbout();
                                                             >Fall filterSelectorParameters: DoParameters(); break
;
case
filterSelectorPrepare: DoPrepare();break

;
case filterSelectorStar t: DoStart() ;
 
break; 
case
filterSelectorContinue: DoContinue();Pause;
🎜>Pause
;
Standard
: filterBadParameters; Für dieses Filterbeispiel müssen wir noch nichts tun
void
DoParameters()
{ }//Teilen Sie PS (Host) zu diesem Zeitpunkt die für den Filter erforderliche Speichergröße mit
void

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

bufferSpace
= 0
;
gFilterRecord->
maxSpace
= 0; }
}
//inRect : Der Filter fordert den von PS gesendeten rechteckigen Bereich an. //outRect: Der rechteckige Bereich, der von der Filterbenachrichtigung PS empfangen wird.
//
filterRect: Der rechteckige Bereich, den der PS-Benachrichtigungsfilter verarbeiten muss. //Da wir mit einer festen roten Farbe füllen, müssen wir PS eigentlich nicht zum Senden von Daten auffordern //
Hier können Sie also inRect auf NULL setzen, dann übergibt PS keine Daten an den Filter.


void DoStart()
{
 if
(gFilterRecord
==NULL)

return;
// Wir initialisieren die erste Kachel und beginnen dann mit dem Aufruf von
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); //Wir brauchen kein PS um uns zu sagen, welche Farbe das Originalbild hat, denn wir füllen einfach
CopyPsRect(&m_Tile, & gFilterRecord->outRect);
Die Daten sind Interleave-Verteilung)
gFilterRecord->
inLoPlane = 0 ; gFilterRecord->inHiPlane
= 0; gFilterRecord->outLoPlane
= 0; gFilterRecord->outHiPlane
= (gFilterRecord- >Flugzeuge -1);}//

Der aktuelle Patch wird hier verarbeitet dass, wenn der Benutzer Esc drückt, der nächste Aufruf Finish
voidDoContinue( )
{
if(gFilterRecord

==
NULL)return;
 
//Standortpixel

 int
Ebenen
= gFilterRecord->outHiPlane - gFilterRecord-> outLoPlane + 1; //Anzahl der Kanäle                                                                      (uint8*)gFilterRecord->
outData;
//Scan-Zeilenbreite (Bytes)
 int Schritt = gFilterRecord->outRowBytes;

 
// Wir kopieren das Ausgaberechteck nach m_Tile
CopyPsRect(&gFilterRecord-> outRect, &m_Tile);
🎜> j
= 0 ; j (m_Tile.bottom 🎜>- m_Tile.top); j++) { for (int
i
= 0; i
(m_Tile.right - m_Tile.left); i++) { // Um es einfach und klar zu sagen: Wir verwenden das Bild standardmäßig im RGB-Format (sollte eigentlich nicht gemacht werden) //
pData[ i*planes + j*stride + 0 ] = 0; >
//
Rot pData[ i*planes + j*stride + 1 ] = 0; i
*planes + j
*
Schrittweite + 2 ]
= 255; //Blau } }  //Beurteilen Sie, ob die Verarbeitung abgeschlossen wurde    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);
 
//Alle Kanäle anfordern (die Daten werden interleaveverteilt)
 gFilterRecord-> ;inLoPlane = 0;
gFilterRecord
-> >inHiPlane = 0;
gFilterRecord
->outLoPlane = 0;
gFilterRecord
->outHiPlane = (gFilterRecord->Flugzeuge -1 ; 🎜>void

DoFinish()
{
}
Der obige Code ist auch ein Filter Im Grundgerüst sehen wir, dass eine der Exportfunktionen, die die DLL bereitstellt, die PluginMain-Funktion ist. Wir segmentieren das Bild in 128*128-Pixel-Slices, wodurch jeweils eine kleinere Datenmenge zwischen PS und dem Filter übertragen werden kann Insbesondere bei sehr großen Bildern hilft die Slicing-Verarbeitung, mit knappen Speichersituationen umzugehen, was auch von Photoshop empfohlen wird. 64*64 oder 128*128 sind typischere Größen. Der Aufrufprozess besteht darin, die erste Kachel (Tile) im Startaufruf zu initialisieren. Anschließend setzen wir die erste Kachel auf outRect, was bedeutet, dass wir PS auffordern, einen Puffer für den Empfang des Rechtecks ​​bereitzustellen Da es sich bei inRect nur um das Ausfüllen handelt, ist uns die Originalfarbe des Bildes egal. Daher kann inRect auf „leeres Rechteck“ gesetzt werden. Bildkanäle Aus Gründen der Intuitivität und Einfachheit des Codes betrachten wir hier nur RGB-Bilder, also Bilder mit 3 Kanälen. Nach dem Festlegen des ersten outRect beginnt PS mit dem Aufruf von continue nacheinander und die Patches werden von links nach rechts und von oben nach unten collagiert, bis alle Patches verarbeitet sind. Beachten Sie, dass inData und outData die Anwendungsdaten und der „Writeback-Puffer“ sind, die PS dem Filter zur Verfügung stellt. Der eine dient zum Lesen und der andere zum Schreiben. Ihre Größe wird durch die Daten gesteuert, die eingegeben werden, wenn der Filter PS über die Anforderung benachrichtigt. Operation Time darf niemals seine Grenzen überschreiten.
                                                                                                                                                                                                                           Der Zeiger außerhalb des Bereichs führt zum Absturz des Photoshop-Programms!

Einzelheiten zum Hauptcode dieses Filters finden Sie in den Codekommentaren und der Erklärung in meinem vorherigen Artikel. Und die offizielle Dokumentation des PS SDK. Wir werden hier nicht näher auf das Prinzip des Codes eingehen, da er sehr einfach ist. Alle oben genannten Codes müssen auf die Header-Dateien im ps sdk verweisen.

                                                                                    Der nächste Schritt besteht jedoch darin, in PIPL-Ressourcen zu investieren.

PIPL-Ressourcen müssen in den Filter eingefügt werden, damit sie von Photoshop korrekt erkannt und geladen werden. Laut der von PS bereitgestellten Dokumentation lautet die Aussprache von PIPL „pipple“, was „Plug-In Property List“ bedeutet. Es handelt sich um eine flexible, erweiterbare Datenstruktur, die zur Darstellung von Plug-In-Modul-Metadaten (Metadaten) verwendet wird. pipl enthält alle Informationen, die Photoshop zum Erkennen und Laden von Plug-in-Modulen benötigt, einschließlich einiger Tags sowie verschiedener statischer Eigenschaften, die jedes Plug-in usw. steuern. Ihr Filter kann eine oder mehrere „pipl“-Strukturen enthalten.

Der Vorgang zum Einfügen von Pipl-Ressourcen für Filter ist wie folgt. Zuerst müssen wir dem Projekt eine *.r-Datei (Macintosh Rez-Datei) hinzufügen und diese Datei dann mit cl.exe kompilieren *.rr-Datei. Verwenden Sie abschließend CnvtPipl.Exe, ein von Ps SDK bereitgestelltes Ressourcenkonvertierungstool, um die *.rr-Datei in eine *.pipl-Datei zu konvertieren, fügen Sie dann eine *.rc-Ressourcendatei für den Filter hinzu und fügen Sie diese ein pipl-Datei am Ende der rc-Datei.

ps sdk hat uns eine gemeinsame r-Datei mit allgemeinen Attributdefinitionen zur Verfügung gestellt, nämlich die Datei PIGeneral.r.

(a) Als nächstes fügen wir dem Projekt eine r-Datei hinzu, klicken mit der rechten Maustaste auf den Ordner „Ressourcendateien“ im Ressourcenmanager, klicken zum Hinzufügen einer neuen Datei und geben „FillRed.r“ als ein Dateiname. Doppelklicken Sie auf die Datei, um sie zu öffnen und den folgenden Inhalt zu kopieren:

// 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:CodesAdobe Photoshop CS2 SDKsamplecodecommonresourcesWinDialogUtils.r"
#endif

Ressource 
'PiPL' ( 16000"FillRed", löschbar )
{
    {
        Art { Filter },
        Name { plugInName },
        Kategorie { 
"Demo By hoodlum1980" },
        Version { (latestFilter Version 
 16| latestFilterSubVersion },
        #ifdef __PIWin__
            CodeWin32X86 { 
"PluginMain" },
        
#else
            CodeMachOPowerPC { 
00"PluginMain" },
        
#endif

        SupportedModes
        {
            Nr Bitmap, unterstütztGrayScale,
            noIndexedColor, unterstütztRGBColor,
            unterstützt CMYKColor, unterstützt HSLColor,
            unterstützt HSBColor, unterstütztMultichannel,
            unterstützt Du otone, doesSupportLABColor
        },
             
        EnableInfo
        >"
in (PSHOP_ImageMode, GrayScaleMode, RGBMode,"            "
CMYKMode, HSLMode, HSBMode , MultichannelMode,"            "
DuotoneMode, LabMode,"            "
Gray16Mode, RGB48Mode, CMYK64Mode, Lab48Mode)"        },        PlugInMaxSize { 20000002000000 },

        FilterCaseInfo {
            {    
/ * Array: 7 Elemente */
                
/* Flache Daten, keine Auswahl  */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
               copySourceToDestination,
                
/* Flache Daten mit Auswahl */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData ,
                copySourceToDestination,
                         inStraightData,
                outStraightData,                doNotWriteOutsideSelection,                doesNotFilterLayerMasks,                doNotWorkWithBlankData,              ,                /*

 Bearbeitbare Transparenz, keine Auswahl 

*/


                inStraightData,
                outStraightData,                doNotWriteOutsideSelection,               NotFilterLayerMasks,                doesNotWorkWithBlankData,                copySourceToDestination,                /* Bearbeitbare Transparenz, mit Auswahl */
                inStraightData,
                outStraightData,
                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                
/* Transparenz beibehalten, keine Auswahl */
                inStraightData,
                outStraightData,
               doNotWriteOutsideSelection,
                doNotFilterLayerMasks,
                doesNotWorkWithBlankData,
                copySourceToDestination,
                
/*
*/                inStraightData,               outStraightData,                doNotWriteOutsideSelection,
                doesNotFilterLayerMasks,
               doesNotWorkWithBlankData,
               copySourceToDestination
            }
         可以看然后右键点击该文件, 在该文件的自定义生成规则的命令行中, 点击编辑, 输入以下内容:

                  


                 弹出的窗口中输入以下两行:

cl /I E:CodesAdobe ~1samplecodeCommonIncludes /IE:CodesAdobe~1PhotoshopAPIPhotoshop /IE:CodesAdobe~1PhotoshopAPIPICA_SP /IE:CodesAdobe~1samplecodeCommonResources /EP /DWIN32=1 /Tc"$(InputPath)" > „$(ProjectDir)$(InputName).rr“
Cnvtpipl.exe „$(ProjectDir)$(InputName).rr“ „$(ProjectDir)$(InputName).pipl“

 

           需要的包含目录.

            第二行表示使用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\增效工具\滤镜”

                  So schreiben Sie einen Photoshop-Filter (1)

 

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

                  So schreiben Sie einen Photoshop-Filter (1)

Im Untermenü des Photoshop-Hilfemenüs – Über Plug-ins – können Sie den von uns geschriebenen Eintrag „FillRed-Filter …“ sehen. Wenn Sie darauf klicken, leitet PS einen Info-Aufruf ein und Sie sehen ein Popup -up MessageBox.

.

                                                                                                                                                                                             . Beispielsweise muss das Verzeichnis des Photoshop SDK entsprechend der spezifischen Umgebung angepasst werden. Die vom PS SDK bereitgestellten Tools zur Ressourcenkonvertierung sind ebenfalls im Projektordner enthalten. (Hinweis: Der Anhang enthält nicht das vollständige PS SDK) http://files.cnblogs.com/hoodlum1980/FillRed.rar

Dieser Abschnitt beschreibt das Einrichtung eines grundlegenden Filter-Frameworks von der Projekterstellung bis zur Einbettung von PiPL-Ressourcen. Aber seine Funktion ist sehr einfach und einfach. In Zukunft müssen wir dieses Beispiel möglicherweise weiter bereichern, einschließlich der Einführung von Dialogressourcen dafür, der Möglichkeit, unsere Parameter für unseren Filter zwischenzuspeichern und zu lesen, einschließlich der Vorschaugrafiken für die Dialogoberfläche und bald.

Weitere verwandte Artikel zum Schreiben eines Photoshop-Filters (1) finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn