Skip to content

Document

src.helpers.document.get_leaf_layers(group: Optional[LayerSet] = None) -> list[ArtLayer]

Utility function to generate a list of leaf layers in a LayerSet or document.

Parameters:

Name Type Description Default
group LayerSet | None

Group to grab leaf layers from.

None

Returns:

Type Description
list[ArtLayer]

A list of leaf layers in a LayerSet or document.

Source code in src\helpers\document.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
def get_leaf_layers(group: Optional[LayerSet] = None) -> list[ArtLayer]:
    """Utility function to generate a list of leaf layers in a LayerSet or document.

    Args:
        group: Group to grab leaf layers from.

    Returns:
        A list of leaf layers in a LayerSet or document.
    """
    if not group:
        group = APP.activeDocument
    layers = [node for node in group.artLayers]
    for g in group.layerSets:
        layers.extend(get_leaf_layers(g))
    return layers

src.helpers.document.get_layer_tree(group: Optional[LayerSet] = None) -> dict[str, Union[ArtLayer, dict[str, ArtLayer]]]

Composes a dictionary tree of layers in the active document or a specific LayerSet.

Parameters:

Name Type Description Default
group LayerSet | None

A specific group to create a dictionary tree for.

None

Returns:

Type Description
dict[str, ArtLayer | dict[str, ArtLayer]]

A dictionary tree comprised of all the layers in a document or group.

Source code in src\helpers\document.py
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
def get_layer_tree(group: Optional[LayerSet] = None) -> dict[str, Union[ArtLayer, dict[str, ArtLayer]]]:
    """Composes a dictionary tree of layers in the active document or a specific LayerSet.

    Args:
        group: A specific group to create a dictionary tree for.

    Returns:
        A dictionary tree comprised of all the layers in a document or group.
    """
    if not group:
        group = APP.activeDocument
    layers = {layer.name: layer for layer in group.artLayers}
    for g in group.layerSets:
        layers[g.name] = get_layer_tree(g)
    return layers

src.helpers.document.import_art(layer: ArtLayer, path: Union[str, Path], name: str = 'Layer 1', docref: Optional[Document] = None) -> ArtLayer

Imports an art file into the active layer.

Parameters:

Name Type Description Default
layer ArtLayer

Layer to make active and receive image.

required
path str | Path

Image file to import.

required
name str

Name of the new layer.

'Layer 1'
docref Document | None

Reference document if provided, otherwise use active.

None

Returns:

Type Description
ArtLayer

Imported art layer.

Source code in src\helpers\document.py
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
def import_art(
    layer: ArtLayer,
    path: Union[str, Path],
    name: str = 'Layer 1',
    docref: Optional[Document] = None
) -> ArtLayer:
    """Imports an art file into the active layer.

    Args:
        layer: Layer to make active and receive image.
        path: Image file to import.
        name: Name of the new layer.
        docref: Reference document if provided, otherwise use active.

    Returns:
        Imported art layer.
    """
    desc = ActionDescriptor()
    docref = docref or APP.activeDocument
    docref.activeLayer = layer
    desc.putPath(sID('target'), str(path))
    APP.executeAction(sID('placeEvent'), desc)
    docref.activeLayer.name = name
    return docref.activeLayer

src.helpers.document.import_svg(path: Union[str, Path], ref: Union[ArtLayer, LayerSet] = None, placement: Optional[ElementPlacement] = None, docref: Optional[Document] = None) -> ArtLayer

Imports an SVG image, then moves it if needed.

Parameters:

Name Type Description Default
path str | Path

SVG file to import.

required
ref ArtLayer | LayerSet

Reference used to move layer.

None
placement ElementPlacement | None

Placement based on the reference.

None
docref Document | None

Reference document if provided, otherwise use active.

None

Returns:

Type Description
ArtLayer

Imported SVG layer.

Source code in src\helpers\document.py
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
def import_svg(
    path: Union[str, Path],
    ref: Union[ArtLayer, LayerSet] = None,
    placement: Optional[ElementPlacement] = None,
    docref: Optional[Document] = None
) -> ArtLayer:
    """Imports an SVG image, then moves it if needed.

    Args:
        path: SVG file to import.
        ref: Reference used to move layer.
        placement: Placement based on the reference.
        docref: Reference document if provided, otherwise use active.

    Returns:
        Imported SVG layer.
    """
    # Import the art
    desc = ActionDescriptor()
    docref = docref or APP.activeDocument
    desc.putPath(sID('target'), str(path))
    APP.executeAction(sID('placeEvent'), desc)

    # Position the layer if needed
    if ref and placement:
        docref.activeLayer.move(ref, placement)
    return docref.activeLayer

src.helpers.document.paste_file(layer: ArtLayer, path: Union[str, Path], action: any = None, action_args: dict = None, docref: Optional[Document] = None) -> ArtLayer

Pastes the given file into the specified layer.

Parameters:

Name Type Description Default
layer ArtLayer

Layer object to paste the image into.

required
path str | Path

Filepath of the image to open.

required
action any

Optional action function to call on the image before importing it.

None
action_args dict

Optional arguments to pass to the action function.

None
docref Document | None

Reference document if provided, otherwise use active.

None

Returns:

Type Description
ArtLayer

Active layer where art was pasted.

Source code in src\helpers\document.py
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
def paste_file(
    layer: ArtLayer,
    path: Union[str, Path],
    action: any = None,
    action_args: dict = None,
    docref: Optional[Document] = None
) -> ArtLayer:
    """Pastes the given file into the specified layer.

    Args:
        layer: Layer object to paste the image into.
        path: Filepath of the image to open.
        action: Optional action function to call on the image before importing it.
        action_args: Optional arguments to pass to the action function.
        docref: Reference document if provided, otherwise use active.

    Returns:
        Active layer where art was pasted.
    """
    # Select the correct layer, then load the file
    docref = docref or APP.activeDocument
    docref.activeLayer = layer
    APP.load(str(path))

    # Optionally run action on art before importing it
    if action:
        action(**action_args) if action_args else action()

    # Select the entire image, copy it, and close the file
    newdoc = APP.activeDocument
    docsel = newdoc.selection
    docsel.selectAll()
    docsel.copy()
    newdoc.close(
        SaveOptions.DoNotSaveChanges)

    # Paste the image into the specific layer
    docref.paste()
    return docref.activeLayer

src.helpers.document.import_art_into_new_layer(path: Union[str, Path], name: str = 'New Layer', docref: Optional[Document] = None) -> ArtLayer

Creates a new layer and imports a given art into that layer.

Parameters:

Name Type Description Default
path str | Path

Image file to import, must have a valid image extension.

required
name str

Chosen name of the new layer.

'New Layer'
docref Document | None

Reference document if provided, otherwise use active.

None

Returns:

Type Description
ArtLayer

New ArtLayer with imported art.

Source code in src\helpers\document.py
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
def import_art_into_new_layer(
    path: Union[str, Path],
    name: str = "New Layer",
    docref: Optional[Document] = None
) -> ArtLayer:
    """Creates a new layer and imports a given art into that layer.

    Args:
        path: Image file to import, must have a valid image extension.
        name: Chosen name of the new layer.
        docref: Reference document if provided, otherwise use active.

    Returns:
        New ArtLayer with imported art.
    """
    return import_art(
        layer=create_new_layer(name),
        path=path,
        name=name,
        docref=docref)

src.helpers.document.jump_to_history_state(position: int)

Jump to a position in the history state relative to its current position. 2 moves forward two, -2 moves backwards two.

Parameters:

Name Type Description Default
position int

Integer value determining how far ahead or behind in the state to move.

required
Source code in src\helpers\document.py
201
202
203
204
205
206
207
208
209
210
211
212
def jump_to_history_state(position: int):
    """Jump to a position in the history state relative to its current position.
        2 moves forward two, -2 moves backwards two.

    Args:
        position: Integer value determining how far ahead or behind in the state to move.
    """
    desc1 = ActionDescriptor()
    ref1 = ActionReference()
    ref1.PutOffset(sID('historyState'),  position)
    desc1.PutReference(sID('target'),  ref1)
    APP.executeAction(sID('select'), desc1,  NO_DIALOG)

src.helpers.document.toggle_history_state(direction: str = 'previous') -> None

Alter the history state.

Parameters:

Name Type Description Default
direction str

Direction to move the history state ("previous" or "next").

'previous'
Source code in src\helpers\document.py
215
216
217
218
219
220
221
222
223
224
225
def toggle_history_state(direction: str = 'previous') -> None:
    """Alter the history state.

    Args:
        direction: Direction to move the history state ("previous" or "next").
    """
    desc1 = ActionDescriptor()
    ref1 = ActionReference()
    ref1.PutEnumerated(sID('historyState'), sID('ordinal'), sID(direction))
    desc1.PutReference(sID('target'), ref1)
    APP.executeAction(sID('select'), desc1, NO_DIALOG)

src.helpers.document.undo_action() -> None

Undo the last action in the history state.

Source code in src\helpers\document.py
228
229
230
def undo_action() -> None:
    """Undo the last action in the history state."""
    toggle_history_state('previous')

src.helpers.document.redo_action() -> None

Redo the last action undone in the history state.

Source code in src\helpers\document.py
233
234
235
def redo_action() -> None:
    """Redo the last action undone in the history state."""
    toggle_history_state('next')

src.helpers.document.reset_document(docref: Optional[Document] = None) -> None

Reset to the history state to when document was first opened.

Parameters:

Name Type Description Default
docref Document | None

Reference document to reset state in, use active if not provided.

None
Source code in src\helpers\document.py
238
239
240
241
242
243
244
245
246
247
248
def reset_document(docref: Optional[Document] = None) -> None:
    """Reset to the history state to when document was first opened.

    Args:
        docref: Reference document to reset state in, use active if not provided.
    """
    docref = docref or APP.activeDocument
    d1, r1 = ActionDescriptor(), ActionReference()
    r1.putName(sID('snapshotClass'), docref.name)
    d1.putReference(sID('target'), r1)
    APP.executeAction(sID('select'), d1, NO_DIALOG)

src.helpers.document.points_to_pixels(number: Union[int, float], docref: Optional[Document] = None) -> float

Converts a given number in point units to pixel units.

Parameters:

Name Type Description Default
number int | float

Number represented in point units.

required
docref Document | None

Document to reference, use active if not provided.

None

Returns:

Type Description
float

Float representing the given value in pixel units.

Source code in src\helpers\document.py
256
257
258
259
260
261
262
263
264
265
266
267
def points_to_pixels(number: Union[int, float], docref: Optional[Document] = None) -> float:
    """Converts a given number in point units to pixel units.

    Args:
        number: Number represented in point units.
        docref: Document to reference, use active if not provided.

    Returns:
        Float representing the given value in pixel units.
    """
    docref = docref or APP.activeDocument
    return (docref.resolution / 72) * number

src.helpers.document.pixels_to_points(number: Union[int, float], docref: Optional[Document] = None) -> float

Converts a given number in pixel units to point units.

Parameters:

Name Type Description Default
number int | float

Number represented in pixel units.

required
docref Document | None

Document to reference, use active if not provided.

None

Returns:

Type Description
float

Float representing the given value in point units.

Source code in src\helpers\document.py
270
271
272
273
274
275
276
277
278
279
280
281
def pixels_to_points(number: Union[int, float], docref: Optional[Document] = None) -> float:
    """Converts a given number in pixel units to point units.

    Args:
        number: Number represented in pixel units.
        docref: Document to reference, use active if not provided.

    Returns:
        Float representing the given value in point units.
    """
    docref = docref or APP.activeDocument
    return number / (docref.resolution / 72)

src.helpers.document.check_active_document() -> bool

Checks if there are any active documents loaded in Photoshop.

Returns:

Type Description
bool

True if exists, otherwise False.

Source code in src\helpers\document.py
289
290
291
292
293
294
295
296
297
298
299
300
def check_active_document() -> bool:
    """Checks if there are any active documents loaded in Photoshop.

    Returns:
        True if exists, otherwise False.
    """
    try:
        if APP.documents.length > 0:
            return True
    except PS_EXCEPTIONS:
        pass
    return False

src.helpers.document.get_document(name: str) -> Optional[Document]

Check if a Photoshop Document has been loaded.

Parameters:

Name Type Description Default
name str

Filename of the document.

required

Returns:

Type Description
Document | None

The Document if located, None if missing.

Source code in src\helpers\document.py
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
def get_document(name: str) -> Optional[Document]:
    """Check if a Photoshop Document has been loaded.

    Args:
        name: Filename of the document.

    Returns:
        The Document if located, None if missing.
    """
    try:
        docs = APP.documents
        if docs.length < 1:
            return
        doc = docs.getByName(name)
        APP.activeDocument = doc
        return doc
    except PS_EXCEPTIONS:
        return

src.helpers.document.trim_transparent_pixels() -> None

Trim transparent pixels from Photoshop document.

Source code in src\helpers\document.py
328
329
330
331
332
333
334
335
336
def trim_transparent_pixels() -> None:
    """Trim transparent pixels from Photoshop document."""
    desc258 = ActionDescriptor()
    desc258.putEnumerated(sID('trimBasedOn'), sID('trimBasedOn'), sID('transparency'))
    desc258.putBoolean(sID('top'), True)
    desc258.putBoolean(sID('bottom'), True)
    desc258.putBoolean(sID('left'), True)
    desc258.putBoolean(sID('right'), True)
    APP.executeAction(sID('trim'), desc258, NO_DIALOG)

src.helpers.document.save_document_png(path: Path, docref: Optional[Document] = None) -> None

Save the current document as a PNG.

Parameters:

Name Type Description Default
path Path

Path to save the PNG file.

required
docref Document | None

Current active document. Use active if not provided.

None
Source code in src\helpers\document.py
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
def save_document_png(path: Path, docref: Optional[Document] = None) -> None:
    """Save the current document as a PNG.

    Args:
        path: Path to save the PNG file.
        docref: Current active document. Use active if not provided.
    """
    docref = docref or APP.activeDocument
    png_options = PNGSaveOptions()
    png_options.compression = 3
    png_options.interlaced = False
    docref.saveAs(
        file_path=str(path.with_suffix('.png')),
        options=png_options,
        asCopy=True)

src.helpers.document.save_document_jpeg(path: Path, optimize: bool = True, docref: Optional[Document] = None) -> None

Save the current document as a JPEG.

Parameters:

Name Type Description Default
path Path

Path to save the JPEG file.

required
optimize bool

Whether to save with "Optimize Baseline". Reduces file size, but may cause an error on older versions of Photoshop.

True
docref Document | None

Current active document. Use active if not provided.

None
Source code in src\helpers\document.py
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
def save_document_jpeg(path: Path, optimize: bool = True, docref: Optional[Document] = None) -> None:
    """Save the current document as a JPEG.

    Args:
        path: Path to save the JPEG file.
        optimize: Whether to save with "Optimize Baseline". Reduces file size, but
            may cause an error on older versions of Photoshop.
        docref: Current active document. Use active if not provided.
    """

    # Set up the save options
    docref = docref or APP.activeDocument
    options = JPEGSaveOptions(quality=12)
    try:

        # Reduces filesize, unsupported by older Photoshop versions
        if optimize:
            options.formatOptions = FormatOptionsType.OptimizedBaseline

        # Save the document
        docref.saveAs(
            file_path=str(path.with_suffix('.jpg')),
            options=options,
            asCopy=True)

    # Retry without Optimize Baseline
    except PS_EXCEPTIONS as e:
        if optimize:
            return save_document_jpeg(
                path=path,
                optimize=False,
                docref=docref)
        raise OSError from e

src.helpers.document.save_document_psd(path: Path, docref: Optional[Document] = None) -> None

Save the current document as a PSD.

Parameters:

Name Type Description Default
path Path

Path to save the PSD file.

required
docref Document | None

Open Photoshop document. Use active if not provided.

None
Source code in src\helpers\document.py
396
397
398
399
400
401
402
403
404
405
406
407
def save_document_psd(path: Path, docref: Optional[Document] = None) -> None:
    """Save the current document as a PSD.

    Args:
        path: Path to save the PSD file.
        docref: Open Photoshop document. Use active if not provided.
    """
    docref = docref or APP.activeDocument
    docref.saveAs(
        file_path=str(path.with_suffix('.psd')),
        options=PhotoshopSaveOptions(),
        asCopy=True)

src.helpers.document.save_document_psb(path: Path, *_args, **_kwargs) -> None

Save the current document as a PSB.

Parameters:

Name Type Description Default
path Path

Path to save the PSB file.

required
_args

Ignored args used by similar methods but not here.

()
_kwargs

Ignored kwargs used by similar methods but not here.

{}
Source code in src\helpers\document.py
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
def save_document_psb(path: Path, *_args, **_kwargs) -> None:
    """Save the current document as a PSB.

    Args:
        path: Path to save the PSB file.
        _args: Ignored args used by similar methods but not here.
        _kwargs: Ignored kwargs used by similar methods but not here.
    """
    d1 = ActionDescriptor()
    d2 = ActionDescriptor()
    d2.putBoolean(sID('maximizeCompatibility'), True)
    d1.putObject(sID('as'), sID('largeDocumentFormat'), d2)
    d1.putPath(sID('in'), str(path.with_suffix('.psb')))
    d1.putBoolean(sID('lowerCase'), True)
    APP.executeAction(sID('save'), d1, NO_DIALOG)

src.helpers.document.close_document(save: bool = False, docref: Optional[Document] = None, purge: bool = True) -> None

Close the active document.

Parameters:

Name Type Description Default
save bool

Whether to save changes to the document before closing.

False
docref Document | None

Open Photoshop document. Use active if not provided.

None
purge bool

Whether to purge all caches.

True
Source code in src\helpers\document.py
427
428
429
430
431
432
433
434
435
436
437
438
439
def close_document(save: bool = False, docref: Optional[Document] = None, purge: bool = True) -> None:
    """Close the active document.

    Args:
        save: Whether to save changes to the document before closing.
        docref: Open Photoshop document. Use active if not provided.
        purge: Whether to purge all caches.
    """
    docref = docref or APP.activeDocument
    save_options = SaveOptions.SaveChanges if save else SaveOptions.DoNotSaveChanges
    docref.close(saving=save_options)
    if purge:
        APP.purge(PurgeTarget.AllCaches)

src.helpers.document.rotate_document(angle: int) -> None

Rotate the document.

Returns:

Name Type Description
angle None

Angle to rotate the document.

Source code in src\helpers\document.py
447
448
449
450
451
452
453
454
455
456
457
458
def rotate_document(angle: int) -> None:
    """Rotate the document.

    Returns:
        angle: Angle to rotate the document.
    """
    desc1 = ActionDescriptor()
    ref1 = ActionReference()
    ref1.PutEnumerated(sID('document'), sID('ordinal'), sID('first'))
    desc1.PutReference(sID('target'), ref1)
    desc1.PutUnitDouble(sID('angle'), sID('angleUnit'), angle)
    APP.executeaction(sID('rotateEventEnum'), desc1, NO_DIALOG)

src.helpers.document.rotate_counter_clockwise() -> None

Utility definition for rotating 90 degrees counter-clockwise.

Source code in src\helpers\document.py
461
462
463
def rotate_counter_clockwise() -> None:
    """Utility definition for rotating 90 degrees counter-clockwise."""
    rotate_document(-90)

src.helpers.document.rotate_clockwise() -> None

Utility definition for rotating 90 degrees clockwise.

Source code in src\helpers\document.py
466
467
468
def rotate_clockwise() -> None:
    """Utility definition for rotating 90 degrees clockwise."""
    rotate_document(90)

src.helpers.document.rotate_full() -> None

Utility definition for rotating a full 180 degrees.

Source code in src\helpers\document.py
471
472
473
def rotate_full() -> None:
    """Utility definition for rotating a full 180 degrees."""
    rotate_document(180)

src.helpers.document.paste_to_document(layer: Union[ArtLayer, LayerSet, None] = None)

Paste current clipboard to the current layer.

Parameters:

Name Type Description Default
layer ArtLayer | LayerSet | None

Layer to make active, if provided.

None
Source code in src\helpers\document.py
481
482
483
484
485
486
487
488
489
490
491
492
def paste_to_document(layer: Union[ArtLayer, LayerSet, None] = None):
    """Paste current clipboard to the current layer.

    Args:
        layer: Layer to make active, if provided.
    """
    if layer:
        APP.activeDocument.activeLayer = layer
    desc1 = ActionDescriptor()
    desc1.PutEnumerated(sID("antiAlias"), sID("antiAliasType"), sID("antiAliasNone"))
    desc1.PutClass(sID("as"), sID("pixel"))
    APP.Executeaction(sID("paste"), desc1, NO_DIALOG)