Skip to content

Document

DOCUMENT HELPERS

NO_DIALOG = DialogModes.DisplayNoDialogs module-attribute

DOCUMENT HIERARCHY

check_active_document()

Checks if there are any active documents loaded in Photoshop. @return: True if exists, otherwise False.

Source code in src/helpers/document.py
228
229
230
231
232
233
234
235
236
237
238
def check_active_document() -> bool:
    """
    Checks if there are any active documents loaded in Photoshop.
    @return: True if exists, otherwise False.
    """
    try:
        if app.documents.length > 0:
            return True
    except PS_EXCEPTIONS:
        pass
    return False

close_document()

Close the active document.

Source code in src/helpers/document.py
343
344
345
def close_document() -> None:
    """Close the active document."""
    app.activeDocument.close(SaveOptions.DoNotSaveChanges)

get_document(name)

Check if a Photoshop Document has been loaded. @param name: Filename of the document. @return: The Document if located, None if missing.

Source code in src/helpers/document.py
241
242
243
244
245
246
247
248
249
250
251
252
253
254
def get_document(name: str) -> Optional[Document]:
    """
    Check if a Photoshop Document has been loaded.
    @param name: Filename of the document.
    @return: The Document if located, None if missing.
    """
    try:
        if app.documents.length < 1:
            return
        doc = app.documents.getByName(name)
        app.activeDocument = doc
        return doc
    except PS_EXCEPTIONS:
        return

get_layer_tree(group=None)

Composes a dictionary tree of layers in the active document or a specific LayerSet. @param: A specific group to create a dictionary tree for. @return: A dictionary tree comprised of all the layers in a document or group.

Source code in src/helpers/document.py
51
52
53
54
55
56
57
58
59
60
61
62
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.
    @param: A specific group to create a dictionary tree for.
    @return: 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

get_leaf_layers(group=None)

Utility function to generate a list of leaf layers in a LayerSet or document. @param group: Group to grab leaf layers from. @return: A list of leaf layers in a LayerSet or document.

Source code in src/helpers/document.py
37
38
39
40
41
42
43
44
45
46
47
48
def get_leaf_layers(group: Optional[LayerSet] = None) -> list[ArtLayer]:
    """
    Utility function to generate a list of leaf layers in a LayerSet or document.
    @param group: Group to grab leaf layers from.
    @return: 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

import_art(layer, file, name='Layer 1')

Imports an art file into the active layer. @param layer: Layer to make active and receive image. @param file: Image file to import. @param name: Name of the new layer.

Source code in src/helpers/document.py
70
71
72
73
74
75
76
77
78
79
80
81
82
def import_art(layer: ArtLayer, file: Union[str, Path], name: str = "Layer 1") -> ArtLayer:
    """
    Imports an art file into the active layer.
    @param layer: Layer to make active and receive image.
    @param file: Image file to import.
    @param name: Name of the new layer.
    """
    desc = ActionDescriptor()
    app.activeDocument.activeLayer = layer
    desc.putPath(sID("target"), str(file))
    app.executeAction(sID("placeEvent"), desc)
    app.activeDocument.activeLayer.name = name
    return app.activeDocument.activeLayer

import_art_into_new_layer(file, name='New Layer')

Creates a new layer and imports a given art into that layer. @param file: Image file to import, must have a valid image extension. @param name: Chosen name of the new layer.

Source code in src/helpers/document.py
138
139
140
141
142
143
144
def import_art_into_new_layer(file: str, name: str = "New Layer") -> ArtLayer:
    """
    Creates a new layer and imports a given art into that layer.
    @param file: Image file to import, must have a valid image extension.
    @param name: Chosen name of the new layer.
    """
    return import_art(create_new_layer(name), file, name)

import_svg(file, ref=None, placement=None)

Imports an SVG image, then moves it if needed. @param file: SVG file to import. @param ref: Reference used to move layer. @param placement: Placement based on the reference. @return: New layer containing SVG.

Source code in src/helpers/document.py
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
def import_svg(
    file: Union[str, os.PathLike],
    ref: Union[ArtLayer, LayerSet] = None,
    placement: Optional[ElementPlacement] = None
) -> ArtLayer:
    """
    Imports an SVG image, then moves it if needed.
    @param file: SVG file to import.
    @param ref: Reference used to move layer.
    @param placement: Placement based on the reference.
    @return: New layer containing SVG.
    """
    # Import the art
    desc = ActionDescriptor()
    desc.putPath(sID("target"), str(file))
    app.executeAction(sID("placeEvent"), desc)

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

jump_to_history_state(position)

Jump to a position in the history state relative to its current position. 2 moves forward two, -2 moves backwards two. @param position: Integer value determining how far ahead or behind in the state to move.

Source code in src/helpers/document.py
152
153
154
155
156
157
158
159
160
161
162
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.
    @param 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)

paste_file(layer, file, action=None, action_args=None)

Pastes the given file into the specified layer. @param layer: Layer object to paste the image into. @param file: Filepath of the image to open. @param action: Optional action function to call on the image before importing it. @param action_args: Optional arguments to pass to the action function

Source code in src/helpers/document.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
def paste_file(
    layer: ArtLayer,
    file: Union[str, os.PathLike],
    action: any = None,
    action_args: dict = None
) -> None:
    """
    Pastes the given file into the specified layer.
    @param layer: Layer object to paste the image into.
    @param file: Filepath of the image to open.
    @param action: Optional action function to call on the image before importing it.
    @param action_args: Optional arguments to pass to the action function
    """
    # Select the correct layer, then load the file
    app.activeDocument.activeLayer = layer
    app.load(str(file))

    # 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
    app.activeDocument.selection.selectAll()
    app.activeDocument.selection.copy()
    app.activeDocument.close(SaveOptions.DoNotSaveChanges)

    # Paste the image into the specific layer
    app.activeDocument.paste()

pixels_to_points(number)

Converts a given number in pixel units to point units. @param number: Number represented in pixel units. @return: Float representing the given value in point units.

Source code in src/helpers/document.py
219
220
221
222
223
224
225
def pixels_to_points(number: Union[int, float]) -> float:
    """
    Converts a given number in pixel units to point units.
    @param number: Number represented in pixel units.
    @return: Float representing the given value in point units.
    """
    return number / (app.activeDocument.resolution / 72)

points_to_pixels(number)

Converts a given number in point units to pixel units. @param number: Number represented in point units. @return: Float representing the given value in pixel units.

Source code in src/helpers/document.py
210
211
212
213
214
215
216
def points_to_pixels(number: Union[int, float]) -> float:
    """
    Converts a given number in point units to pixel units.
    @param number: Number represented in point units.
    @return: Float representing the given value in pixel units.
    """
    return (app.activeDocument.resolution / 72) * number

redo_action()

Redo the last action undone in the history state.

Source code in src/helpers/document.py
184
185
186
187
188
def redo_action() -> None:
    """
    Redo the last action undone in the history state.
    """
    toggle_history_state("next")

reset_document()

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

Source code in src/helpers/document.py
191
192
193
194
195
196
197
198
199
200
201
202
def reset_document() -> None:
    """
    Reset to the history state to when document was first opened.
    """
    idslct = cID("slct")
    desc9 = ActionDescriptor()
    idnull = sID("target")
    ref1 = ActionReference()
    idSnpS = cID("SnpS")
    ref1.putName(idSnpS, app.activeDocument.name)
    desc9.putReference(idnull, ref1)
    app.executeAction(idslct, desc9, NO_DIALOG)

rotate_clockwise()

Utility definition for rotating 90 degrees clockwise.

Source code in src/helpers/document.py
371
372
373
def rotate_clockwise() -> None:
    """Utility definition for rotating 90 degrees clockwise."""
    rotate_document(90)

rotate_counter_clockwise()

Utility definition for rotating 90 degrees counter-clockwise.

Source code in src/helpers/document.py
366
367
368
def rotate_counter_clockwise() -> None:
    """Utility definition for rotating 90 degrees counter-clockwise."""
    rotate_document(-90)

rotate_document(angle)

Rotate the document. @param angle: Angle to rotate the document.

Source code in src/helpers/document.py
353
354
355
356
357
358
359
360
361
362
363
def rotate_document(angle: int) -> None:
    """
    Rotate the document.
    @param 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)

rotate_full()

Utility definition for rotating a full 180 degrees.

Source code in src/helpers/document.py
376
377
378
def rotate_full() -> None:
    """Utility definition for rotating a full 180 degrees."""
    rotate_document(180)

save_document_jpeg(path, optimize=True)

Save the current document as a JPEG. @param path: Path to save the JPEG file. @param optimize: Whether to save with "Optimize Baseline". Reduces file size, but may cause an error on older versions of Photoshop.

Source code in src/helpers/document.py
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
def save_document_jpeg(path: Path, optimize: bool = True) -> None:
    """
    Save the current document as a JPEG.
    @param path: Path to save the JPEG file.
    @param optimize: Whether to save with "Optimize Baseline". Reduces file size, but
    may cause an error on older versions of Photoshop.
    """
    try:
        jpeg_options = JPEGSaveOptions(quality=12)
        if optimize:
            # Reduces filesize, might cause an error on older Photoshop versions
            jpeg_options.formatOptions = FormatOptionsType.OptimizedBaseline
        app.activeDocument.saveAs(
            file_path=str(path.with_suffix('.jpg')),
            options=jpeg_options,
            asCopy=True)
    except PS_EXCEPTIONS as e:
        # Retry without Optimize Baseline
        if optimize:
            return save_document_jpeg(path, False)
        raise OSError from e

save_document_png(path)

Save the current document as a PNG. @param path: Path to save the PNG file.

Source code in src/helpers/document.py
280
281
282
283
284
285
286
287
288
289
290
291
def save_document_png(path: Path) -> None:
    """
    Save the current document as a PNG.
    @param path: Path to save the PNG file.
    """
    png_options = PNGSaveOptions()
    png_options.compression = 3
    png_options.interlaced = False
    app.activeDocument.saveAs(
        file_path=str(path.with_suffix('.png')),
        options=png_options,
        asCopy=True)

save_document_psb(path)

Save the current document as a PSB. @param path: Path to save the PSB file.

Source code in src/helpers/document.py
329
330
331
332
333
334
335
336
337
338
339
340
def save_document_psb(path: Path) -> None:
    """
    Save the current document as a PSB.
    @param path: Path to save the PSB file.
    """
    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, DialogModes.DisplayNoDialogs)

save_document_psd(path)

Save the current document as a PSD. @param path: Path to save the PSD file.

Source code in src/helpers/document.py
317
318
319
320
321
322
323
324
325
326
def save_document_psd(path: Path) -> None:
    """
    Save the current document as a PSD.
    @param path: Path to save the PSD file.
    """
    app.activeDocument.saveAs(
        file_path=str(path.with_suffix('.psd')),
        options=PhotoshopSaveOptions(),
        asCopy=True
    )

toggle_history_state(direction='previous')

Alter the history state. @param direction: Direction to move the history state ("previous" or "next").

Source code in src/helpers/document.py
165
166
167
168
169
170
171
172
173
174
def toggle_history_state(direction: str = "previous") -> None:
    """
    Alter the history state.
    @param 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)

trim_transparent_pixels()

Trim transparent pixels from Photoshop document.

Source code in src/helpers/document.py
262
263
264
265
266
267
268
269
270
271
272
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)

undo_action()

Undo the last action in the history state.

Source code in src/helpers/document.py
177
178
179
180
181
def undo_action() -> None:
    """
    Undo the last action in the history state.
    """
    toggle_history_state("previous")