Skip to content

Releases: EmilDohne/PhotoshopAPI

v0.9.0

06 Apr 19:38
e16e4e1

Choose a tag to compare

This release primarily brings the long awaited support for editable text layers thanks to @ogkalu2!. For documentation please refer to here:

https://photoshopapi.readthedocs.io/en/latest/concepts/text-layers.html

Features:

  • Add support for editable text layer. You can now read/parse/update/create text layer data.
  • Add support for modifying a layers' display color via the new Layer<T>::display_color property.
  • Add support for passing unparsed data on roundtripping so e.g. adjustment layers will be maintained as you read/write files.

Bugfixes

  • Fix linked layers from latest photoshop release not parsing due to updated descriptor version (thanks @prodBirdy!)

CI/Build

  • Add support for python 3.14 out of the box

v0.8.2

11 Jan 17:21

Choose a tag to compare

Bugfixes

  • Fix bug where large files (>30.000) pixels would report EOF read error in Photoshop #196

v0.8.1

10 Jan 14:50

Choose a tag to compare

Bugfixes

  • Fix bug where uncompressed 8-bit layers would load as white #164 #191
  • Fix bug where smart object layer channel order was non-deterministic #190

v0.8.0

18 Dec 21:02
5e3b0d7

Choose a tag to compare

This release mainly focuses on bugfixes as well as some QOL changes. More larger changes are to follow!

We have a first time contribute with this release @oallw, thank you for contributing! 🥳

Features:

  • Swap the internal compression backend to use the compressed-image API which should give some additional performance/memory savings as well as providing a way to interact with the compressed file buffers.
  • python: Allow setting of icc profiles directly with numpy arrays

Bugfixes

  • Fix various Unicode related issues related to file reads. This should now be much more consistent #180 #182
  • python: Fix bug where unicode assignment was broken #174 from @oallw
  • Fix issue where after replacing a SmartObject, the warp/transform was lost #162

CI/Build

  • Fix vcpkg binary caching to speed up CI/Releases
  • Bump OpenImageIO from 2.5.16.0 -> 3.0.9.1

v0.7.0 - Smart Object improvements

18 Jul 07:35
171bb60

Choose a tag to compare

The v0.7.0 Release primarily fixes miscellaneous errors on smart objects as well as exposing the clipping mask property on layers

Note

This release changes the python import of psapi -> photoshopapi. If you wish to keep using psapi as alias you can import photoshopapi as psapi

Features:

  • Add the clipping_mask field to all layer types, allowing you to set and restore clipping masks. #156

Bugfixes

  • Fix issue with smart object layers where the quilt warp was being calculated incorrectly, causing stepped output files with an offset #156
  • Fix miscellaneous read errors when attempting to read older style smart object descriptors.
  • photoshopapi python package will now be properly installed into photoshopapi and photoshopapi.libs rather than polluting site-packages
  • Fix python issue on windows where you weren't able to import both PhotoshopAPI and OpenImageIO due to dll issues.

CI/Build

  • Change python wheel setup to use more modern scikit-build-core. Deprecate the old setup.py workflow completely replacing it with a much simpler pyproject.toml

Breaking Changes:

  • The python wheels are now importable via import photoshopapi, not import psapi

v0.6.1

09 Jun 17:11
36209f5

Choose a tag to compare

The v0.6.1 Release fixes some bugs related to smart object layer parsing

Warning

This release drops support for python 3.7 wheels due to CI limitations

Bugfixes:

  • Fix smart object layer translating to 0,0 on write #142
  • Fix incorrect padding for LinkedLayerItem sometimes causing files with more than one smart object layer to fail #149
  • Add internal mini psd/psb reader for reading embedded photoshop files in smart objects rather than relying on OpenImageIO #149
  • Add handling and tests for smart object layers that do not embed the customEnvelopeWarp field (which seems to happen sometimes) #149

Deprecations

  • Deprecate SmartObjectWarp::valid().

v0.6.0 - Smart Objects

25 Feb 19:39
bd9f29f

Choose a tag to compare

The v0.6.0 Release primarily targets adding support for SmartObject layers and warps. Additionally, we refactored large parts of the internal and public API.

To check out how to use SmartObjects please have a look here for an example, here for the documentation (c++) and here for the documentation (python)

Warning

This is a breaking release, please proceed with caution and read both the changelogs and documentation carefully as large parts of the API were overhauled.

Features:

  • Add support for SmartObject layers SmartObjectLayer<T>, psapi.SmartObjectLayer_*bit
  • add support for SmartObject warps (Exceptions being "smart" perspective warp and puppet warp)

Python

  • Expose all mask parameters that were previously hidden. This includes mask_disabled, mask_relative_to_layer, mask_default_color, mask_density, mask_feather, mask_position, mask_width and mask_height

Bugfixes:

  • Masks on layers now are better supported and have their width and height decoupled from the layers' width and height (except for during construction of image layers).
  • Internal: Harden file section write to be less error prone using scoped section markers

C++

  • Harden template requirements to only allow uint8_t, uint16_t, float for all Photoshop related templates

Python

  • Add missing is_visible and is_locked arguments to constructor of layers

Breaking Changes:

  • Layer coordinates are no longer expressed relative to the canvas center but rather relative to canvas top left to be more in line with photoshop
    • Example: if previously for a 64x64 canvas a centered layer was at (0, 0), now it would be at (32, 32)
  • Layer opacity is now expressed as a float (but still backed by a uint8_t

C++

  • Drop C++17 support
  • Public facing API was changed from camelCase to snake_case to be more in line and equal to python bindings
  • All previously public member variables are now private with appropriate getters and setters to allow the API to implement more logic on them in the future

Python

  • All image data is no longer expressed as a property but instead as method as these are potentially quite expensive to compute
  • ImageLayer_*bit.channels property is now ImageLayer_*bit.channel_indices()

Miscellaneous:

  • Add Compositing Framework to prepare for eventual layer stack compositing
  • Internal: Add basic 2D rendering framework
  • Internal: Add Geometry Framework to allow for parsing of Quad Meshes and Bezier Surfaces
  • Internal: Add Parsing of Descriptors
  • Internal: Simplify endian functions to work more generically
  • Refactor large parts of the internal API.
  • Refactor inheritance structure of Image Based layers and extract mask logic to mixin

Dependencies:

  • Add OpenImageIO as dependency (via vcpkg)
  • Add fmt as dependency (via vcpkg)
  • Add stduiid as dependency (via vcpkg)
  • Add eigen3 as dependency (via vcpkg)
  • Add json as a submodule
  • Move libdeflate from submodule to vcpkg
  • Add vcpkg submodule
  • Bump c-blosc2 to 2.15.2

Documentation

  • Link in examples directly to hosted docs for easier access

CI:

  • Add Clang ubuntu build target
  • Add ASAN to all tests (that support it)
  • Add Clang ubuntu valgrind target

v0.5.2

18 Dec 13:53

Choose a tag to compare

Bugfixes

Python

  • When calling ImageLayer.get_image_data() or ImageLayer.image_data it no longer fails if there is a mask channel with a different size than the image data itself
  • ImageLayer num_channels and channels properties now consider the mask channel instead of skipping it

v0.5.1

22 Oct 16:18

Choose a tag to compare

Bugfixes

  • The previous release (v0.5.0) had missing wheels in the release, we address this here. Any pip install of photoshop should target this version instead of v0.5.0

v0.5.0

22 Oct 15:07
d9e6454

Choose a tag to compare

The v0.5.0 Release primarily targets adding support for CMYK and Grayscale while also improving the overal consistency of the python bindings. Additionally we added support for trivially replacing image data.

Three new examples were added. Please feel free to check them out!

Roadmap

v0.6.0

  • Adjustment Layers
  • Smart Objects

Performance

  • Read and Write speeds of 8-bit files are about 30-40% faster
  • Read and Write speeds of 16- and 32-bit files are about 10-15% faster
  • Image data extraction from ImageLayer<T> now runs fully parallelized
  • Python channel extraction speed was greatly improved

Features:

C++ / General

  • Add optional ProgressCallback that can be passed to read and write functions for LayeredFile<T>
  • Add support for Unicode layer names. Preferring these over PascalString layer names.
  • Add support for CMYK color mode
  • Add support for Grayscale color mode
  • Make files Krita compatible
  • Add support for locked layers
  • Add a PhotoshopFile::findBitdepth() function which reads out the header and allows for programmatic dispatching of LayeredFile<T> instances
  • Add a LayeredFile<T>::flatLayers() function for getting a flattened layer hierarchy which can be iterated without recursion.
  • Add functions for swapping image data: ImageLayer<T>::setImageData(), Layer<T>::setMask()

Python

  • Added more verbose error logging if the image data provided as numpy array does not match what is expected
  • LayeredFile: add flat_layers property giving you a temporary view over all the layers allowing for easy flat traversal. This is especially useful when applying some operation to all layers like resizing.
  • Layer: add is_visible property
  • Layer: add is_locked property
  • Layer: add has_mask() function
  • ImageLayer: add set_image_data, set_channel_by_id and set_channel_by_index functions as well as making the image_data property read-writable
  • ImageLayer: add num_channels and channels properties

Bugfixes:

C++ / General

  • findLayerAs() function no longer raises an error if layer cannot be found but instead returns nullptr to be more consistent with LayeredFile<T>::findLayer()
  • Fix memory leak due to missing call to blosc2_schunk_free()
  • Fix bug where files with only GroupLayers would not be openable in photoshop
  • Mask channels passed to ImageLayer<T> as image data now get automatically forwarded to m_LayerMask

Python

  • Fixed bug where non c-style contiguous arrays wouldn't be parsed correctly (e.g. when using numpy.reshape()). This conversion is now forced in-place
  • Fix missing self argument in psapi-stubs

Deprecations

  • Deprecate Layer<T>::getMaskData() in favour of Layer<T>::getMask()

Breaking changes:

The main breaking changes are to what is considered the internal API. A lot of the files in Util/ were moved over to Core/ where appropriate.

ImageLayer<T> constructor now takes an int16_t rather than uint16_t

Python

  • The Layer.layer_mask property has been removed in favour of Layer.mask. This property is now read-writable

CI / Compiling

  • Cranked up warnings under MSVC to /W4 and /WX with some additional warnings
  • Added ASAN and Valgrind steps to CI for continuous checking of correctness
  • Added memory-mapped files as backend for faster load times