Skip to content

Draft: PSD: refactor, modernize, upgrade, optimize, and implement missing features

👋

In this PR I apply the same drill as in !1695 (closed). For the present branch, I grabbed the 80-layer PSD file we got from https://bugs.kde.org/462417 and profiled it. The results will speak from themselves:

Before After
imagen imagen

For the save, the improvements are smaller but still meaningful (after CFG overhead).

Before After
imagen imagen

New features

  • Progress updater

Breaking changes

None. There was little need for clang-tidy here, fortunately.

Performance highlights

  • In KisPainter, I switched to the tile accessor for 25% cheaper transparency checks on opaque pictures (tested with https://bugs.kde.org/444844)
  • 18% less time spent exporting the channel panels by inline templating the color space checks
  • 10% less time RLE compressing the rows by reworking of the compressor logic
  • 50% less time spent accessing pixels individually by switching to the tile accessor
  • A simple 3% speedup by caching the layer info record instead of copy-constructing it when checking it for the compression type

Reading pixels

87% of the time of the old readChannelValue() function, the workhorse of pixel reconstitution, was taken in QMap innards and the constant virtual function calls. Here I:

  • switched to a const std::map for accessing the channels, which is a true O(log n) container and does not allocate within accessors
  • made the layer info records const and memory managed
  • took all bounds checks out of the hot path, by caching the pointers before reconstituting the row
  • fixed some inlining issues in KisRLE::decompress(), brought by QByteArray container iterators being virtual function calls, instead of inlinable pointers
  • employed my templated inlined functions trick to perform the color space and compression checks only once, instead of in every pixel.

And, only once per chunk of contiguous rows:

  • cached the PSD row data reusing the same map strategy as above
  • this had the added benefit that the channel could be accessed only once, at the row start, and only the pointer is shipped around
  • performed the bounds check and early rejected the PSD as malformed

Test Plan

Build Krita and try using PSD files.

Formalities Checklist

  • I confirmed this builds.
  • I confirmed Krita ran and the relevant functions work.
  • I tested the relevant unit tests and can confirm they are not broken. (If not possible, don't hesitate to ask for help!)
  • I made sure my commits build individually and have good descriptions as per KDE guidelines.
  • I made sure my code conforms to the standards set in the HACKING file.
  • I can confirm the code is licensed and attributed appropriately, and that unattributed code is mine, as per KDE Licensing Policy.

Merge request reports