Photoshop插件开发-filter

初学,,感觉PS插件的文档很烂,,教程也很少,,也就这么简单学一下了!!!
adobe_photoshop_sdk 下载http://www.adobe.com/devnet/photoshop.html


本文实现的是最简单的filter插件--将图像取反---也就是根本没有任何参数的一个filter!!!

其实要有参数可以自己加对话框(不熟悉windows编程,没实现),,完全没必要采用adobe的框架。
感觉alien skin  exposure ; google nik collection等都是自己实现的:先读一个要修改的图像,在自己插件里选好效果后执行,返回结果到PS。 因而学习adobe家的架构不是太必要

注:只保证对RGB图像有效,,,对灰度图本来可以,,后来不知道怎么回事,直接弹对话框说接口不支持。。。。

修改自 http://www.cnblogs.com/hoodlum1980/archive/2009/05/11/1453870.html  非常好的中文教程,,但是我改了他的没成功,,年份久了,接口变了,,,
以及 adobe_photoshop_sdk_cc_2014_win 中的  dissolve 例程


最后工程用的dissolve例程的,本文件是例程和该网页综合起来的,还有我自己写的

注意例程使用的是相对路径,,,所以本工程必须放到和例程dissolve的同一级目录才行!!!否则请按以上教程所示自行修改头文件及 编译pipl文件的程序路径


重要参考文献:
How to Write a Photoshop Plug-In, Part 1(强烈推荐!!)   http://www.mactech.com/articles/mactech/Vol.15/15.04/PhotoshopPlug-InsPart1/index.html
Writing a Photoshop Plug-In, Part 2  http://www.mactech.com/articles/mactech/Vol.15/15.05/PhotoshopPlug-InsPart2/index.html
adobe_photoshop_sdk_cc_2014_win document (很烂,但毕竟比较全)
Photoshop 的插件及其实现: http://www.moon-soft.com/book/plugin.htm


最后贴上主要代码:工程文件见附件

// 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.
//-------------------------------------------------------------------------------
#include "Matrix.hpp"
#include "PiFilter.h"
#include "FilterInfo.h"
#include <stdio.h>

/************************************************************************/
/*

Photoshop 的无参数 filter  例程。
其实要有参数可以自己加对话框(不熟悉windows编程,没实现),,完全没必要采用adobe的框架。
感觉alien skin  exposure ; google nik collection等都是自己实现的:先读一个要修改的图像,在自己插件里选好效果后执行,返回结果到PS。 因而学习adobe家的架构不是太必要

adobe_photoshop_sdk下载:[url]http://www.adobe.com/devnet/photoshop.html[/url]

修改自 http://www.cnblogs.com/hoodlum1980/archive/2009/05/11/1453870.html   非常好的中文教程,,但是我改了他的没成功,,年份久了,接口变了,,,
以及 adobe_photoshop_sdk_cc_2014_win 中的  dissolve 例程


最后工程用的dissolve例程的,本文件是例程和该网页综合起来的,还有我自己写的

注意例程使用的是相对路径,,,所以本工程必须放到和例程dissolve的同一级目录才行!!!否则请按以上教程所示自行修改头文件及 编译pipl文件的程序路径


重要参考文献:
How to Write a Photoshop Plug-In, Part 1(强烈推荐!!)   http://www.mactech.com/articles/mactech/Vol.15/15.04/PhotoshopPlug-InsPart1/index.html
Writing a Photoshop Plug-In, Part 2  http://www.mactech.com/articles/mactech/Vol.15/15.05/PhotoshopPlug-InsPart2/index.html
adobe_photoshop_sdk_cc_2014_win document (很烂,但毕竟比较全)
Photoshop 的插件及其实现:http://www.moon-soft.com/book/plugin.htm

*/
/************************************************************************/

/************************************************************************/
/* 
自己从新建立工程步骤(注意因为下面很多路径使用的是相对路径,,,所以本solution必须放到和例程dissolve的同一级目录(filter文件夹下)才行):
1、新建dll工程,,   拷贝本工程的一应文件
2、更改字符集为multibyte   ;  更改输出文件类型为.8bf    (debug、release要分别改,,下同)
3、拷贝dissolve工程的  c/c++    ->  general ->  additional include dictionaries 属性
4、拷贝dissolve工程的  linker -> input 属性
5、添加dissolve工程的common sources对应的cpp文件到本工程
6、右键LC_PSFilter.r,,设置编译属性,,这个直接copy就好

7、更改FilterInfo.h文件中的vendorName,,plugInName,,plugInUniqueID,,plugInDescription等属性
8、按下一个注释块更改本文件中的相关函数实现filter功能


*/
/************************************************************************/




/************************************************************************/
/*

说明:
要实现自己的filter,,只需要修改processTile() 函数即可 (当前只是对RGB图像的实现)!!!
如果处理的通道不是RGB或灰度的,则也要修改setChannels()函数。


*/
/************************************************************************/






/*******************************************/  //参数区
#ifndef NDEBUG
#define  USE_LOG   //输出日志到桌面上
#endif

#define USE_TILE__   //如果定义此项,,则将图片分成128*128的图像处理,如果不定义,则一次性进行处理


/*******************************************/





#ifdef USE_LOG    //日志文件会出现在桌面上
#include "Logger.h"
//template<typename Val>
// void log (Logger& l, const char* des, Val v) {
//     l.Write (des, false);
//     l.Write (":\t", false);
//     l.Write (v, true);
// }
Logger logIt ("LCInvert");
#define printDesVal(des,v)  logIt.Write (des, false);logIt.Write (":\t", false); logIt.Write (v, true);
#define printDesValLn(v) printDesVal(#v,v);
#define print(val) logIt.Write(val,false);
#define println(val) logIt.Write(val,true);

#else

#define printDesVal(des,v)  ;
#define printDesValLn(v) ;
#define print(val) ;
#define println(val) ;

#endif


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


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



//=======================================
//        全局变量
//=======================================
//dll instance
HINSTANCE        dllInstance;
FilterRecord*    gFilterRecord;
intptr_t*            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;
}

#ifdef _MANAGED
#pragma managed(pop)
#endif

//===================================================================================================
//------------------------------------ 滤镜被ps调用的函数 -------------------------------------------
//===================================================================================================
DLLExport MACPASCAL void PluginMain (const int16 selector,
                                     FilterRecordPtr filterRecord,
                                     intptr_t * data,
                                     int16 * result) {
    try {
        //Timer timeIt; //需要#include "Timer.h"

        print ("Selector: ");
        print (selector);
        print ("\t\t\t");


        // update our global parameters
        gData = data;
        gResult = result;

        if (selector == filterSelectorAbout) {
            MessageBox (GetActiveWindow(), plugInDescription, plugInName, MB_OK);
            //sSPBasic = gFilterRecord->sSPBasic;
        } else {
            gFilterRecord = filterRecord;
            sSPBasic = gFilterRecord->sSPBasic;

            //虽然这是dissolve例程中的,,,但有下面两句,,直接不执行 continue了。。。。
            //另外自己试的 int err = gFilterRecord->advanceState(); 方法也无法正常使用。。。(不报错,但是数据指针均为空)不知道注释了之后行不行,,没试
// 			if (gFilterRecord->bigDocumentData != NULL)
// 				gFilterRecord->bigDocumentData->PluginUsing32BitCoordinates = true;
        }

        // do the command according to the selector
        switch (selector) {
        case filterSelectorAbout:
            println ("filterSelectorAbout");
            //DoAbout();
            break;
        case filterSelectorParameters:
            println ("filterSelectorParameters");

            DoParameters();
            break;
        case filterSelectorPrepare:
            println ("filterSelectorPrepare");

            DoPrepare();
            break;
        case filterSelectorStart:
            println ("filterSelectorStart");

            DoStart();
            break;
        case filterSelectorContinue:
            println ("filterSelectorContinue");

            DoContinue();
            break;
        case filterSelectorFinish:
            println ("filterSelectorFinish");

            DoFinish();
            break;
        default:
            break;
        }



        print ("Image size:");
        print (filterRecord->imageSize.h);
        print ("*");
        println (filterRecord->imageSize.v);


        printDesValLn (filterRecord->maxSpace);
        printDesValLn (filterRecord->planes);
        printDesValLn (filterRecord->depth);

        //printDesValLn( timeIt.GetElapsed());
        println ("");

    } // end try

    catch (...) {
        if (NULL != result)
            *result = -1;
    }
}

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

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

void setChannels() { //设置我们需要处理的通道
    int nchanel = 3;
    switch (gFilterRecord->imageMode) {   //我们这里只处理灰度图,或者RGB图像
    case plugInModeRGBColor:
        nchanel = 3;
    case  plugInModeGrayScale:
        nchanel = 1;
    default:
        nchanel = 3;
        break;
    }
    gFilterRecord->inLoPlane = 0;
    gFilterRecord->inHiPlane = nchanel - 1;
    gFilterRecord->outLoPlane = 0;
    gFilterRecord->outHiPlane = nchanel - 1;
}

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

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

    if (gFilterRecord == NULL)
        return;


#ifdef USE_TILE__
    //我们初始化第一个Tile,然后开始进行调用
    m_Tile.left = gFilterRecord->filterRect.left;
    m_Tile.top = gFilterRecord->filterRect.top;
    m_Tile.right = min (m_Tile.left + TILESIZE, gFilterRecord->filterRect.right); //只要修改这里就变成分tile处理的了
    m_Tile.bottom = min (m_Tile.top + TILESIZE, gFilterRecord->filterRect.bottom);
#else
    //不分tile了,一次完成!!!!
    m_Tile.left = gFilterRecord->filterRect.left;
    m_Tile.top = gFilterRecord->filterRect.top;
    m_Tile.right =  gFilterRecord->filterRect.right;
    m_Tile.bottom = gFilterRecord->filterRect.bottom;
#endif

    //设置inRect, outRect
    //ZeroPsRect (&gFilterRecord->inRect);
    CopyPsRect (&m_Tile, &gFilterRecord->inRect);
    CopyPsRect (&m_Tile, &gFilterRecord->outRect);
    setChannels();//设置需要请求的通道

}



template<typename T>
void processTile() {
    //定位像素
    int planes = gFilterRecord->outHiPlane - gFilterRecord->outLoPlane + 1; //通道数量
    CopyPsRect (&gFilterRecord->outRect, &m_Tile);
    const int R = m_Tile.bottom - m_Tile.top;
    const int C = m_Tile.right - m_Tile.left;

    switch (planes) {
    case 1: {//单通道图像
        T* pOut = (T*) gFilterRecord->outData;
        T* pIn = (T*) gFilterRecord->inData;
        LC::Matrix<T> in (pIn, R, C , gFilterRecord->inRowBytes);
        LC::Matrix<T> out (pOut, R, C, gFilterRecord->outRowBytes);

        printDesValLn ( (int) pIn[0]);



        for (int r = 0; r < R; r++) {
            //Sleep (100);
            // gFilterRecord->progressProc (r, out.rows() );   //显示进度条,此时按ESC键可以撤销该filter!!!
            // if (gFilterRecord->abortProc() ) {*gResult=-1;  return};
            for (int c = 0; c < C; c++) {
                T& orgb = out (r, c);
                T& irgb = in (r, c);
                orgb = LC::maxValInPS<T>() - irgb;
            }
        }

    }
    break;
    case 3: { //RGB图像
        LC::RGB<T> *pOut = (LC::RGB<T>*) gFilterRecord->outData;
        LC::RGB<T>* pIn = (LC::RGB<T>*) gFilterRecord->inData;
        LC::Matrix<LC::RGB<T>> in (pIn, R, C, gFilterRecord->inRowBytes);
        LC::Matrix<LC::RGB<T>> out (pOut, R, C, gFilterRecord->outRowBytes);

        printDesValLn ( (int) pIn[0].r);

        //我们把输出矩形拷贝到 m_Tile

        for (int r = 0; r < R; r++) {
            //Sleep (100);
            // gFilterRecord->progressProc (r, out.rows() );   //显示进度条,此时按ESC键可以撤销该filter!!!
            // if (gFilterRecord->abortProc() ) {*gResult=-1;  return};
            for (int c = 0; c < C; c++) {

                LC::RGB<T>& orgb = out (r, c);
                LC::RGB<T>& irgb = in (r, c);
                orgb.r = LC::maxValInPS<T>() - irgb.r;
                orgb.g = LC::maxValInPS<T>() - irgb.g;
                orgb.b = LC::maxValInPS<T>() - irgb.b;
            }
        }
    }
    break;
    default:
        *gResult = -1;
        break;
    }



}



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

    gResult = 0;
    println (gFilterRecord->depth);
    switch (gFilterRecord->depth) {
    case 8:
        processTile<uint8>();
        break;
    case 16:
        processTile<uint16>();
        break;
    case 32:
        processTile<uint32>();
        break;


    default:
        *gResult = -1;
        break;
    }


    //判断是否已经处理完毕
    if (gResult != 0 || ( 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.left + 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.top + TILESIZE, gFilterRecord->filterRect.bottom);
    }

    // ZeroPsRect (&gFilterRecord->inRect);
    CopyPsRect (&m_Tile, &gFilterRecord->inRect);
    CopyPsRect (&m_Tile, &gFilterRecord->outRect);

}

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

猜你喜欢

转载自cherishlc.iteye.com/blog/2248390