SmartObjectLayer#
Class Reference SmartObjectLayer#
- class photoshopapi.SmartObjectLayer_8bit#
Smart objects are Photoshops’ way of non-destructive image data edits while keeping a live link to the original file.
We expose not only ways to replace this linked image data but also have functionality to recreate and store the warps applied to these objects (with more features coming in the future). We currently support recreating all the warps found in the Edit->Transform tab. We do not yet support the Edit->Puppet Warp and Edit->Perspective Warp which are stored as Smart Filters.
Smart objects store their original image data on the LayeredFile while storing a decoded preview the size of the layer on the layer itself. We provide multiple methods to get both the scaled and warped image data as well as the full size image data.
<b>Image Data:</b>
Due to how SmartObjects work, image data is read-only. In order to modify the underlying image data you should use the replace() method which will actually replace the underlying file the smart object is linked to.
Getting the image data can be done via the get_image_data(), get_channel_by_id(), get_channel_by_index() and get_original_image_data() functions. These will retrieve the transformed and warped image data. If you modify the transformations or the warp the warp is only redrawn on access to these functions.
<b>Transformations:</b>
Unlike normal layers, SmartObjects have slightly different transformation rules. As they link back to a file in memory or on disk the transformations are stored ‘live’ and can be modified without negatively impacting the quality of the image. We expose a variety of transformation options to allow you to express this freedom.
Since we have both the original image data, and the rescaled image data to worry about there is two different widths and heights available:
- original_width() / original_height()
These represent the resolution of the original file image data, irrespective of what transforms are applied to it. If you are e.g. loading a 4000x2000 jpeg these will return 4000 and 2000 respectively. These values may not be written to
- width() / height()
These represent the final dimensions of the SmartObject with the warp and any transformations applied to it.
For actually transforming the layer we expose the following methods:
move()
rotate()
scale()
transform()
These are all individually documented and abstract away the underlying implementation of these operations. You likely will not have to dive deeper than these.
<b>Warp:</b>
Smart objects can also store warps which we implement using the SmartObjectWarp structure. These warps are stored as bezier surfaces with transformations applied on top of them. The transformations should be disregarded by the user as we provide easier functions on the SmartObjectLayer directly (see above). You may transfer these warps from one layer to another, modify them (although this requires knowledge of how bezier surfaces work), or clear them entirely.
For the latter we provide the reset_transform()` and reset_warp() functions.
- Attributes:
- warpSmartObjectWarp
Property holding the warp (and transformation) information. May be modified, although for transforming the layer it is recommended to use the transformation functions such as move, rotate, scale and transform.
- linkagepsapi.enum.LinkedLayerType
The linkage of the backing image file, if this is set to psapi.enum.LinkedLayerType.data the image is stored in the file while if it is set to psapi.enum.LinkedLayerType.external it links to the file on disk and only stores the transformed image on file.
- namestr
The name of the layer, cannot be longer than 255
- blend_modeenum.BlendMode
The blend mode of the layer, ‘Passthrough’ is reserved for group layers
- opacityfloat
The layers opacity from 0.0 - 1.0
- widthint
The width of the layer ranging up to 30,000 for PSD and 300,000 for PSB, this does not have to match the files width
- heightint
The height of the layer ranging up to 30,000 for PSD and 300,000 for PSB, this does not have to match the files height
- center_xfloat
The center of the layer in regards to the canvas, a layer at center_x = 0 is perfectly centered around the document
- center_yfloat
The center of the layer in regards to the canvas, a layer at center_y = 0 is perfectly centered around the document
- is_locked: bool
The locked state of the layer, this locks all pixel channels
- is_visible: bool
Whether the layer is visible
- clipping_mask: bool
Whether the layer is clipped to the one below.
- mask: np.ndarray
The layers’ mask channel, may be empty
- mask_disabled: bool
Whether the mask is disabled. Ignored if no mask is present
- mask_relative_to_layer: bool
Whether the masks position is relative to the layer. Ignored if no mask is present
- mask_default_color: int
The masks’ default color outside of the masks bounding box from 0-255. Ignored if no mask is present
- mask_density: int
Optional mask density from 0-255, this is equivalent to layers’ opacity. Ignored if no mask is present
- mask_feather: float
Optional mask feather. Ignored if no mask is present
- mask_position: psapi.geometry.Point2D
The masks’ canvas coordinates, these represent the center of the mask in terms of the canvas (file). Ignored if no mask is present
- mask_width: int
The masks’ width, this does not have to correspond with the layers’ width
- mask_height: int
The masks’ height, this does not have to correspond with the layers’ height
- __init__(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit, layered_file: photoshopapi.lib64.photoshopapi.LayeredFile_8bit, path: str, layer_name: str, link_type: photoshopapi.lib64.photoshopapi.enum.LinkedLayerType = <LinkedLayerType.data: 0>, warp: Optional[PhotoshopAPI::SmartObject::Warp] = None, layer_mask: Optional[numpy.ndarray[numpy.uint8]] = None, blend_mode: photoshopapi.lib64.photoshopapi.enum.BlendMode = <BlendMode.normal: 1>, opacity: float = 1.0, compression: photoshopapi.lib64.photoshopapi.enum.Compression = <Compression.zipprediction: 3>, color_mode: photoshopapi.lib64.photoshopapi.enum.ColorMode = <ColorMode.rgb: 3>, is_visible: bool = True, is_locked: bool = False) None#
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.
- 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
- __getitem__(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit, key: int) numpy.ndarray[numpy.uint8]#
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.
- raises ValueError:
if the specified index does not exist on the layer
- Returns:
The extracted channel
- Return type:
numpy.ndarray
- channel_indices(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit, include_mask: bool = True) List[int]#
Retrieve a list of all the channel indices.
- param include_mask:
Whether to include the mask channel
- filename(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit) str#
Retrieve the filename associated with this smart object.
- filepath(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit) os.PathLike#
- Retrieve the filepath associated with this smart object. Depending on how the
Smart object is linked (external or data) this may not be written to disk.
If the file is linked as data this path may not represent the actual filepath on disk as this information is no longer present.
- get_channel_by_id(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit, key: photoshopapi.lib64.photoshopapi.enum.ChannelID) numpy.ndarray[numpy.uint8]#
- 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.
- param psapi.enum.ColorMode key:
The key to access.
- raises ValueError:
if the specified index does not exist on the layer
- Returns:
The extracted channel
- Return type:
numpy.ndarray
- get_channel_by_index(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit, key: int) numpy.ndarray[numpy.uint8]#
- 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.
- param int:
The key to access.
- raises ValueError:
if the specified index does not exist on the layer
- Returns:
The extracted channel
- Return type:
numpy.ndarray
- get_image_data(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit) Dict[int, numpy.ndarray[numpy.uint8]]#
- Get all the channels of the layer (including masks) as a dict mapped by intnp.ndarray. This includes
any mask channel which would be found at index -2. While all non-mask channels are guaranteed to be the same size as width() * height() this does not hold true for the mask channel which would be the size of mask_width() and mask_height()
- Returns:
The extracted image data
- Return type:
dict[int, numpy.ndarray]
- get_original_image_data(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit) Dict[int, numpy.ndarray[numpy.uint8]]#
Extract all the channels of the original image data.
Unlike the accessors get_image_data() and get_channel() this function gets the full resolution image data that is stored on the smart object, i.e. the original image data. This may be smaller or larger than the layers width or height. To get the actual resolution you can query: original_width() and original_height()
- has_mask(self: photoshopapi.lib64.photoshopapi.Layer_8bit) bool#
Check whether the layer has an associated mask component (pixel mask)
- hash(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit) str#
- Retrieve the hashed value associated with the layer, this is what is used to identify the
linked layer associated with this smart object (where the original image data is stored)
- property mask#
The layers’ pixel mask, this is a 2-dimensional array stored in format { height, width }. A pixel mask may have any dimensions and does not have to match a layers’ width or height. To get the pixel value outside of the masks’ bbox use the mask_default_color property.
- property mask_default_color#
The masks’ default color outside of the masks bounding box. Ignored if no mask is present. From 0-255 regardless of bit depth
- property mask_density#
Optional mask density from 0-255, this is equivalent to layers’ opacity. Ignored if no mask is present
- property mask_disabled#
Whether the mask is disabled. Ignored if no mask is present
- property mask_feather#
Optional mask feather. Ignored if no mask is present
- mask_height(self: photoshopapi.lib64.photoshopapi.Layer_8bit) int#
The masks’ height in pixels. This does not always have to correspond with the layers’ height.
- property mask_position#
The masks’ canvas coordinates, these represent the center of the mask in terms of the canvas (file). Ignored if no mask is present
- property mask_relative_to_layer#
Whether the masks position is relative to the layer. Ignored if no mask is present
- mask_width(self: photoshopapi.lib64.photoshopapi.Layer_8bit) int#
The masks’ width in pixels. This does not always have to correspond with the layers’ width.
- move(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit, x_offset: float, y_offset: float) None#
Move the layer (including any warps) by the given x and y offset.
- num_channels(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit, include_mask: bool = True) int#
Retrieve the total number of channels held by the layer
- param include_mask:
Whether to include the mask channel
- original_height(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit) int#
Retrieve the original image datas’ height.
This does not have the same limitation as Photoshop layers of being limited to 30,000 or 300,000 pixels depending on the file type
- raises RuntimeError:
if the hash defined by hash() is not valid for the document
- returns:
The height of the original image data
- original_width(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit) int#
Retrieve the original image datas’ width.
This does not have the same limitation as Photoshop layers of being limited to 30,000 or 300,000 pixels depending on the file type
- raises RuntimeError:
if the hash defined by hash() is not valid for the document
- returns:
The width of the original image data
- replace(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit, path: str, link_externally: bool = False) None#
Replace the smart object with the given path keeping transformations as well as warp in place.
- Parameters:
path – The new filepath to link to, this must be a file format recognized both by Photoshop and OpenImageIO
link_externally –
- Whether to link the file externally or store the raw file bytes on the
photoshop document itself. Keeping this at its default False is recommended for sharing these files. If the file already exists as another smart object layer
this parameter is ignored.
- reset_transform(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit) None#
- Reset all the transformations (not the warp) applied to the layer to map it back to the original square
from [0 - original_width()] and [0 - original_height()]. This does not reset the warp itself so if
you had a warp applied it will stay.
If you instead wish to clear the warp you can use reset_warp().
These two may be used in combination and sequence, so it is perfectly valid to call reset_transform and reset_warp in any order.
- reset_warp(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit) None#
Reset the warp (not the transformations) applied to the Smart Object.
If you instead wish to clear the transformations you can use the reset_transform() function.
These two may be used in combination and sequence, so it is perfectly valid to call reset_transform and reset_warp in any order
- rotate(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit, angles: float, x: float, y: float) None#
Rotate the layer (including any warps) by the given angle (in degrees) around the point defined by the x and y coordinate. If you wish to rotate around the layers center you can call the function as follows:
layer.rotate(45, layer.center_x, layer.center_y)
- Parameters:
angle – The angle to rotate with in degrees
x – The x position to rotate about
y – The y position to rotate about
- scale(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit, x_scalar: float, y_scalar: float, x: float, y: float) None#
Scale the layer (including any warps) by the given x and y scalar around the point defined by the x and y coordinate. If you wish to scale around the layers center you can call the function as follows:
layer.scale(1.0, 1.0, layer.center_x, layer.center_y)
- Parameters:
x_scalar – The x component of the scalar
y_scalar – The y component of the scalar
x – The x position to scale about
y – The y position to scale about
- set_mask_compression(self: photoshopapi.lib64.photoshopapi.Layer_8bit, arg0: photoshopapi.lib64.photoshopapi.enum.Compression) None#
Set the masks’ write compression in terms of one of the Photoshop compression codecs. The mask channel may have any compression codec applied to it and this does not need to match the layers’ compression in any way. All compression codecs are valid in the PhotoshopAPI.
- transform(self: photoshopapi.lib64.photoshopapi.SmartObjectLayer_8bit, matrix: numpy.ndarray[numpy.float64]) None#
Apply the transformation matrix to the smart object layer. This must be a 3x3 matrix which can contain both affine and non affine transformations.
- Parameters:
matrix (np.ndarray) – The matrix to transform by, as a 3x3 matrix of np.double