Bug 456586 - [kpp][pattern] Could not import embedded resource KoResourceSignature("patterns", "e1d2f36380b34f2ebbe75d6418e937a9", "tex9.png.pat", "tex9.png.pat")
Summary: [kpp][pattern] Could not import embedded resource KoResourceSignature("patter...
Status: RESOLVED FIXED
Alias: None
Product: krita
Classification: Applications
Component: Resource Management (show other bugs)
Version: nightly build (please specify the git hash!)
Platform: Appimage Linux
: NOR normal
Target Milestone: ---
Assignee: Dmitry Kazakov
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-07-11 12:49 UTC by David REVOY
Modified: 2024-10-24 11:36 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
^ the buggy KPP brush preset (358.77 KB, image/png)
2022-07-11 12:49 UTC, David REVOY
Details

Note You need to log in before you can comment on or make changes to this bug.
Description David REVOY 2022-07-11 12:49:35 UTC
Created attachment 150535 [details]
^ the buggy KPP brush preset

Hi,
I made a derivation of a default kpp preset, saved it; but this new kpp can't never load it's pattern... unless I click first on the original preset.

To reproduce:
===========
1. Download the KPP file in attachement "g)_Dry_Textured_Creases_creamy.0001.kpp"
2. Open Krita, create a new document, go to Settings > Manage Resources > Import Resources and load the KPP, Close the resources Manager.
3. In your "Brush Preset" docker, scroll to find the preset "g)_Dry_Textured_Creases_creamy" with it's green stroke on the thumbnail. Click on it and paint a stroke on the canvas. 

Result:
======
The terminal prints these errors:
```
Could not open "/home/deevad/sources/krita/.share/krita/paintoppresets/g)_Dry_Textured_Creases_creamy.0001.kpp" for reading
Could not get linked pattern
createLocalResourcesSnapshot: Could not import embedded resource KoResourceSignature("patterns", "e1d2f36380b34f2ebbe75d6418e937a9", "tex9.png.pat", "tex9.png.pat")
```
If you paint with the brush, you'll notice it doesn't have any texture: the stroke is plain.
Painting this way will print many:
```
WARNING: Couldn't load the pattern for a stroke (KisTextureMaskInfo)
WARNING: Couldn't load the pattern for a stroke (KisTextureMaskInfo)
WARNING: Couldn't load the pattern for a stroke (KisTextureMaskInfo)
WARNING: Couldn't load the pattern for a stroke (KisTextureMaskInfo)
WARNING: Couldn't load the pattern for a stroke (KisTextureMaskInfo)
createLocalResourcesSnapshot: Could not import embedded resource KoResourceSignature("patterns", "e1d2f36380b34f2ebbe75d6418e937a9", "tex9.png.pat", "tex9.png.pat")
WARNING: Couldn't load the pattern for a stroke (KisTextureMaskInfo)
WARNING: Couldn't load the pattern for a stroke (KisTextureMaskInfo)
WARNING: Couldn't load the pattern for a stroke (KisTextureMaskInfo)
WARNING: Couldn't load the pattern for a stroke (KisTextureMaskInfo)
WARNING: Couldn't load the pattern for a stroke (KisTextureMaskInfo)
WARNING: Couldn't load the pattern for a stroke (KisTextureMaskInfo)
```

Observation:
===========
Something interesting is, if you click now on the 'original' preset part of the default "g)_Dry_Textured_Creases" (side to side with the custom preset), paint a little bit on the canvas (a single stroke is ok), and then pick back the faulty preset "g)_Dry_Textured_Creases_creamy.0001.kpp" ... Then the bug is fixed: it now  behaves correctly and there is no more issue of loading the pattern.

Hardware and Spec:
================
2022-07-11, 13h13 nightly stable appimage: krita-5.1.0-beta2-fd924d7c03-x86_64.appimage
Fedora 36 KDE. Mesa 
GPU: AMD ATI Radeon RX 5500/5500M / Pro 5500M
CPU: AMD Ryzen 7 3700X (16) @ 3.600GHz
VM: Kwin/X11
DE: KDE Plasma 5.24.5
Qt version compiled: 5.12.12, loaded: 5.12.12.
Comment 1 wolthera 2023-01-26 13:44:59 UTC
I can confirm with the Krita Version: 5.2.0-prealpha (git 5c98a72) Appimage with Qt 5.15.7

Assigning to dmitry given it's a pattern embedding problem.
Comment 2 Dmitry Kazakov 2024-08-22 16:39:23 UTC
Remove triaged keyword from CONFIRMED bugs
Comment 3 Dmitry Kazakov 2024-10-24 11:33:08 UTC
Git commit 072460560b704e9ab36f488b35081bf49c7b9edd by Dmitry Kazakov.
Committed on 24/10/2024 at 11:27.
Pushed by dkazakov into branch 'master'.

Fix loading .kpp files with embedded top-level resources

The patch fixes multiple issues with loading embedded (side-loaded) resources
from the .kpp files:

1) Side-loaded resources were **never** loaded (since the very beginning of 5.0),
    because `reader.text("embedded_resources").toInt()` was read from a wrong
    place. The number of resources is stored in XML data, not in the PNG's metadata
    field.

    Now Krita doesn't check the resource count at all and just iterates over the XML to
    find "resource" elements.

2) A new KoResource::sideLoadedResources() method is introduced. It returns a one-time-
    available resources which are loaded alongside the main resource. These side-loaded
    resources can be expelled from memory by calling clearSideLoadedResources(), which
    is called by KisResourceLocator right after loading the resources into the memory.

3) KisResourceLocator now calls loadRequiredResources() in all code paths that load the
    resource into memory (to make sure all its embedded resources are loaded). Previously
    it required a Krita restart to load the embedded resources, cause it happened only during
    the normal lazy-loading.

4) Fixed KisEmbeddedTextureData::loadLinkedPattern() to return FailedLink resource
    instead of invalid EmbeddedResource, when the actual "patternBase64" tag is missing
    (it is missing in 5.0 version of the presets)

5) Adds a unittest that checks all these peculiarities (see KisPaintOpPresetTest)

NOTE:
Bug 456197 is "kind of fixed" with this patch, because side-loaded resources are now
loaded correctly. Though the problem may still be valid for other resource types that
do not side-load the dependencies.
Related: bug 487866, bug 456197

M  +50   -30   libs/image/brushengine/kis_paintop_preset.cpp
M  +3    -0    libs/image/brushengine/kis_paintop_preset.h
M  +1    -0    libs/image/tests/CMakeLists.txt
A  +108  -0    libs/image/tests/KisPaintOpPresetTest.cpp     [License: GPL(v2.0+)]
A  +21   -0    libs/image/tests/KisPaintOpPresetTest.h     [License: GPL(v2.0+)]
A  +-    --    libs/image/tests/data/test-embedded-resources-2.2.kpp
A  +-    --    libs/image/tests/data/test-embedded-resources-5.0.kpp
M  +39   -21   libs/resources/KisResourceLocator.cpp
M  +17   -0    libs/resources/KoResource.cpp
M  +28   -0    libs/resources/KoResource.h
M  +6    -1    plugins/paintops/libpaintop/KisEmbeddedTextureData.cpp

https://invent.kde.org/graphics/krita/-/commit/072460560b704e9ab36f488b35081bf49c7b9edd
Comment 4 Dmitry Kazakov 2024-10-24 11:36:12 UTC
Git commit 869cad0ce67c7786058de47c42909a9dd285597f by Dmitry Kazakov.
Committed on 24/10/2024 at 11:35.
Pushed by dkazakov into branch 'krita/5.2'.

Fix loading .kpp files with embedded top-level resources

The patch fixes multiple issues with loading embedded (side-loaded) resources
from the .kpp files:

1) Side-loaded resources were **never** loaded (since the very beginning of 5.0),
    because `reader.text("embedded_resources").toInt()` was read from a wrong
    place. The number of resources is stored in XML data, not in the PNG's metadata
    field.

    Now Krita doesn't check the resource count at all and just iterates over the XML to
    find "resource" elements.

2) A new KoResource::sideLoadedResources() method is introduced. It returns a one-time-
    available resources which are loaded alongside the main resource. These side-loaded
    resources can be expelled from memory by calling clearSideLoadedResources(), which
    is called by KisResourceLocator right after loading the resources into the memory.

3) KisResourceLocator now calls loadRequiredResources() in all code paths that load the
    resource into memory (to make sure all its embedded resources are loaded). Previously
    it required a Krita restart to load the embedded resources, cause it happened only during
    the normal lazy-loading.

4) Fixed KisEmbeddedTextureData::loadLinkedPattern() to return FailedLink resource
    instead of invalid EmbeddedResource, when the actual "patternBase64" tag is missing
    (it is missing in 5.0 version of the presets)

5) Adds a unittest that checks all these peculiarities (see KisPaintOpPresetTest)

NOTE:
Bug 456197 is "kind of fixed" with this patch, because side-loaded resources are now
loaded correctly. Though the problem may still be valid for other resource types that
do not side-load the dependencies.
Related: bug 487866, bug 456197

M  +50   -30   libs/image/brushengine/kis_paintop_preset.cpp
M  +3    -0    libs/image/brushengine/kis_paintop_preset.h
M  +1    -0    libs/image/tests/CMakeLists.txt
A  +108  -0    libs/image/tests/KisPaintOpPresetTest.cpp     [License: GPL(v2.0+)]
A  +21   -0    libs/image/tests/KisPaintOpPresetTest.h     [License: GPL(v2.0+)]
A  +-    --    libs/image/tests/data/test-embedded-resources-2.2.kpp
A  +-    --    libs/image/tests/data/test-embedded-resources-5.0.kpp
M  +39   -21   libs/resources/KisResourceLocator.cpp
M  +17   -0    libs/resources/KoResource.cpp
M  +28   -0    libs/resources/KoResource.h
M  +6    -1    plugins/paintops/libpaintop/KisEmbeddedTextureData.cpp

https://invent.kde.org/graphics/krita/-/commit/869cad0ce67c7786058de47c42909a9dd285597f