Structure Description: LayeredFile#

The LayeredFile struct is the primary interface for editing Photoshop Files. It creates an abstraction over the actual implementation and provides more high level control over the Photoshop binary file format. It makes modifying a layer structure very convenient and as we are just shuffling pointers around internally also very efficient

Usage#

The code snippets below show some examples of how one would generally use a LayeredFile. For more detailed examples please visit the PhotoshopExamples/ directory on the github page

Read from disk and modify#
using namespace NAMESPACE_PSAPI;

LayeredFile<bpp16_t> layeredFile = LayeredFile<bpp16_t>::read("InFile.psd");

// Move a layer one level up in the hierarchy
layeredFile.moveLayer("Group/NestedGroup/Image", "Group");

// Delete the now empty group from the document
layeredFile.removeLayer("Group/NestedGroup");

// We can now convert the LayeredFile to a PhotoshopFile and write it out (this is done internally
// but can be exposed, see the ExtendedSignature example for more information)
LayeredFile<bpp16_t>::write(std::move(layeredFile), "OutFile.psd");
Initialize, modify and write#
using namespace PhotoshopAPI;

const static uint32_t width = 64u;
const static uint32_t height = 64u;

LayeredFile<bpp8_t> 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 <Enum::ChannelID, std::vector<bpp8_t>> channelMap;
channelMap[Enum::ChannelID::Red] = std::vector<bpp8_t>(width * height, 255u);
channelMap[Enum::ChannelID::Green] = std::vector<bpp8_t>(width * height, 0u);
channelMap[Enum::ChannelID::Blue] = std::vector<bpp8_t>(width * height, 0u);

ImageLayer<bpp8_t>::Params layerParams = {};
layerParams.layerName = "Layer Red";
layerParams.width = width;
layerParams.height = height;

auto layer = std::make_shared<ImageLayer<bpp8_t>>(std::move(channelMap), layerParams);
document.addLayer(layer);

LayeredFile<bpp8_t>::write(std::move(layeredFile), "OutFile.psd");

Layer Type Derivatives#

Below you can find a list of layers that one is able to add to the LayeredFile instance. Keep in mind that some of these are not fully implemented yet

Conversion Functions#

template<typename T>
std::unique_ptr<PhotoshopFile> LayeredToPhotoshopFile(LayeredFile<T> &&layeredFile)#

Converts a layeredFile into a PhotoshopFile, taking ownership of and invalidating any data.

Note

This will not fill any specific TaggedBlocks or ResourceBlocks beyond what is required to create the layer structure.


Find Layer as specific type#

template<typename T, template<typename X> class LayerType>
std::shared_ptr<LayerType<T>> findLayerAs(const std::string path, const LayeredFile<T> &layeredFile)#

Finds a layer based on the given path and casts it to the given type.

This function matches LayeredFile<T>::findLayer() but instead of returning a generic layer basetype we return the requested type (if the cast is valid), this is especially useful if the layer type is known ahead of time and is the preferred way of accessing a layer.

Example call:

LayeredFile<bpp8_t> layeredFile{};  // We assume this is already populated
auto imageLayerPtr = findLayerAs<bpp8_t, ImageLayer>("Path/To/ImageLayer", layeredFile);

The path should be separated by forward slashes, e.g., “Group1/GroupNested/ImageLayer”. Returns a reference to the specific layer if found; otherwise, returns nullptr and issues a warning. If we cannot upcast to the specified ptr a warning is raised and nullptr is returned.

Parameters:
  • path – The path to the layer.

  • layeredFile – the file to search from

Returns:

A shared pointer to the found layer or nullptr.


ICC Profile Struct#

struct ICCProfile#

Helper Structure for loading an ICC profile from memory of disk. Photoshop will then store the raw bytes of the ICC profile in their ICCProfile ResourceBlock (ID 1039)

Public Functions

inline ICCProfile()#

Initialize an empty ICCProfile.

inline ICCProfile(std::vector<uint8_t> data)#

Initialize the ICCProfile by passing in a raw byte array of an ICC profile.

ICCProfile(const std::filesystem::path &pathToICCFile)#

Initialize the ICCProfile by loading the path contents from disk.

inline std::vector<uint8_t> getData() const noexcept#

Return a copy of the ICC profile data.

inline uint32_t getDataSize() const noexcept#

Return the absolute size of the data.


LayeredFile Struct#

template<typename T>
struct LayeredFile#

Represents a layered file structure.

This struct defines a layered file structure, where each file contains a hierarchy of layers. Layers can be grouped and organized within this structure.

Template Parameters:

T – The data type used for pixel values in layers (e.g., uint8_t, uint16_t, float32_t).

Public Functions

inline LayeredFile(std::unique_ptr<PhotoshopFile> file)#

Constructs a LayeredFile instance from a Photoshop file.

Takes ownership of the provided Photoshop file, transferring from a flat layer hierarchy to a layered file using the lrSectionDivider taggedBlock to identify layer breaks.

Parameters:

file – The PhotoshopFile to transfer

inline LayeredFile(Enum::ColorMode colorMode, uint64_t width, uint64_t height)#
requires std

Constructs an empty LayeredFile object.

Creates a LayeredFile with the specified color mode, width, and height.

Finds a layer based on the given path. The path should be separated by forward slashes, e.g., “Group1/GroupNested/ImageLayer”. Returns a reference to the specific layer if found; otherwise, returns nullptr and issues a warning.

Inserts a layer into the root of the layered file.

If you wish to add a layer to a group, use GroupLayer::addLayer() on a group node retrieved by \ref findLayer().

\param layer The layer to be added.

Parameters:
  • colorMode – The color mode of the file.

  • width – The width of the file in pixels.

  • height – The height of the file in pixels.

  • path – The path to the layer.

Returns:

A shared pointer to the found layer or nullptr.

inline void moveLayer(std::shared_ptr<Layer<T>> layer, std::shared_ptr<Layer<T>> parentLayer = nullptr)#

Moves a layer from its current parent to a new parent node.

If no parentLayer is provided, moves the layer to the root. If the parentLayer is found to be under the layer it will issue a warning and stop the insertion. I.e. if moving “/Group” to “/Group/GroupNested/” that would be an illegal move operation as well as moving a layer to itself

Parameters:
  • layer – The layer to be moved.

  • parentLayer – The new parent layer (if not provided, moves to the root).

inline void moveLayer(const std::string layer, const std::string parentLayer = "")#

Moves a layer from its current parent to a new parent node.

If no parentLayer is provided, moves the layer to the root. If the parentLayer is found to be under the layer it will issue a warning and stop the insertion. I.e. if moving “/Group” to “/Group/GroupNested/” that would be an illegal move operation as well as moving a layer to itself

Parameters:
  • layer – The layer to be moved.

  • parentLayer – The new parent layer (if not provided, moves to the root).

inline void removeLayer(std::shared_ptr<Layer<T>> layer)#

Recursively removes a layer from the layer structure.

Iterates the layer structure until the given node is found and then removes it from the tree.

Parameters:

layer – The layer to be removed.

inline void removeLayer(const std::string layer)#

Recursively removes a layer from the layer structure.

Iterates the layer structure until the given node is found and then removes it from the tree.

Parameters:

layer – The layer to be removed.

inline void setCompression(const Enum::Compression compCode)#

change the compression codec across all layers and channels

Iterates the layer structure and changes the compression codec for write on all layers. This is especially useful for e.g. 8-bit files which from Photoshop write with RLE compression but ZipCompression gives us better ratios

Parameters:

compCode – the compression codec to apply

inline std::vector<std::shared_ptr<Layer<T>>> generateFlatLayers(std::optional<std::shared_ptr<Layer<T>>> layer, const LayerOrder order) const#

Generate a flat layer stack from either the current root or (if supplied) from the given layer. It should be preferred to use flatLayers() instead of this function.

Parameters:
  • layer – Optional layer to start the generation from (default is root). If you provide e.g. a group this will only build the below layer tree

  • order – The order in which layers should be stacked.

Returns:

The flat layer tree with automatic SectionDividerLayer inserted to mark section ends

inline std::vector<std::shared_ptr<Layer<T>>> flatLayers()#

Get a view over the flattened layer stack, helpful for iterating and applying properties to all layers such as visibility overrides etc.

After any layer modification actions this list may no longer be up-to-date so it would have to be re-generated. It is highly discouraged to use this flattened layer vector for any layer hierarchy modifications

Returns:

The layer hierarchy as a flattened vector that can be iterated over.

inline uint16_t getNumChannels(bool ignoreMaskChannels = true, bool ignoreAlphaChannel = true)#

Gets the total number of channels in the document.

Excludes mask channels unless ignoreMaskChannels is set to false. Same goes for ignoreAlphaChannel

Parameters:
  • ignoreMaskChannels – Flag to exclude mask channels from the count.

  • ignoreAlphaChannel – Flag to exclude the transparency alpha channel from the count.

Returns:

The total number of channels in the document.

inline bool isLayerInDocument(const std::shared_ptr<Layer<T>> layer) const#

Checks if a layer already exists in the nested structure.

Parameters:

layer – The layer to check for existence.

Returns:

True if the layer exists, false otherwise.

Public Members

std::vector<std::shared_ptr<Layer<T>>> m_Layers#

The root layers in the file, they may contain multiple levels of sub-layers.

ICCProfile m_ICCProfile#

The ICC Profile associated with the file, this may be empty in which case there will be no colour profile associated with the file

float m_DotsPerInch = 72.0f#

The DPI of the document, this will only change the display unit and wont resize any data.

Enum::BitDepth m_BitDepth = Enum::BitDepth::BD_8#

The bit depth of the file.

Enum::ColorMode m_ColorMode = Enum::ColorMode::RGB#

The color mode of the file. Currently supports RGB only.

uint64_t m_Width = 1u#

The width of the file in pixels. Can be up to 30,000 for PSD and up to 300,000 for PSB.

uint64_t m_Height = 1u#

The height of the file in pixels. Can be up to 30,000 for PSD and up to 300,000 for PSB.

Public Static Functions

static inline LayeredFile<T> read(const std::filesystem::path &filePath, ProgressCallback &callback)#

read and create a LayeredFile from disk

Simplify the creation of a LayeredFile by abstracting away the step of PhotoshopFile -> LayeredFile doing the work internally without exposing the PhotoshopFile instance to the user

Parameters:
  • filePath – the path on disk of the file to be read

  • callback – the callback which reports back the current progress and task to the user

static inline LayeredFile<T> read(const std::filesystem::path &filePath)#

read and create a LayeredFile from disk

Simplify the creation of a LayeredFile by abstracting away the step of PhotoshopFile -> LayeredFile doing the work internally without exposing the PhotoshopFile instance to the user

Parameters:

filePath – the path on disk of the file to be read

static inline void write(LayeredFile<T> &&layeredFile, const std::filesystem::path &filePath, ProgressCallback &callback, const bool forceOvewrite = true)#

write the LayeredFile instance to disk, consumes and invalidates the instance

Simplify the writing of a LayeredFile by abstracting away the step of LayeredFile -> PhotoshopFile doing the work internally without exposing the PhotoshopFile instance to the user

Parameters:
  • layeredFile – The LayeredFile to consume, invalidates it

  • filePath – The path on disk of the file to be written

  • callback – the callback which reports back the current progress and task to the user

  • forceOvewrite – Whether to forcefully overwrite the file or fail if the file already exists

static inline void write(LayeredFile<T> &&layeredFile, const std::filesystem::path &filePath, const bool forceOvewrite = true)#

write the LayeredFile instance to disk, consumes and invalidates the instance

Simplify the writing of a LayeredFile by abstracting away the step of LayeredFile -> PhotoshopFile doing the work internally without exposing the PhotoshopFile instance to the user

Parameters:
  • layeredFile – The LayeredFile to consume, invalidates it

  • filePath – The path on disk of the file to be written

  • forceOvewrite – Whether to forcefully overwrite the file or fail if the file already exists


Layer Order Enum#

enum class LayerOrder#

Enumerator to specify the order of traversal for parsing.

Values:

enumerator forward#

Forward in this case refers to us going top to bottom. e.g. if we have the layer structure

Group
  NestedGroup
  Image
We would write out the layers starting with ‘Group’

enumerator reverse#

Reverse in this case refers to us going bottom to top. e.g. if we have the layer structure

Group
  NestedGroup
  Image
We would write out the layers starting with ‘Image’