오래 전에 포토샵에서 필터 개발의 기본 개념을 간략하게 설명하고 필터와 PS의 협업 관계를 설명하고 빗방울 효과 필터의 데모를 제공하는 기사를 작성했습니다. 그런데 소스코드가 빠졌네요. 그리고 우리는 Photoshop 필터를 처음부터 어떻게 프로그래밍합니까? PS 필터 플러그인의 가장 간단한 기본 프레임워크를 어떻게 구축하고, 이를 기반으로 원하는 기능을 계속 추가하려면 어떻게 해야 할까요? 여기서는 한 네티즌이 나에게 던진 질문을 예로 들어 가장 기본적인 건설 프로젝트부터 답해보도록 하겠다. 이 예(또한 이 네티즌의 문제)는 그가 가장 간단한 필터를 만들고 싶어한다는 것입니다. 즉, 이미지를 "빨간색"으로 채우는 것입니다. PS 사용자의 경우 이는 매우 간단하고 쉬운 일입니다. 단축키 조작만 필요합니다. (필터는 일반적으로 더 복잡한 작업을 완료하는 데 사용됩니다.) 필터 작성 방법을 설명하기 위해 가장 기본적인 예부터 시작하겠습니다. 거울 과정. 예제의 소스 코드 다운로드 링크는 기사 끝에 첨부됩니다.
~ (1) 우리가 사용하는 개발 도구는 Photoshop SDK CS(기본적으로 일부 C++ 코드와 리소스 및 기타 파일로 구성된 배포 패키지)와 쌍을 이루는 Visual Studio .NET 2005 버전입니다. 사용되는 개발 언어는 C와 C++입니다.
그럼 C#이나 다른 언어를 사용해도 괜찮을까요? 현재로서는 불가능할 것 같습니다. 따라서 포토샵 필터를 개발하려면 개발자에게 가장 중요한 C 및 C++에 대한 탄탄한 기초가 있어야 합니다. 물론 개발자가 영상 처리에 익숙하고 디지털 신호 처리에 대한 기본 지식이 있으면 더 좋겠죠.
(2) 도구 준비가 끝나면 VS2005를 열고 새 프로젝트를 만듭니다. 프로젝트 템플릿으로 Visual C++의 Win32를 선택합니다. 프로젝트 이름에는 "FillRed" 필터와 같이 생성하려는 필터의 이름을 입력합니다. 이는 아래와 같이 이 필터가 빨간색을 채우는 데 사용된다는 의미입니다.
확인을 클릭한 후 팝업 설정 대화상자에서 "애플리케이션 설정"을 클릭하고 애플리케이션 유형에서 "DLL"을 선택한 후 확인을 클릭합니다.
(a) 일반적으로 프로젝트에서 사용하는 문자 집합을 "멀티바이트 문자 집합 사용"으로 변경하는 것을 좋아합니다. char*를 사용하고 double 인용문의 문자열 유형을 직접 사용합니다. 물론 유니코드도 사용할 수 있지만 둘이 사용하는 문자열 함수는 서로 다릅니다. 원하는대로 설정할 수 있습니다.
~ "파일 포함" 선택: 옵션의 VC++ 포함 디렉터리에 여러 Photoshop SDK 폴더를 추가하면 파일을 찾을 수 없다는 오류를 보고하지 않고 프로젝트를 더 쉽게 컴파일할 수 있습니다. 아래와 같이:
이 소스 파일의 코드는 다음과 같습니다. 다음과 같이 교체되었습니다:
// 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() { }
void DoFinish();
//보조 기능, 직사각형 복사
void CopyPsRect(Rect* src, Rect* dest )
{
목적지->왼쪽 = src->왼쪽;
목적지->상단 = src->top;
dest->right = src-> 오른쪽;
목적지->하단 = src-> ;bottom;
}
//보조 기능, 직사각형을 빈 직사각형으로 설정
void ZeroPsRect(Rect* dest)
{
dest-> 왼쪽 = 0;
목적지-> 상위 = 0;
대상-> 오른쪽 = 0;
목적지->하단 = 0;
}
//DLLMain
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
dllInstance = static_castHINSTANCE>(hModule);
return TRUE;
}
#ifdef _MANAGED
#pragma 관리(팝)
#endif
//============= = ================================================ = ===================================
// --------------- ps가 호출하는 함수 필터 ---- ------------------------------- -
//=================================== == =============================================== == =============
DLLExport void PluginMain( const int16 선택기, void * filterRecord, int32 *data, int16 *결과)
{
gData = data;
gResult = 결과;
if (선택기 == filterSelectorAbout )
{
>"FillRed 필터: 빨간색 채우기 -- by Hoodlum1980",
"FillRed 소개", MB_OK); 🎜 > (FilterRecordPtr)filterRecord; sSPBasic = gFilterRecord->sSPBasic;
}
스위치
(선택기)
> //DoAbout();
케이스 filterSelectorParameters: DoParameters();
break
;case filterSelectorPrepare: DoPrepare();
break; case
filterSelectorStart t: DoStart() ; break;
case filterSelectorContinue: DoContinue();중단;
🎜>중단;
기본값
: filterBadParameters; 여기서 매개변수를 준비합니다. 이 필터 예에서는 아직 아무것도 할 필요가 없습니다.
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)
반품
;
// 첫 번째 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);
//Set inRect, outRect
ZeroPsRect(&gFilterRecord->inRect) //PS는 필요하지 않습니다. 원본 이미지에 어떤 색상이 있는지 알려주세요.
CopyPsRect(&m_Tile, & gFilterRecord->outRect);
데이터는 인터리브 배포) gFilterRecord
->inLoPlane = 0 ; gFilterRecord->
inHiPlane = 0; gFilterRecord->
outLoPlane = 0; gFilterRecord->
outHiPlane = (gFilterRecord- >비행기 -1);}
//
현재 패치가 여기에서 처리됩니다. 사용자가 Esc를 누르면 다음 호출은 Finishvoid
DoContinue( ){ if
(gFilterRecord
== NULL) return;
//
위치 픽셀
int
평면 = gFilterRecord->outHiPlane - gFilterRecord-> outLoPlane + 1 //채널 수 (uint8*)gFilterRecord->
outData;//스캔 줄 너비(바이트)
int stride = gFilterRecord->outRowBytes;
// 출력 직사각형을 m_Tile
CopyPsRect(&gFilterRecord->에 복사합니다. outRect, &m_Tile);
🎜> j = 0 ; j (m_Tile.bottom 🎜>- m_Tile.top); 🎜>) { for (int i =
0; i (m_Tile.right - m_Tile.left); i++) ~ > = 0 //빨간색 pData[ i*planes + j*stride + 1 ] = 0; i*planes
+
j*
보폭+ 2 ]
= 255 //
파랑 } } //처리 완료 여부 판단 if(m_Tile.right >= gFilterRecord->filterRect.right && m_Tile.bottom >= gFilterRecord->filterRect.bottom)
{
//处理结束
ZeroPsRect(&gFilterRecord->inRect);
ZeroPsRect(&gFilterRecord->outRect);
ZeroPsRect(&gFilterRecord->maskRect);
반환;
}
//设置下一个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);
//모든 채널 요청(데이터는 인터리브 분산됨)
gFilterRecord-> ;inLoPlane = 0;
gFilterRecord-> >inHiPlane = 0;
gFilterRecord->outLoPlane = 0;
gFilterRecord->outHiPlane = (gFilterRecord->비행기 -1 ; 🎜>void
DoFinish()
{}
위 코드도 필터입니다. 기본 프레임워크에서 DLL이 제공하는 내보내기 기능 중 하나가 PluginMain 기능임을 알 수 있습니다. 이미지를 128*128 픽셀 슬라이스로 분할하여 PS와 DLL 간에 더 적은 양의 데이터를 전송할 수 있습니다. 특히 매우 큰 이미지의 경우 슬라이싱 처리는 Photoshop에서 권장하는 64*64 또는 128*128 크기를 처리하는 데 도움이 됩니다. 호출 프로세스는 시작 호출에서 첫 번째 타일(Tile)을 초기화한 다음 첫 번째 타일을 outRect로 설정하는 것입니다. 이는 PS에게 직사각형을 수신할 버퍼를 제공하도록 요청한다는 의미입니다. inRect의 경우 단지 채우는 중이므로 이미지의 원래 색상은 신경 쓰지 않으므로 inRect를 "빈 직사각형"으로 설정할 수 있습니다. 이미지 채널 여기서는 코드의 직관성과 단순성을 위해 RGB 이미지, 즉 3채널 이미지만을 고려합니다. 첫 번째 outRect를 설정한 후 PS는 continue 호출을 순서대로 시작하고 패치는 모든 패치가 처리될 때까지 왼쪽에서 오른쪽으로, 위에서 아래로 콜라주됩니다. inData 및 outData는 PS가 필터에 제공하는 애플리케이션 데이터이자 "쓰기 저장 버퍼"입니다. 하나는 읽기용이고 다른 하나는 필터가 PS에 요청을 알릴 때 채워지는 데이터에 의해 제어됩니다. 작동 시간은 경계를 넘어서는 안 됩니다.
~ 포인터가 범위를 벗어나면
Photoshop 프로그램이 중단됩니다!
Photoshop에서 PIPL 리소스를 올바르게 인식하고 로드하려면 필터에 PIPL 리소스를 삽입해야 합니다. PS에서 제공한 문서에 따르면 PIPL의 발음은 플러그인 속성 목록을 의미하는 "pipple"입니다. 플러그인 모듈 메타데이터(메타데이터)를 나타내는 데 사용되는 유연하고 확장 가능한 데이터 구조입니다. pipl에는 일부 태그는 물론 각 플러그인을 제어하는 다양한 정적 속성 등을 포함하여 Photoshop이 플러그인 모듈을 인식하고 로드하는 데 필요한 모든 정보가 포함되어 있습니다. 필터에는 하나 이상의 "pipl" 구조가 포함될 수 있습니다.
필터용 pipl 리소스를 삽입하는 과정은 다음과 같습니다. 먼저 프로젝트에 *.r(Macintosh Rez 파일) 파일을 추가한 후 cl.exe를 사용하여 이 파일을 *.rr 파일. 마지막으로 Ps SDK에서 제공하는 리소스 변환 도구인 CnvtPipl.Exe를 사용하여 *.rr 파일을 *.pipl 파일로 변환한 후 필터용 *.rc 리소스 파일을 추가하고 rc 파일 끝에 pipl 파일이 있습니다.
ps sdk는 공통 속성 정의를 포함한 공통 r 파일인 PIGeneral.r 파일을 제공했습니다.
(a) 다음으로 프로젝트에 r 파일을 추가하고 리소스 관리자에서 "Resource Files" 폴더를 마우스 오른쪽 버튼으로 클릭한 다음 클릭하여 새 파일을 추가하고 "FillRed.r"을 입력합니다. 파일 이름. 파일을 두 번 클릭하여 열고 다음 내용을 복사하세요.
// 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 { 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 } } } };
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
(5)我们编译项目,即可在项目的输出目录中看到 生成 FillRed.8bf 文件,下面我们把这个文件复制到 Photoshop的滤镜文件夹下面,例如我的Photoshop CS的滤镜所在目录是:“D:\Program Files\Adobe\Photoshop CS\增效工具\滤镜”
最后我们启动Photoshop,Photoshop会扫描插件目录,并把我们的滤镜加载到相应的菜单上,我们选择一个矩形选区,然后点击我们制作的滤镜相应菜单,即可看到效果,如下图所示。注意,下面的例子的效果是我仅仅把蓝通道填充了255。
Photoshop 도움말 메뉴의 하위 메뉴인 플러그인 정보에서 우리가 작성한 "FillRed Filter..." 항목을 볼 수 있습니다. 이 항목을 클릭하면 PS가 관련 호출을 시작하고 팝업이 표시됩니다. - 메시지박스.
~ . 예를 들어 Photoshop SDK의 디렉터리는 특정 환경에 따라 조정되어야 합니다. PS SDK에서 제공하는 리소스 변환 도구도 프로젝트 폴더에 포함되어 있습니다. (참고: 첨부 파일에는 전체 PS SDK가 포함되어 있지 않습니다.) http://files.cnblogs.com/hoodlum1980/FillRed.rar
이 섹션에서는 프로젝트 생성부터 Pipl 리소스 삽입까지 기본 필터 프레임워크를 구축합니다. 그러나 그 기능은 매우 기본적이고 간단합니다. 앞으로는 대화 상자 리소스를 도입하고 PS가 대화 상자 표면 그리기 필터 미리 보기 그래픽 및 필터에 대한 매개 변수를 읽을 수 있도록 하는 등 이 예제를 계속해서 풍부하게 해야 할 수도 있습니다. 곧.
Photoshop 필터 작성 방법에 대한 더 많은 관련 기사(1)를 보려면 PHP 중국어 웹사이트를 주목하세요!

가장 경제적 인 방식으로 Photoshop에 액세스 할 수 있습니다. 1. 7 일 무료 평가판으로 소프트웨어 기능을 경험하십시오. 2. 계절적 프로모션뿐만 아니라 학생 또는 교사 할인을 찾으십시오. 3. 타사 웹 사이트에서 쿠폰을 사용하십시오. 4. Adobe CreativeCloud의 월별 또는 연간 계획을 구독하십시오.

다음 단계를 통해 Photoshop에서 시각적 개념을 만들 수 있습니다. 1. 새 문서 만들기, 2. 배경 레이어 추가, 2. 브러시 도구를 사용하여 기본 모양을 그리기 위해, 4. 색상과 밝기 조정, 5. 텍스트 및 그래픽 추가, 6. 로컬 편집에 마스크 사용, 필터 효과를 적용하는 데 도움이됩니다.이 단계는 스크래치에서 완전히 시각적 인 작업을 구축 할 수 있도록 도와줍니다.

Photoshop은 무료가 아니지만 저렴한 비용 또는 무료로 사용하는 몇 가지 방법이 있습니다. 1. 무료 시험 기간은 7 일 이며이 기간 동안 모든 기능을 경험할 수 있습니다. 2. 학생 및 교사 할인은 비용을 절반으로 줄일 수 있으며 학교 증거가 필요합니다. 3. CreativeCloud 패키지는 전문 사용자에게 적합하며 다양한 Adobe 도구가 포함되어 있습니다. 4. Photoshopelements와 Lightroom은 기능이 적지 만 가격이 낮은 저렴한 대안입니다.

Photoshop은 강력한 기능과 광범위한 애플리케이션 시나리오를 제공하기 때문에 투자 가치가 있습니다. 1) 핵심 기능에는 이미지 편집, 레이어 관리, 특수 효과 생산 및 색상 조정이 포함됩니다. 2) 전문 디자이너 및 사진 작가에게 적합하지만 아마추어는 김프와 같은 대안을 고려할 수 있습니다. 3) 높은 일회성 지출을 피하기 위해 필요에 따라 AdobecreativeCloud를 구독 할 수 있습니다.

창의적인 이미지 디자인에서 Photoshop의 핵심 사용은 강력한 기능과 유연성입니다. 1) 디자이너는 레이어, 마스크 및 필터를 통해 창의성을 시각적 현실로 변환 할 수 있습니다. 2) 기본 사용에는 자르기, 크기 조정 및 색 보정이 포함됩니다. 3) 레이어 스타일, 블렌드 모드 및 스마트 객체와 같은 고급 사용법은 복잡한 효과를 만들 수 있습니다. 4) 일반적인 실수에는 부적절한 계층 관리 및 필터 사용 과도한 사용이 포함되며, 레이어를 구성하고 필터를 합리적으로 사용하여 해결할 수 있습니다. 5) 성능 최적화 및 모범 사례에는 계층의 합리적 사용, 파일의 정기 저축 및 바로 가기 키 사용이 포함됩니다.

Photoshop은 웹 디자인에 사용하여 고 충실도 프로토 타입을 만들고 UI 요소를 설계하며 사용자 상호 작용을 시뮬레이션 할 수 있습니다. 1. 기본 디자인을 위해 레이어, 마스크 및 스마트 객체를 사용하십시오. 2. 애니메이션 및 타임 라인 기능을 통해 사용자 상호 작용을 시뮬레이션합니다. 3. 스크립트를 사용하여 설계 프로세스를 자동화하고 효율성을 향상시킵니다.

이전 기사 "PS (즐겨 찾기)를 사용하여 플레이트 이미지에 인쇄 효과를 추가하기 위해 단계별로 가르치십시오. 다음 기사는 PS 브러시를 사용하여 글꼴에 균열 효과를 추가하는 방법을 소개합니다. 어떻게하는지 살펴 보겠습니다.

Photoshop에서 레이어 스타일과 필터를 통해 텍스트 효과를 만들 수 있습니다. 1. 새 문서를 만들고 텍스트를 추가하십시오. 2. 그림자 및 외부 글로우와 같은 레이어 스타일을 적용하십시오. 3. 파도 효과와 같은 필터를 사용하고 경사 및 구호 효과를 추가하십시오. 4. 마스크를 사용하여 효과 범위와 강도를 조정하여 텍스트 효과의 시각적 영향을 최적화합니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

SublimeText3 영어 버전
권장 사항: Win 버전, 코드 프롬프트 지원!

DVWA
DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음
