Home Web Front-end PS Tutorial Introduction to Photoshop filter development--Photoshop callback function

Introduction to Photoshop filter development--Photoshop callback function

Feb 20, 2017 am 09:34 AM

In the previous article, we introduced some of the most basic concepts and foundations for developing Photoshop filter plug-ins. Ps In order to meet the application needs of the plug-in, it also provides a large number of callback functions (or services) for the plug-in. For example, a filter can save the parameters set by the latest user after a call and apply them to the next call or display of the UI. This is done through the callback function of Ps. In this article we will explain some of the most important PS callback functions. After understanding this article, we will be able to use callback functions to complete the necessary work such as storing our filter parameters. This article will be much more complex and in-depth than the first one, but at the same time, from this article we can also get a glimpse of the internal secrets of PS: careful system design, perfect interface and complex working mechanism.

(1) Classification of callback functions:
The callback functions of PS can be divided into two types according to the location of obtaining them:
(1) Direct Callback: (can Directly called callback functions)
These callback functions are direct members of FilterRecord and can be obtained directly from the FilterRecord parameters. For example, AdvanceStateProc (update data), TestAbortProc (test user cancels), etc., fall into this category.
(2) CallBack Suite: (Receiving function set)
The recovery function set provided by the transfer function according to the function classification is a set of a set of callback functions. It is a pointer, which contains a set of sets The structure (struct) of the callback function, we can get a certain callback function set from FilterRecord, and then call the function in it.

The main callback function sets currently provided are:
Buffer Suite: Cache memory management (application and release of cache space).
UI Hook Suite: A set of functions related to UI operations.
Channel Ports Suite: Channel port reading and writing, used to read and write the real selection data inside PS! Rather than a copy copy.
            Descriptor Suite: Descriptor operation set, used for script recording systems, which itself contains two sub-suites (sub-function sets): "read" and "write".
Color Space Suite: Color space services (color conversion, etc.).
          Handle Suite: Handle management (PS encapsulated handle and memory management, similar to Buffer suite).
Error Suite: Receive and display error messages to users (receives different types of error message strings).
GetFileList Suite: Get the file list (get files, call the browser to browse the web, etc.).
GetPath Suite: Get the path.
ZString Suite: Encapsulates string processing.

For example, UI Hook Suite provides a set of callback functions related to UI. Its first version was defined as:

UI Hooks Suite Version1
#define kPSUIHooksSuiteVersion1 1 // suite version
typedef
struct
{
ProcessEventProc processEvent;
DisplayPixelsProc displayPixels;
ProgressProc progressBar;
TestAbortProc testAbort;
MainAppWindowProc MainAppWindow;
HostSetCursorProc SetCursor;
HostTickCountProc TickCount;
PluginNameProc GetPluginName;
} PSUIHooksSuite1;

# Please note that some callback functions are direct callbacks and are stored in a suite , such as testAbout and displayPixels. I speculate that in the early days, these function pointers were added to FilterRecord, but with the upgrade, more and more callback functions were added, which would cause FilterRecord to continuously upgrade and add members, making maintenance difficult, so Adobe began to add callback functions Classification is divided into several suites, and only the suite is placed in FilterRecord. In this way, when adding a function, you only need to add it to the corresponding suite and upgrade the suite without affecting the FilterRecord. In this way, some early callback functions are located in two places at the same time, FilterRecord and the suite to which they belong, so that they can be called directly or through the corresponding suite.


(2) Suite PEA (Plug-in function set management module (layer), my translated name, to be discussed) Suite PEA is a plug-in system used by some Adobe series software. It provides a common plug-in management core layer for the host program and a standard interface for plug-ins.
It is slightly different from the direct call in that the function set should be acquired (Acquired) before use, and the suite should be released (release) after use.
                                                                                     
                                                                                                                                                                                                  # );

Therefore, a function in the callback function set is called, in the following form:

Suite的获取和释放
ADMBasicSuite *sADMBasic;

//获取ADMBasic Suite:
filterParamBlock->sSPBasic->AcquireSuite(
              kADMBasicSuite,
              kADMBasicSuiteVersion,
              
&sADMBasic );

//调用
sADMBasic->Beep( );

//释放
filterParamBlock->sSPBasic->ReleaseSuite(
               kADMBasicSuite,
               kADMBasicSuiteVersion );


# (3) Part of the more important callback function profile

This Here we will introduce some recovery functions that I think are more important for the filter plug -in . Briefly introduce the location and use of these callback functions.
3.1 DisplayPixelsProc( )
Function: Output pixel data (draw a picture) at the specified position on the specified DC. (Of course, we can actually complete this function ourselves.)
Location: Direct Callback, UI Hook Suite;
Definition:
OSErr (*DisplayPixelsProc) (const PSPixelMap *source ,
CONST VRECT *SRCRECT, Int32 DStrow, Int32 DStcol,
UNSIGNED32 PlatformContext);
## Source Instructions:
Source: The first parameter is a structure that describes pixel information (PSPIXELMAP). pointer, which is defined as follows:

PSPixelMap Struct Define

typedef struct PSPixelMap{
int32 version; /
Version number                                                                                                                 # int32 imageMode; //
Mode
## int32 rowBytes; / /Scan line width
# int32 colBytes;       //Number of column bytes
int32 planeBytes; //Number of bytes per channel
void
*
baseAddr; //Pixel data starting address
//
--------------------// Omitted .. } PSPixelMap;
          srcRect: Source rectangle (copy range of the source image)
      dstRow, dstCol: Target starting point coordinates (upper left corner), because it is not stretched and drawn, so only the coordinates of the upper left corner are enough.
           platformContext: Under Windows system, that is, device context (DC);

3.2 Descriptor suite (descriptor function set)
The descriptor set is mainly used for the script system of PS. It is used to record (record) the information and parameters required during a series of actions in PS, and can be played back. It is divided into two sub-function sets: "read" and "write". We can use this function set to make PS's scripting system "know" our filters and record them into an action sequence.
The way to obtain it is to first get PIDescriptorParameters through FilterRecord:

PIDescriptorParameters Struct Define
typedef struct PIDescriptorParameters
{
int16 descriptorParametersVersion;
//Version number
## int16 playInfo; // Action playback identification: 0-dialog box optional; 1-dialog box required; 2-no dialog box;
## int16 recordInfo;
//Action recording identification: 0-The dialog box is not displayed; 1-The dialog box is displayed; 2-The dialog box is silent; ## PIDescriptorHandle descriptor;
//The handle of the descriptor is very important, we will use it to read and write data! ## WriteDescriptorProcs
*
writeDescriptorProcs; //"Write" sub-function Set## ReadDescriptorProcs*
readDescriptorProcs; //"read" sub Function set} PIDescriptorParameters;
Then we can get the "read" or "write" sub-function set:

Get the "read" and "write" sub-suite
//Get the descriptor parameter structure:
PIDescriptorParameters*## descParams = gFilterRecord- >descriptorParameters;
if (descParams == NULL) return err;

##//
Get the "read" sub-function set:
ReadDescriptorProcs
*## readProcs = gFilterRecord->descriptorParameters ->readDescriptorProcs; if
(readProcs == NULL) return err;
//
Get the "write" sub-function set: WriteDescriptorProcs
* writeProcs = gFilterRecord-> descriptorParameters->writeDescriptorProcs; if
(writeProcs == NULL) return err;
Having obtained two sub-function sets, we can call the functions under the corresponding sub-function sets to "read" and "write" our parameters. The use of the two sub-function sets is similar to the registry operation. Before reading and writing, we first need to open the corresponding descriptor. Therefore we first introduce the opening and closing descriptor operations.
      OpenReadDescriptorProc( ): Open a "read" descriptor
      Definition:
        PIReadDescriptor (*OpenReadDescriptorProc) (PIDescriptorHandle, DescriptorKeyIDArray);
            Parameter description:  
PIDescriptorHandle:
Descriptor handle, we will use it to read and write data in subsequent operations, similar to the Key of the registry.
        DescriptorKeyIDArray:
                uint32 array, stores the key set that needs to be queried.其相关定义为:
                  typedef unsigned long DescriptorKeyID;
                  typedef DescriptorKeyID DescriptorKeyIDArray[];

The elements in the array are the key names you need, that is, the parameter names you want to query, that is, which keys you want to query. Note that because it is an int32 type, each key can hold an ASCII code represented by 4 characters. If it is less than 4 bytes, it can be filled with spaces. For example, setting this parameter assignment can set {'Pam1','Pam2',NULL}, which means you need to query two parameters, 'Pam1' and 'Pam2'. For example, in the script system, the key of the Gaussian Blur (GaussianBlur) filter is 'GsnB'.
Each key value is obtained by calling GetKeyProc(). Each time a value is returned, the corresponding key in this string array will be set to empty ('\0'). Under normal circumstances, when you call CloseReadDescriptorProc(), this array will become all empty. Otherwise, it means that some keys have not been queried. At this time, you will lose your data or display the dialog box. Ask users to provide data.

##           CloseReadDescriptorProc(): Close a "read" descriptor     Definition:
     OSErr (*CloseReadDescriptorProc) (PIReadDescriptor);

Description; Close a descriptor. If an error occurs during reading, it will return the main error.


        GetKeyProc( ): Get a Key
        Definition:
           
(*GetKeyProc) (PIReadDescriptor descriptor, DescriptorKeyID *key, DescType *type, int16 *flags); Description: This function returns a KeyID (parameter name), descriptor type, and identification. According to the key returned by the function, it indicates which key is currently queried. We can then use the corresponding query function mentioned below to obtain the value of this key. Related type definitions:

     typedef unsigned long DescriptorKeyID;    typedef unsigned long DescriptorTypeID;

                                                                                       Definition: PIWriteDescriptor (*OpenWriteDescriptorProc) (void);
Description: Open a write descriptor, if failed, return NULL;CloseWriteDescriptorProc()
Definition:
OSErr ( *CloseWriteDescriptorProc) (PIWriteDescriptor descriptor, PIDescriptorHandle *newDescriptor);
Description:
This function closes a write descriptor and creates a new descriptor handle. You need to set the new descriptor to PIDescriptorParameteres to return it to the host program. The behavior of the function here is somewhat similar to SelectObject in GDI operations. In a GDI operation, when you set new properties on the device context, it returns the existing properties to you, expecting you to make a backup.

                                                                                                                                                                              ‐                                       ’ ’ s ’ s ’ s ’ s to ’ s ’ s               ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ​ ​ ​ ​ ​ ​ ​ ​I will explain them one by one. Here I only introduce the general form and explain them separately when necessary.                                                                                                                                                                                                                                             Most have relatively standardized characteristics (there are a few functions with exception forms, which we will introduce separately later), that is, reading starts with Get, writing starts with Put, the first parameter is the corresponding descriptor, and the second parameter is The corresponding type of data pointer used to receive query results (or to store written data). Assuming that the data type we need to query is TypeName, it is as follows:
      OSErr (*
Get
TypeName

Proc) (PIReadDescriptor descriptor, TypeName *dest); //Read OSErr (*PutTypeName
Proc) (PIWriteDescriptor descriptor,
DescriptorKeiD, Typename * Dest); // Write: Below we list the functions of all readable functions and write sub -function sets (at pilation. h): Read Descriptor sub-suite

##Code highlighting produced by Actipro CodeHighlighter (freeware)http:// www.php.cn/-->
////写子函数集成员,形式类似前面的函数,但都额外需要提供key
typedef struct WriteDescriptorProcs
 {
 int16 writeDescriptorProcsVersion;
 int16 numWriteDescriptorProcs;
 OpenWriteDescriptorProc  openWriteDescriptorProc;
 CloseWriteDescriptorProc closeWriteDescriptorProc;
 PutIntegerProc    putIntegerProc;
 PutFloatProc    putFloatProc;
 PutUnitFloatProc   putUnitFloatProc;
 PutBooleanProc    putBooleanProc;
 PutTextProc     putTextProc;
 PutAliasProc    putAliasProc;
 PutEnumeratedProc   putEnumeratedProc;
 PutClassProc    putClassProc;
 PutSimpleReferenceProc  putSimpleReferenceProc;
 PutObjectProc    putObjectProc;
 PutCountProc    putCountProc; 
 PutStringProc    putStringProc; 
 
/* Scoped classes are not for use by plug-ins in Photoshop 4.0 */
  PutScopedClassProc   putScopedClassProc;
 PutScopedObjectProc   putScopedObjectProc; 
 } WriteDescriptorProcs;


Reading and writing parameter examples:
Reading parameters from the script system: Suppose the key of our parameter is 'Pam1', we use a temporary variable param1 to receive it:

Read A Parameter Demo Code
PIReadDescriptor token = NULL; //Read operator
DescriptorKeyID key = NULL; //uint32, that is, char*, Key name
DescriptorTypeID type = NULL; //Descriptor Type
int32 flags = 0; #//Identification# DescriptorKeyIDArray array
= { 'Pam1', NULL }; //The key set to be queried
double param1; //The parameters we want to read //
Get the descriptor parameter structure## PIDescriptorParameters
*
descParams = gFilterRecord->descriptorParameters;     if
(descParams  
== NULL) return err; //
Get the "read" sub-function in Descriptor Suite Set
## ReadDescriptorProcs*
readProcs = gFilterRecord->descriptorParameters->readDescriptorProcs;     if (readProcs  
== NULL) return err;
if (descParams->descriptor != NULL)
{
         
//Open the "read" descriptor
##                                                   1 readProcs->openReadDescriptorProc(descParams->descriptor, array);        if
(token
!= NULL)                                                                                                                                     
##            
while(readProcs->
getKeyProc(token,
&key, &type, &#flags) && !err)                                                                                                                                                 ##             case 'Pam1
'
:/ /
Read our parameters
##                                                                                                                                                    >getFloatProc(token, &param1);                                                              #default:                                                                                                                                                                                                     Since #                                                                                                                                         

            err = readProcs->closeReadDescriptorProc(token);
            
//释放描述符
            gFilterRecord->handleProcs->disposeProc(descParams->descriptor);
            descParams
->descriptor = NULL;
        }
   }

        向脚本系统写入参数:同上面的例子:

Write Descriptor Demo Code
    OSErr err = noErr;
    PIWriteDescriptor token 
= NULL;
    PIDescriptorHandle h;
    const
double param1 = 1.05;

    PIDescriptorParameters
*    descParams = gFilterRecord->descriptorParameters;
    
if (descParams == NULL) return err;
    
    WriteDescriptorProcs
* writeProcs = gFilterRecord->descriptorParameters->writeDescriptorProcs;
    
if (writeProcs == NULL) return err;

    token 
= writeProcs->openWriteDescriptorProc();
    
if (token != NULL)
    {
        //写入参数~
        writeProcs
->putFloatProc(token,'Pam1',&param1);
        //释放描述符

        gFilterRecord
->handleProcs->disposeProc(descParams->descriptor);
        //关闭该“读”描述符
        writeProcs
->closeWriteDescriptorProc(token, &h);
        //把新的描述符返还给photoshop
        descParams
->descriptor = h;
    }


3.3 DescriptorRegistry suite: (Descriptor registration function set)
The descriptor registration function set is mainly used for the registration and acquisition of descriptors. This allows ps to be entrusted to save our parameters while the filter is called multiple times. It contains several key functions for registration, removal, and key acquisition.
      Register()
                                                                                                                                                                                                                                                                         .
                                                                                                                # or descriptor, //Descriptor handle
                                                                                                                                                                                                                                                                                             Remove a Key Definition:
OSErr (*Erase)
(
) /* IN */ const char* key // Unique string or ID
);
##Get()
Description: Returns a Key. The returned descriptor is a copy, so you must actively release it after use.
                                                                                                                                                         /* OUT */ PIActionDescriptor* descriptor / / Release him after use
);




3.4 ActionDescriptor suite: (Action descriptor function set)

## Action Descriptor function set,
is used to store keys (or objects) into descriptors, read them from descriptors, and other descriptor management. This function set contains both read and write functions, and the usage method is similar to the descriptor in the previous section. It is defined as follows:



PSActionDescriptorProcs Struct



Code highlighting produced by Actipro CodeHighlighter (freeware)http:// www.php.cn/-->typedef
struct
PSActionDescriptorProcs
{

 //
ALLOCATES: descriptor//Write parameters and register
SPErr WriteRegistryParameters(void)
{
SPErr err
= noErr;
#// Obtain SPBasicSuite, which is the basis for obtaining other Suites
## SPBasicSuite* basicSuite = gFilterRecord->sSPBasic;
// Descriptor registration function set pointer
## PSDescriptorRegistryProcs
*## registryProcs = NULL; //
Descriptor function set pointer PSActionDescriptorProcs
* descriptorProcs = NULL; //
Descriptor handle PIActionDescriptor descriptor
= NULL; //
Our parameters
double param1=0.1;
//
Get the descriptor registration function set err
= basicSuite->AcquireSuite(kPSDescriptorRegistrySuite,                                                       (const

void **)&registryProcs);//Get the action descriptor function set
## err = basicSuite ->AcquireSuite(kPSActionDescriptorSuite,                                                      (

const
void **)&descriptorProcs);                                                                                               ## descriptorProcs

->
Make(&descriptor); //Write us Parameters err =
descriptorProcs
->
PutFloat(descriptor, 'Pam1',param1); //Register the descriptor of the specified ID err = registryProcs- >Register(plugInUniqueID, descriptor, true);
//
Release descriptor

if
(descriptor
!= NULL) descriptorProcs->Free (descriptor);
//Release function set
if
(registryProcs
!= NULL) basicSuite->ReleaseSuite(kPSDescriptorRegistrySuite, kPSDescriptorRegi strySuiteVersion);
      
if (descriptorProcs 

!=
NULL)           basicSuite->ReleaseSuite(kPSActionDescriptorSuite,                                                                                                                                                                                                                                                      Example of reading our parameters:

Reading registered parameters
//Read registered parameters
SPErr ReadRegistryParameters(void)
{
SPErr err
= noErr;
/ /Get the basic function set, SPBasicSuite, and get other function sets through it
SPBasicSuite* basicSuite = gFilterRecord->sSPBasic;
PSDescriptorRegistryProcs
* registryProcs = NULL;
PSActionDescriptorProcs
* descriptorProcs = NULL;
PIActionDescriptor descriptor
= NULL;
double param1;

//Get the descriptor registration function set
## err = basicSuite-> AcquireSuite(kPSDescriptorRegistrySuite, #const

void **)&registryProcs); //

Get the action descriptor Function set
err
=
basicSuite->AcquireSuite(kPSActionDescriptorSuite ) ** )

&
descriptorProcs);
//Get the descriptor of the specified ID
## err = registryProcs->Get(plugInUniqueID, &descriptor);
//Read registered Parameter err
= descriptorProcs->GetFloat(descriptor, 'Pam1',&param1);
//Release descriptor
if (descriptor != NULL ) descriptorProcs
->Free(descriptor);
//Release descriptor registration function set
##       
if (registryProcs  != NULL)                                                                                                                #->
ReleaseSuite(kPSDescriptorRegistrySuite,                                                                                                                                                                                                                
##                                                                                                                                                                                                                        ##->
ReleaseSuite(kPSActionDescriptorSuite,                                                                                                                                                                                                            ## (4) Summary
This article, we introduced some photoshop to the plug -in (not just to the filter plug -in) recovery function. It is divided into two major categories, one is directly included in the plug-in parameter structure, called a direct callback function; the other is a callback function included in the callback function set.
                For the direct callback function, the text only explains that DisplayPixelsProc can be used to map on the device DC. Including AdvanceStateProc, TestAbortProc, and UpdateProgressProc mentioned in the first article, they are all direct callbacks, and some direct callback functions belong to a certain Suite.                                                                                                                                                            but also for the callback function set (Callback Suite), we focused on the reading, writing, registration and other operations in the Descriptor Suite in the callback function set. This function set can enable PS to record our filter parameters into the action sequence, or it can Register our filter parameters to save and read them across multiple calls. Other callback function sets such as memory management, color space services and other function sets have not been covered yet due to space limitations. (--By hoodlum1980)For more introduction to Photoshop filter development--Photoshop callback function related articles, please pay attention to the PHP Chinese website!

Statement of this Website
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

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

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1664
14
PHP Tutorial
1268
29
C# Tutorial
1241
24
Photoshop's Value: Weighing the Cost Against Its Features Photoshop's Value: Weighing the Cost Against Its Features Apr 11, 2025 am 12:02 AM

Photoshop is worth the investment because it provides powerful features and a wide range of application scenarios. 1) Core functions include image editing, layer management, special effects production and color adjustment. 2) Suitable for professional designers and photographers, but amateurs may consider alternatives such as GIMP. 3) Subscribe to AdobeCreativeCloud can be used as needed to avoid high one-time spending.

Advanced Photoshop Tutorial: Master Retouching & Compositing Advanced Photoshop Tutorial: Master Retouching & Compositing Apr 17, 2025 am 12:10 AM

Photoshop's advanced photo editing and synthesis technologies include: 1. Use layers, masks and adjustment layers for basic operations; 2. Use image pixel values ​​to achieve photo editing effects; 3. Use multiple layers and masks for complex synthesis; 4. Use "liquefaction" tools to adjust facial features; 5. Use "frequency separation" technology to perform delicate photo editing, these technologies can improve image processing level and achieve professional-level effects.

Photoshop's Key Features: A Deep Dive Photoshop's Key Features: A Deep Dive Apr 19, 2025 am 12:08 AM

Key features of Photoshop include layers and masks, adjustment tools, filters and effects. 1. Layers and masks allow independent editing of image parts. 2. Adjust tools such as brightness/contrast can modify image tone and brightness. 3. Filters and effects can quickly add visual effects. Mastering these features can help creative professionals achieve their creative vision.

Using Photoshop: Creative Possibilities and Practical Uses Using Photoshop: Creative Possibilities and Practical Uses Apr 22, 2025 am 12:09 AM

Photoshop is very practical and creative in practical applications. 1) It provides basic editing, repairing and synthesis functions, suitable for beginners and professionals. 2) Advanced features such as content recognition fill and layer style can improve image effects. 3) Mastering shortcut keys and optimizing layer structure can improve work efficiency.

Is Photoshop Free? Understanding Subscription Plans Is Photoshop Free? Understanding Subscription Plans Apr 12, 2025 am 12:11 AM

Photoshop is not free, but there are several ways to use it at low cost or free: 1. The free trial period is 7 days, and you can experience all functions during this period; 2. Student and teacher discounts can cut costs by half, and school proof is required; 3. The CreativeCloud package is suitable for professional users and includes a variety of Adobe tools; 4. PhotoshopElements and Lightroom are low-cost alternatives, with fewer functions but lower prices.

The Core Purpose of Photoshop: Creative Image Design The Core Purpose of Photoshop: Creative Image Design Apr 10, 2025 am 09:29 AM

Photoshop’s core use in creative image design is its powerful functionality and flexibility. 1) It allows designers to transform creativity into visual reality through layers, masks and filters. 2) Basic usages include cropping, resizing and color correction. 3) Advanced usages such as layer styles, blend modes and smart objects can create complex effects. 4) Common mistakes include improper layer management and excessive use of filters, which can be solved by organizing layers and using filters reasonably. 5) Performance optimization and best practices include rational use of layers, regular saving of files, and using shortcut keys.

Photoshop: Investigating Free Trials and Discount Options Photoshop: Investigating Free Trials and Discount Options Apr 14, 2025 am 12:06 AM

You can get the access to Photoshop in the most economical way: 1. Experience the software features with a 7-day free trial; 2. Find student or teacher discounts, as well as seasonal promotions; 3. Use coupons on third-party websites; 4. Subscribe to Adobe CreativeCloud's monthly or annual plan.

Photoshop for Designers: Creating Visual Concepts Photoshop for Designers: Creating Visual Concepts Apr 13, 2025 am 12:09 AM

Creating visual concepts in Photoshop can be achieved through the following steps: 1. Create a new document, 2. Add a background layer, 3. Use the brush tool to draw basic shapes, 4. Adjust colors and brightness, 5. Add text and graphics, 6. Use masks for local editing, 7. Apply filter effects, these steps help designers build a complete visual work from scratch.

See all articles