### Install Python Dependencies for Docs
Source: https://photoshopapi.readthedocs.io/en/latest/building.html
Navigate to the Doxygen documentation directory within the PhotoshopAPI project and install the required Python dependencies using pip.
```bash
$ cd
$ cd docs/doxygen
$ py -m pip install -r requirements.txt
```
--------------------------------
### Install PhotoshopAPI Python Bindings
Source: https://photoshopapi.readthedocs.io/en/latest/building.html
Install the PhotoshopAPI Python bindings from PyPi using pip. This is the recommended method for using the bindings in your Python projects.
```bash
$ py -m pip install PhotoshopAPI
```
--------------------------------
### LayeredFile Operations
Source: https://photoshopapi.readthedocs.io/en/latest/code/layeredfile.html
Examples of reading, modifying, and writing Photoshop files using the LayeredFile interface.
```APIDOC
## Read and Modify LayeredFile
### Description
Reads a PSD file from disk, moves a layer within the hierarchy, removes a group, and writes the modified file back to disk.
### Request Example
```cpp
using namespace NAMESPACE_PSAPI;
LayeredFile layeredFile = LayeredFile::read("InFile.psd");
layeredFile.move_layer("Group/NestedGroup/Image", "Group");
layeredFile.remove_layer("Group/NestedGroup");
LayeredFile::write(std::move(layeredFile), "OutFile.psd");
```
```
--------------------------------
### Initialize and Write Photoshop Files
Source: https://photoshopapi.readthedocs.io/en/latest/code/layeredfile.html
Shows how to create a new LayeredFile from scratch, populate it with an image layer containing color channels, and write it to disk.
```cpp
using namespace PhotoshopAPI;
const static uint32_t width = 64u;
const static uint32_t height = 64u;
LayeredFile document = { Enum::ColorMode::RGB, width, height };
// Create our individual channels to add to our image layer. Keep in mind that all these 3 channels
// need to be specified for RGB mode
std::unordered_map > channelMap;
channelMap[Enum::ChannelID::Red] = std::vector(width * height, 255u);
channelMap[Enum::ChannelID::Green] = std::vector(width * height, 0u);
channelMap[Enum::ChannelID::Blue] = std::vector(width * height, 0u);
ImageLayer::Params layerParams = {};
layerParams.layerName = "Layer Red";
layerParams.width = width;
layerParams.height = height;
auto layer = std::make_shared>(std::move(channelMap), layerParams);
document.add_layer(layer);
LayeredFile::write(std::move(layeredFile), "OutFile.psd");
```
--------------------------------
### Define Image Data Dictionary
Source: https://photoshopapi.readthedocs.io/en/latest/python/layers/image.html
Example structure for passing RGB image data as a dictionary of numpy arrays.
```python
data = {
0 : numpy.ndarray,
1 : numpy.ndarray,
2 : numpy.ndarray
}
```
--------------------------------
### Create Simple Document in Python
Source: https://photoshopapi.readthedocs.io/en/latest/examples/create_simple_document.html
Example of creating a simple 8-bit RGB document with a single red layer and exporting it as a PSD file. Demonstrates initialization, layer creation, property modification, and file writing.
```python
# Example of creating a simple document with a single layer using the PhotoshopAPI.
import os
import numpy as np
import photoshopapi as psapi
def main() -> None:
# Initialize some constants that we will need throughout the program
width = 64
height = 64
color_mode = psapi.enum.ColorMode.rgb
# Generate our LayeredFile instance
document = psapi.LayeredFile_8bit(color_mode, width, height)
img_data = np.zeros((3, height, width), np.uint8)
img_data[0] = 255
# When creating an image layer the width and height parameter are required if its not a zero sized layer
img_layer = psapi.ImageLayer_8bit(img_data, "Layer Red", width=width, height=height)
document.add_layer(img_layer)
# Similar to the C++ version we can adjust parameters of the layer after it has been added to the document
# as long as it happens before we write to disk
img_layer.opacity = .5
document.write(os.path.join(os.path.dirname(__file__), "WriteSimpleFile.psd"))
if __name__ == "__main__":
main()
```
--------------------------------
### Get Channel by Index
Source: https://photoshopapi.readthedocs.io/en/latest/python/layers/smart_object.html
Retrieves a specific channel from the image data, including the mask channel. Accessing individual channels can be slower than getting all data at once.
```APIDOC
## GET /api/layers/{layer_id}/channel/{key}
### Description
Get the specified channel from the image data, this may also be the mask channel at index -2.
If -2 is passed this function is identical to get_mask(). The mask channel will have the shape { mask_height(), mask_width() } while any other channel will have the shape { height(), width() }.
Generally accessing each channel individually is slower than accessing all of them with get_image_data() as that function is better parallelized. So if you wish to extract more than a couple channels it is recommended to get all of them.
### Method
GET
### Endpoint
/api/layers/{layer_id}/channel/{key}
### Parameters
#### Path Parameters
- **layer_id** (string) - Required - The ID of the layer.
- **key** (int) - Required - The key to access the channel. Use -2 for the mask channel.
### Response
#### Success Response (200)
- **channel_data** (numpy.ndarray) - The extracted channel data.
#### Response Example
```json
{
"channel_data": "[numpy.ndarray]"
}
```
### Errors
- **ValueError**: if the specified index does not exist on the layer.
```
--------------------------------
### Create Simple Document in C++
Source: https://photoshopapi.readthedocs.io/en/latest/examples/create_simple_document.html
Example of creating a simple 8-bit RGB document with a single red layer and exporting it as a PSD file. Demonstrates initialization, layer creation, property modification, and file writing.
```cpp
/*
Example of creating a simple document with a single layer using the PhotoshopAPI.
*/
#include "PhotoshopAPI.h"
#include
#include
int main()
{
using namespace NAMESPACE_PSAPI;
// Initialize some constants that we will need throughout the program
const static uint32_t width = 64u;
const static uint32_t height = 64u;
// Create an 8-bit LayeredFile as our starting point, 8- 16- and 32-bit are fully supported
LayeredFile document = { Enum::ColorMode::RGB, width, height };
// Create our individual channels to add to our image layer. Keep in mind that all these 3 channels need to
// be specified for RGB mode
std::unordered_map > channelMap;
channelMap[Enum::ChannelID::Red] = std::vector(width * height, 255u);
channelMap[Enum::ChannelID::Green] = std::vector(width * height, 0u);
channelMap[Enum::ChannelID::Blue] = std::vector(width * height, 0u);
ImageLayer::Params layerParams = {};
layerParams.name = "Layer Red";
layerParams.width = width;
layerParams.height = height;
layerParams.display_color = Enum::LayerColor::blue;
auto layer = std::make_shared>(std::move(channelMap), layerParams);
document.add_layer(layer);
// It is perfectly legal to modify a layers properties even after it was added to the document as attributes
// are only finalized on export
layer->opacity(.5);
// Convert to PhotoshopFile and write to disk. Note that from this point onwards
// our LayeredFile instance is no longer usable
LayeredFile::write(std::move(document), "WriteSimpleFile.psd");
}
```
--------------------------------
### Get File Section Size - C++
Source: https://photoshopapi.readthedocs.io/en/latest/code/photoshopsections/additionallayerinfo.html
Gets the size of the FileSection, casting it to a specified integral type. It includes internal checks to prevent overflow for the template argument T.
```cpp
template inline T size() const
```
--------------------------------
### Compile PhotoshopAPI from Source
Source: https://photoshopapi.readthedocs.io/en/latest/building.html
After cloning the repository, compile the static library using your preferred compiler. The include files and the library binary will be located in specific subdirectories.
```bash
$ /bin-int/PhotoshopAPI//include
```
```bash
$ /bin-int/PhotoshopAPI//PhotoshopAPI/PhotoshopAPI.lib
```
--------------------------------
### Get Text Layer Attributes in C++
Source: https://photoshopapi.readthedocs.io/en/latest/concepts/text-layers.html
Retrieve various text layer properties such as text content, position, dimensions, and orientation. You can also iterate through style and paragraph runs to get their specific attributes.
```cpp
auto text = layer->text();
auto [x, y] = layer->position();
auto box_w = layer->box_width();
auto box_h = layer->box_height();
auto orientation = layer->orientation();
if (auto lengths = layer->style_run_lengths(); lengths.has_value()) {
for (size_t i = 0; i < lengths->size(); ++i) {
auto font_idx = layer->style_run_font(i);
auto size = layer->style_run_font_size(i);
auto fill = layer->style_run_fill_color(i);
auto char_dir = layer->style_run_character_direction(i);
}
}
if (auto p_lengths = layer->paragraph_run_lengths(); p_lengths.has_value()) {
for (size_t i = 0; i < p_lengths->size(); ++i) {
auto just = layer->paragraph_run_justification(i);
}
}
```
--------------------------------
### Create Layered File with Mask (C++)
Source: https://photoshopapi.readthedocs.io/en/latest/examples/add_layer_masks.html
Demonstrates creating an 8-bit RGB LayeredFile, adding an image layer with a pixel mask channel, and writing the document to disk. Ensure all necessary channels are specified for the color mode.
```cpp
/*
Example of creating a simple document with a single layer and a mask using the PhotoshopAPI.
*/
#include "PhotoshopAPI.h"
#include
#include
int main()
{
using namespace NAMESPACE_PSAPI;
// Initialize some constants that we will need throughout the program
constexpr uint32_t width = 64u;
constexpr uint32_t height = 64u;
// Create an 8-bit LayeredFile as our starting point, 8- 16- and 32-bit are fully supported
LayeredFile document = { Enum::ColorMode::RGB, width, height };
// Create our individual channels to add to our image layer. Keep in mind that all these 3 channels need to
// be specified for RGB mode
std::unordered_map > channelMap;
channelMap[Enum::ChannelID::Red] = std::vector(width * height, 255u);
channelMap[Enum::ChannelID::Green] = std::vector(width * height, 0u);
channelMap[Enum::ChannelID::Blue] = std::vector(width * height, 0u);
// Create a mask channel which for now is just a semi grey channel. This channel for the time being
// needs to be the exact same size as the layer even though Photoshop officially supports masks being smaller
// or larger than channels
auto maskchannel = std::vector(width * height, 128u);
ImageLayer::Params layerParams = {};
layerParams.name = "Layer Red";
layerParams.width = width;
layerParams.height = height;
layerParams.mask = maskchannel;
layerParams.center_x = 32;
layerParams.center_y = 32;
auto layer = std::make_shared>(
std::move(channelMap),
layerParams
);
document.add_layer(layer);
// Convert to PhotoshopDocument and write to disk. Note that from this point onwards
// our LayeredFile instance is no longer usable
LayeredFile::write(std::move(document), "WriteLayerMasks.psd");
}
```
--------------------------------
### Get Layer Opacity
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Retrieves the layer opacity.
```cpp
inline float opacity() const noexcept
```
--------------------------------
### Get FileSection Offset
Source: https://photoshopapi.readthedocs.io/en/latest/code/photoshopsections/imagedata.html
Retrieves the offset of the FileSection.
```cpp
inline size_t offset() const noexcept#
```
--------------------------------
### Access Visibility
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Methods to get or set the layer visibility.
```cpp
inline bool &visible() noexcept
```
```cpp
inline bool visible() const noexcept
```
```cpp
inline void visible(bool is_visible) noexcept
```
--------------------------------
### Create Layered File with Mask (Python)
Source: https://photoshopapi.readthedocs.io/en/latest/examples/add_layer_masks.html
Demonstrates creating an 8-bit RGB LayeredFile using numpy arrays for image data and a mask, then adding the layer and writing the document to disk. The output file is saved in the same directory as the script.
```python
# Example of creating a simple document with a single layer and a mask using the PhotoshopAPI.
import os
import numpy as np
import photoshopapi as psapi
def main() -> None:
# Initialize some constants that we will need throughout the program
width = 64
height = 64
color_mode = psapi.enum.ColorMode.rgb
# Generate our LayeredFile instance
document = psapi.LayeredFile_8bit(color_mode, width, height)
img_data = np.zeros((3, height, width), np.uint8)
img_data[0] = 255
mask = np.full((height, width), 128, np.uint8)
img_layer = psapi.ImageLayer_8bit(img_data, "Layer Red", layer_mask=mask, width=width, height=height)
# Add the layer and write to disk
document.add_layer(img_layer)
document.write(os.path.join(os.path.dirname(__file__), "WriteLayerMasks.psd"))
if __name__ == "__main__":
main()
```
--------------------------------
### Get Center Y Coordinate
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Retrieves the y-coordinate of the layer center.
```cpp
inline virtual float center_y() const noexcept override
```
--------------------------------
### SmartObjectLayer Constructors
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Details on how to initialize a SmartObjectLayer, either from a file path or from existing layer data.
```APIDOC
## POST /smartobjectlayer/from_file
### Description
Initializes a SmartObjectLayer from a specified file path. This method loads the image data, resamples it based on provided parameters, and requires a LayeredFile object for state management.
### Method
POST
### Endpoint
/smartobjectlayer/from_file
### Request Body
- **file** (LayeredFile&) - Required - The LayeredFile this SmartObject is to be associated with.
- **parameters** (Layer::Params&) - Required - The Layers’ parameters.
- **filepath** (std::filesystem::path) - Required - The path of the file to load. This file must be in a format Photoshop can decode. It's recommended to keep this file local to the output directory if `link_externally` is true.
- **linkage** (LinkedLayerType) - Optional - Whether to link the file externally. Defaults to `LinkedLayerType::data` (false).
- **warp** (SmartObject::Warp) - Optional - The warp to apply to the image data. If not provided, a default warp can be generated or modified later.
### Request Example (with warp)
```json
{
"file": "",
"parameters": "",
"filepath": "/path/to/your/image.psb",
"linkage": "external",
"warp": {
"type": "custom",
"data": ""
}
}
```
### Request Example (without warp)
```json
{
"file": "",
"parameters": "",
"filepath": "/path/to/your/image.psb",
"linkage": "internal"
}
```
### Response
#### Success Response (200)
- **message** (string) - Confirmation of SmartObjectLayer creation.
#### Response Example
```json
{
"message": "SmartObjectLayer created successfully."
}
```
## POST /smartobjectlayer/from_data
### Description
Generates a SmartObjectLayer from existing Photoshop file data, including layer records, channel image data, file header, and additional layer information. This constructor is intended for internal use.
### Method
POST
### Endpoint
/smartobjectlayer/from_data
### Request Body
- **file** (LayeredFile&) - Required - The LayeredFile this SmartObject is to be associated with.
- **layerRecord** (LayerRecord) - Required - The record of the layer.
- **channelImageData** (ChannelImageData&) - Required - The image data for the channels.
- **header** (FileHeader) - Required - The header information of the file.
- **globalAdditionalLayerInfo** (AdditionalLayerInfo) - Required - Additional global layer information.
### Request Example
```json
{
"file": "",
"layerRecord": "",
"channelImageData": "",
"header": "",
"globalAdditionalLayerInfo": ""
}
```
### Response
#### Success Response (200)
- **message** (string) - Confirmation of SmartObjectLayer creation from data.
#### Response Example
```json
{
"message": "SmartObjectLayer created from data successfully."
}
```
```
--------------------------------
### Create and Write Simple Document (C++)
Source: https://photoshopapi.readthedocs.io/en/latest/index.html
Use this snippet to create a basic Photoshop document with a single image layer. Ensure you have the necessary includes and namespace. The LayeredFile instance is moved during the write operation and becomes unusable afterward.
```cpp
/*
Example of creating a simple document with a single layer using the PhotoshopAPI.
*/
#include "PhotoshopAPI.h"
#include
#include
int main()
{
using namespace NAMESPACE_PSAPI;
// Initialize some constants that we will need throughout the program
const static uint32_t width = 64u;
const static uint32_t height = 64u;
// Create an 8-bit LayeredFile as our starting point, 8- 16- and 32-bit are fully supported
LayeredFile document = { Enum::ColorMode::RGB, width, height };
// Create our individual channels to add to our image layer. Keep in mind that all these 3 channels need to
// be specified for RGB mode
std::unordered_map > channelMap;
channelMap[Enum::ChannelID::Red] = std::vector(width * height, 255u);
channelMap[Enum::ChannelID::Green] = std::vector(width * height, 0u);
channelMap[Enum::ChannelID::Blue] = std::vector(width * height, 0u);
ImageLayer::Params layerParams = {};
layerParams.name = "Layer Red";
layerParams.width = width;
layerParams.height = height;
layerParams.display_color = Enum::LayerColor::blue;
auto layer = std::make_shared>(std::move(channelMap), layerParams);
document.add_layer(layer);
// It is perfectly legal to modify a layers properties even after it was added to the document as attributes
// are only finalized on export
layer->opacity(.5);
// Convert to PhotoshopFile and write to disk. Note that from this point onwards
// our LayeredFile instance is no longer usable
LayeredFile::write(std::move(document), "WriteSimpleFile.psd");
}
```
--------------------------------
### Get Layer Height
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Retrieves the current layer height.
```cpp
inline virtual uint32_t height() const noexcept override
```
--------------------------------
### PhotoshopFile Constructor
Source: https://photoshopapi.readthedocs.io/en/latest/code/photoshopfile.html
Initializes a PhotoshopFile struct using the individual file sections.
```cpp
inline PhotoshopFile(FileHeader header, ColorModeData colorModeData, ImageResources &&imageResources, LayerAndMaskInformation &&layerMaskInfo, ImageData imageData)
```
--------------------------------
### Get Layer Width
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Retrieves the current layer width.
```cpp
inline virtual uint32_t width() const noexcept override
```
--------------------------------
### Initialize SmartObjectLayer from Filepath
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Initializes a SmartObject layer from a given filepath. It loads the file, decodes image data, and generates resampled data based on provided parameters. Requires LayeredFile for global state tracking.
```cpp
inline SmartObjectLayer(LayeredFile &file, Layer::Params ¶meters, std::filesystem::path filepath, LinkedLayerType linkage = LinkedLayerType::data)#
Initialize a SmartObject layer from a filepath.
This will internally load the given file (assuming it exists) into memory, decoding the full resolution image data as well as generating a resampled image data based on the resolution provided in the layers’ parameters (this may be zero in which case we will ignore the width and height and keep the original size). Requires the `LayeredFile` to be passed so we can keep track of this global state of linked layer data.
Parameters:
* **file** – The LayeredFile this SmartObject is to be associated with
* **parameters** – The Layers’ parameters
* **filepath** – The path of the file to load, this must be a file format Photoshop knows about and can decode. If `link_externally` is set to true it is highly recommended to keep this file local to the output directory. I.e. if the file gets written to `C:/PhotoshopFiles/file.psb` The file should be in `C:/PhotoshopFiles/` (same applies to linux). To learn more about how photoshop resolves these linkes head to this page: https://helpx.adobe.com/photoshop/using/create-smart-objects.html#linking_logic
* **linkage** – Whether to link the file externally (without saving it in the document). While this does reduce file size, due to linking limitations it is usually recommended to leave this at its default `false`. If the given file already exists on the `LayeredFile` e.g. when you link 2 layers with the same filepath the settings for the first layer are used instead of overriding the behaviour
```
--------------------------------
### Get Center X Coordinate
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Retrieves the x-coordinate of the layer center.
```cpp
inline virtual float center_x() const noexcept override
```
--------------------------------
### Manage Mask Position
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/image.html
Get or set the center position of the mask.
```cpp
inline Geometry::Point2D mask_position() const
```
```cpp
inline void mask_position(Geometry::Point2D position)
```
--------------------------------
### Create and Transform Smart Object Layer
Source: https://photoshopapi.readthedocs.io/en/latest/examples/smart_objects.html
Demonstrates creating a new external Smart Object layer, applying transformations (rotate, scale, move, perspective transform using matrix and homography), and resetting them. Requires OpenImageIO for image reading.
```python
import os
from typing import Union
import numpy as np
import cv2
import photoshopapi as psapi
def main() -> None:
# Reading the file works as normal, as well as accessing the layers.
layered_file = psapi.LayeredFile.read(os.path.join(os.path.dirname(__file__), "SmartObject.psd"))
warped_layer: psapi.SmartObjectLayer_8bit = layered_file["warped"]
# If we want to add an additional smart object layer we can do this just like you would with a normal layer.
# The only exception is that we have to provide a path for the image file we wish to link. We can additionally provide a warp
# object which will reapply the given warp to the new layer. This is convenient if you wish to create a copy of a layer without
# removing the other layer. These images are read using OpenImageIO so all of the file formats supported by it are supported
# here
layer_new = psapi.SmartObjectLayer_8bit(
layered_file,
path = os.path.join(os.path.dirname(__file__), "uv_grid.jpg"),
layer_name = "uv_grid",
link_type = psapi.enum.LinkedLayerType.external,
warp = warped_layer.warp
)
# Smart objects also have more freedom in their transformations which we expose in the API:
layer_new.rotate(45, layer_new.center_x, layer_new.center_y)
layer_new.scale(.65, .65, layer_new.center_x, layer_new.center_y)
layer_new.move(50, 50)
# We can additionally also apply a perspective transformation using a 3x3 projective matrix.
# This could also be used to skew or to directly apply all the above operations. This matrix e.g.
# applies a perspective transform where the vanishing point is at 2048, 0 (keeping in mind that 0
# in this case is at the top of the canvas).
# If you wish to know more about how these 3x3 transformation matrices work this is a great video/channel:
# https://www.youtube.com/watch?v=B8kMB6Hv2eI.
matrix = np.zeros((3, 3), dtype=np.double)
matrix[0][0] = 1
matrix[1][1] = 1
matrix[0][2] = 1 / 2048
matrix[2][2] = 1
layer_new.transform(matrix)
# If you want to be a bit more descriptive of how these matrices are to be built you can create one using a source
# and destination quad like this. Keep in mind that these have to be in the coordinate space of the image itself:
source_transform = psapi.geometry.create_quad(2048, 2048)
destination_transform = psapi.geometry.create_quad(2048, 2048)
# Squash together the top of the image
destination_transform[0].x = 512
destination_transform[1].x = 1536
# Create a 3x3 homography mapping the source_transform quad to the destination_transform quad.
homography = psapi.geometry.create_homography(source_transform, destination_transform)
layer_new.transform(homography)
# If now we wanted to clear the transformation and/or warp that could be done as well. This will now just
# be a smart object layer with width and height of 2048 (like the original image data).
layer_new.reset_transform()
layer_new.reset_warp()
# For modifying the warp directly (bezier) we can push the individual points, although this is a bit more
# advanced and we don't currently have a very convenient interface for it. This code right here
# pushes the top left corner to the 50, 50 position which will create a slightly rounded corner
warp_pts = layer_new.warp.points
warp_pts[0].x = 50
warp_pts[0].y = 50
layer_new.warp.points = warp_pts
# adding these works just as with any other layers, writing also works as usual
layered_file.add_layer(layer_new)
layered_file.write(os.path.join(os.path.dirname(__file__), "SmartObjectOut.psd"))
if __name__ == "__main__":
main()
```
--------------------------------
### Initialize BezierSurface
Source: https://photoshopapi.readthedocs.io/en/latest/code/geometry/bezier.html
Constructor for BezierSurface. Control points must be provided in scanline order. Optional x and y slices can be defined for non-uniform surfaces.
```cpp
inline BezierSurface(const std::vector> &controlPoints, size_t gridWidth, size_t gridHeight, std::optional> slices_x = std::nullopt, std::optional> slices_y = std::nullopt)
```
--------------------------------
### Get Filename
Source: https://photoshopapi.readthedocs.io/en/latest/code/util/linked_layer_data.html
Retrieves the filename associated with the LinkedLayerData. This function is noexcept.
```cpp
inline std::string filename() const noexcept#
Get the filename associated with the LinkedLayerData.
```
--------------------------------
### Access Clipping Mask
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Methods to get or set the clipping mask status.
```cpp
inline bool &clipping_mask() noexcept
```
```cpp
inline bool clipping_mask() const noexcept
```
```cpp
inline void clipping_mask(bool is_clipped) noexcept
```
--------------------------------
### Create and Modify Layered File (C++)
Source: https://photoshopapi.readthedocs.io/en/latest/examples/extended_signature.html
Demonstrates creating a LayeredFile using the extended signature in C++, allowing direct access to the PhotoshopFile structure. This method is more verbose than the preferred LayeredFile approach and is mainly for debugging or understanding parsing. It includes moving and removing layers within the file structure.
```C++
/*
This is the ModifyLayerStructure example but instead of using the simplified read and write signature we use the extend
one to give us direct access to the PhotoshopFile. This is a lot more verbose than the alternative presented in the other examples
The preferred method is always to interact through the LayeredFile
struct rather than directly with the low level PhotoshopAPI::PhotoshopFile although that is also possible but requires a deep understanding of the
underlying structure whereas LayeredFile abstracts the implementation details.
*/
#include "PhotoshopAPI.h"
#include
#include
int main()
{
using namespace NAMESPACE_PSAPI;
auto inputFile = File("./LayeredFile.psd");
auto psDocumentPtr = std::make_unique();
// The PhotoshopFile struct requires a progress callback to be passed which will be
// edited by the write function, to see an example of how to interact with this callback please refer
// to the "ProgressCallbacks" example
ProgressCallback callback{};
psDocumentPtr->read(inputFile, callback);
// In this case we already know the bit depth but otherwise one could use the PhotoshopFile.m_Header.m_Depth
// variable on the PhotoshopFile to figure it out programmatically
LayeredFile layeredFile = { std::move(psDocumentPtr), "./LayeredFile.psd" };
// The Structure of the photoshop file we just opened is
// 'Group'
// 'NestedGroup'
// 'NestedImageLayer'
// 'ImageLayer'
//
// and we now want to move the 'NestedGroup' and all of its children to the scene root
// as well as delete 'ImageLayer'. It is advised to do the restructuring in steps
// as shown below to avoid trying to access a layer which no longer exists
// By not specifying a second parameter to move_layer() we tell the function to move it to the scene root
// we could however also move it under another group by passing that group as a second parameter
layeredFile.move_layer("Group/NestedGroup");
layeredFile.remove_layer("Group/ImageLayer");
// This is the alternative signature which expects a layer ptr instead of a path.
// It is useful if we already have the layer ptr from another operation like extracting data and then want to move
// it etc.
/*
auto nestedGroupLayer = layeredFile.findLayer("Group/NestedGroup");
if (nestedGroupLayer)
{
layeredFile.moveLayer(nestedGroupLayer);
}
auto imageLayer = layeredFile.findLayer();
if (imageLayer)
{
layeredFile.removeLayer(imageLayer);
}
*/
// We can now convert back to a PhotoshopFile and write out to disk
File::FileParams params = File::FileParams();
params.doRead = false;
params.forceOverwrite = true;
auto outputFile = File("./RearrangedFile.psd", params);
auto psOutDocumentPtr = layered_to_photoshop(std::move(layeredFile), "./RearrangedFile.psd");
// We pass the same callback into the write function, clearing of data will
// be handled internally
psOutDocumentPtr->write(outputFile, callback);
}
```
--------------------------------
### Access Blend Mode
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Methods to get or set the layer blend mode.
```cpp
inline Enum::BlendMode &blendmode() noexcept
```
```cpp
inline Enum::BlendMode blendmode() const noexcept
```
```cpp
inline void blendmode(Enum::BlendMode blend_mode) noexcept
```
--------------------------------
### Rescale a LayeredFile in Python
Source: https://photoshopapi.readthedocs.io/en/latest/examples/rescale_canvas.html
Demonstrates reading a .psb file, iterating through layers to rescale image data and masks using OpenCV, and writing the modified file.
```python
# Example of replacing image data on a layer
import os
from typing import Union
import numpy as np
import cv2
import photoshopapi as psapi
def is_image_layer(layer: Union[psapi.Layer_8bit, psapi.Layer_16bit, psapi.Layer_32bit]) -> bool:
return isinstance(layer, (psapi.ImageLayer_8bit, psapi.ImageLayer_16bit, psapi.ImageLayer_32bit))
def scale_dimensions(layer: Union[psapi.Layer_8bit, psapi.Layer_16bit, psapi.Layer_32bit], scaling_factor: float) -> None:
"""
Apply the scaling factor to width, height, center_x and center_y of the layer
"""
layer.width *= scaling_factor
layer.height *= scaling_factor
layer.center_x *= scaling_factor
layer.center_y *= scaling_factor
def main() -> None:
layered_file = psapi.LayeredFile.read(os.path.join(os.path.dirname(__file__), "BaseFile.psb"))
# Scale up our canvas, this will not change any of the image data but only prepare it for later
scaling_factor = 2
layered_file.width *= scaling_factor
layered_file.height *= scaling_factor
# Loop over all the layers in the file and rescale them
# Note that we have to do it in the following order:
#
# - Extract the image data we want to process
# - Modify the layers' width and height properties
# - Set the Image data back on the channel
#
# The reason for this is that we internally use the layers' width and height to deduce and
# verify the numpy array's shape.
for layer in layered_file.flat_layers:
new_shape = (layer.width * scaling_factor, layer.height * scaling_factor)
if is_image_layer(layer):
image_data = layer.get_image_data()
scale_dimensions(layer, scaling_factor)
for index, channel in image_data.items():
rescaled_channel = cv2.resize(channel, new_shape, interpolation=cv2.INTER_LINEAR)
layer[index] = rescaled_channel
# As for image layers the image_data property will also return a mask channel we can safely
# apply the scaling here regardless
elif layer.has_mask():
mask = layer.mask
scale_dimensions(layer, scaling_factor)
layer.mask = cv2.resize(mask, new_shape, interpolation=cv2.INTER_LINEAR)
# We can now write the scaled file back out!
layered_file.write(os.path.join(os.path.dirname(__file__), "RescaledFile.psb"))
if __name__ == "__main__":
main()
```
--------------------------------
### Get Mask Default Color
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/image.html
Retrieves the default color value for the mask.
```cpp
inline uint8_t mask_default_color()
```
--------------------------------
### Read and Write Photoshop Files
Source: https://photoshopapi.readthedocs.io/en/latest/python/layeredfile.html
Demonstrates simple and extended methods for reading and writing Photoshop files using the LayeredFile interface.
```python
import photoshopapi as psapi
file_path = "Path/To/File.psb"
# This is a wrapper over the different LayeredFile_*bit types and will actually return the
# appropriate type depending on the file itself
layered_file = photoshopapi.LayeredFile.read(file_path)
# it is however important to note that the layered_file variable will be one of 3 types
# LayeredFile_8bit | LayeredFile_16bit | LayeredFile_32bit
# modify the layered_file...
layered_file.write("Path/To/Out.psb")
```
```python
import photoshopapi as psapi
file_path = "Path/To/File.psb"
bit_depth: photoshopapi.enum.BitDepth = photoshopapi.PhotoshopFile.find_bitdepth(file_path)
layered_file = None
if bit_depth == photoshopapi.enum.BitDepth.bd_8:
layered_file = photoshopapi.LayeredFile_8bit.read(file_path)
elif bit_depth == photoshopapi.enum.BitDepth.bd_16:
layered_file = photoshopapi.LayeredFile_16bit.read(file_path)
elif bit_depth == photoshopapi.enum.BitDepth.bd_32:
layered_file = photoshopapi.LayeredFile_32bit.read(file_path)
if not layered_file:
raise RuntimeError("Unable to deduce LayeredFile bit-depth")
# modify the layered_file...
layered_file.write("Path/To/Out.psb")
```
--------------------------------
### Create Text Layer in C++
Source: https://photoshopapi.readthedocs.io/en/latest/concepts/text-layers.html
Use `TextLayer::create` to initialize a new text layer with specified properties. Ensure you are within the `NAMESPACE_PSAPI` namespace.
```cpp
using namespace NAMESPACE_PSAPI;
LayeredFile doc = { Enum::ColorMode::RGB, 1200u, 1800u };
auto layer = TextLayer::create(
"Caption",
"Hello\nWorld",
"ArialMT",
36.0,
{1.0, 0.0, 0.0, 0.0}, // [A, R, G, B]
120.0, 160.0,
600.0, 260.0
);
doc.add_layer(layer);
```
--------------------------------
### Get Channel Metadata
Source: https://photoshopapi.readthedocs.io/en/latest/code/photoshopsections/layerandmaskinformation.html
Retrieves offsets, sizes, and compression information for channels.
```cpp
inline std::vector> getChannelOffsetsAndSizes() const noexcept
```
```cpp
inline Enum::Compression getChannelCompression(int index) const noexcept
```
--------------------------------
### SmartObjectLayer Initialization
Source: https://photoshopapi.readthedocs.io/en/latest/python/layers/smart_object.html
Constructs a SmartObjectLayer from a given filepath, allowing for linked layers with various optional parameters for masks, blend modes, and visibility.
```APIDOC
## SmartObjectLayer Constructor
### Description
Construct a SmartObjectLayer from the given filepath, linking the layer according to the link type. Accepts an optional warp object to construct the layer with. If None is passed we default initialize the warp.
### Method
__init__
### Parameters
#### Path Parameters
* **layered_file** (_LayeredFile_*bit_) – The file into which the layer will be inserted. This needs to be present as the actual link to the image file is stored globally and not on the layer itself.
* **path** (_str_) – The path to the image file to link into this SmartObject. This must be a valid file on disk.
* **layer_name** (_str_) – The name of the group, its length must not exceed 255
* **layer_mask** (_numpy.ndarray_) – Optional layer mask, must have the same dimensions as height * width as a 2-dimensional array with row-major ordering (for a numpy 2D array this would mean with a shape of (height, width)
* **blend_mode** (_psapi.enum.BlendMode_) – Optional, the blend mode of the layer, ‘Passthrough’ is the default for groups.
* **opacity** (_int_) – The opacity of the layer from 0-255 where 0 is 0% and 255 is 100%. Defaults to 255
* **compression** (_psapi.enum.Compression_) – The compression to apply to all the channels of the layer, including mask channels
* **color_mode** (_psapi.enum.ColorMode_) – The color mode of the Layer, this must be identical to the color mode of the document. Defaults to RGB
* **is_visible** (_bool_) – Whether the group is visible
* **is_locked** (_bool_) – Whether the group is locked
### Raises
ValueError: if length of layer name is greater than 255
ValueError: if opacity is not between 0-255
```
--------------------------------
### Get Channel Index
Source: https://photoshopapi.readthedocs.io/en/latest/code/photoshopsections/layerandmaskinformation.html
Retrieves the index of a specific channel based on its identifier.
```cpp
inline int getChannelIndex(Enum::ChannelID channelID) const
```
```cpp
inline int getChannelIndex(Enum::ChannelIDInfo channelIDInfo) const
```
--------------------------------
### Get File Section Offset
Source: https://photoshopapi.readthedocs.io/en/latest/code/photoshopsections/layerandmaskinformation.html
Retrieves the offset of the FileSection. Marked as noexcept.
```cpp
inline size_t offset() const noexcept
```
--------------------------------
### PhotoshopFile.write()
Source: https://photoshopapi.readthedocs.io/en/latest/python/photoshopfile.html
Writes the PhotoshopFile class to disk using an instance. The provided file must be a valid .psd or .psb file.
```APIDOC
## PhotoshopFile.write()
### Description
Write the PhotoshopFile class to disk using a instance, this file must be a valid .psd or .psb file.
### Method
Instance method
### Endpoint
N/A (Instance method)
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
- **document** (psapi.util.File) - Required - The file object used for writing.
### Request Example
```python
# Assuming 'file_obj' is an instance of psapi.util.File
photoshop_file.write(file_obj)
```
### Response
#### Success Response (200)
None (This method writes to the provided file object)
#### Response Example
None
```
--------------------------------
### Layer Display Color
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Allows getting and setting the display color of a layer in the GUI.
```APIDOC
## Layer Display Color
### Description
Manages the display color of a layer as shown in the graphical user interface.
### Method
`Enum::LayerColor display_color() const noexcept` (getter)
`void display_color(const Enum::LayerColor color) noexcept` (setter)
### Parameters (for setter)
#### Request Body
- **color** (Enum::LayerColor) - Required - The desired display color for the layer.
```
--------------------------------
### Initialize ImageData with Channels
Source: https://photoshopapi.readthedocs.io/en/latest/code/photoshopsections/imagedata.html
Initializes the ImageData with a specified number of channels. This is done instead of deducting from the header because the header counts alpha channels while this structure does not.
```cpp
inline ImageData(uint16_t numChannels)#
```
--------------------------------
### Access Locked State
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Methods to get or set the pixel lock status of the layer.
```cpp
inline bool &locked() noexcept
```
```cpp
inline bool locked() const noexcept
```
```cpp
inline void locked(bool is_locked) noexcept
```
--------------------------------
### Initialize SmartObjectLayer with Warp from Filepath
Source: https://photoshopapi.readthedocs.io/en/latest/code/layers/smartobject.html
Initializes a SmartObject layer from a filepath, including a specified warp transformation. Loads file data, decodes images, and generates resampled data. Requires LayeredFile for state tracking.
```cpp
inline SmartObjectLayer(LayeredFile &file, Layer::Params ¶meters, std::filesystem::path filepath, const SmartObject::Warp &warp, LinkedLayerType linkage = LinkedLayerType::data)#
Initialize a SmartObject layer from a filepath.
This will internally load the given file (assuming it exists) into memory, decoding the full resolution image data as well as generating a resampled image data based on the resolution provided in the layers’ parameters (this may be zero in which case we will ignore the width and height and keep the original size). Requires the `LayeredFile` to be passed so we can keep track of this global state of linked layer data.
Parameters:
* **file** – The LayeredFile this SmartObject is to be associated with
* **parameters** – The Layers’ parameters
* **filepath** – The path of the file to load, this must be a file format Photoshop knows about and can decode. If `link_externally` is set to true it is highly recommended to keep this file local to the output directory. I.e. if the file gets written to `C:/PhotoshopFiles/file.psb` The file should be in `C:/PhotoshopFiles/` (same applies to linux). To learn more about how photoshop resolves these linkes head to this page: https://helpx.adobe.com/photoshop/using/create-smart-objects.html#linking_logic
* **warp** – The warp to apply to the image data, this may be default generated warp which can be modified later on by retrieving it using `warp()`. After then modifying it, the updated warp will be lazily evaluated on write or access. So you may modify it as many times as you want but only retrieving it will call the evaluation. If you wish to skip this you can pass `SmartObject::Warp::generate_default(width, height)` or use the alternative ctor without `warp` argument
* **linkage** – Whether to link the file externally (without saving it in the document). While this does reduce file size, due to linking limitations it is usually recommended to leave this at its default `false`. If the given file already exists on the `LayeredFile` e.g. when you link 2 layers with the same filepath the settings for the first layer are used instead of overriding the behaviour
```
--------------------------------
### Extract and Insert Layer with Python
Source: https://photoshopapi.readthedocs.io/en/latest/python/bindings.html
Demonstrates reading a 16-bit PSB file, converting a layer to 8-bit, and inserting it into an 8-bit PSD file. Requires the PhotoshopAPI package and NumPy.
```python
import photoshopapi as psapi
import numpy as np
import os
def main():
# Read both our files, they can be open at the same time or we can also read one file,
# extract the layer and return just that layer if we want to save on RAM.
file_src = psapi.LayeredFile.read("GraftSource_16.psb")
file_dest = psapi.LayeredFile.read("GraftDestination_8.psd")
# Extract the image data and convert to 8-bit.
lr_src: psapi.ImageLayer_16bit = file_src["GraftSource"]
img_data_src = lr_src.get_image_data()
img_data_8bit = {}
for key, value in img_data_src.items():
value = value / 256 # Convert from 0-65535 -> 0-255
img_data_8bit[key] = value.astype(np.uint8)
# Reconstruct an 8bit converted layer
img_layer_8bit = psapi.ImageLayer_8bit(
img_data_8bit,
layer_name=lr_src.name,
width=lr_src.width,
height=lr_src.height,
blend_mode=lr_src.blend_mode,
opacity=lr_src.opacity
)
# add the layer and write out to file!
file_dest.add_layer(img_layer_8bit)
file_dest.write("GraftDestination_8_Edited.psd")
if __name__ == "__main__":
main()
```