Bug 402382 - Node::projectionPixelData returns 0s for grouplayer and wrong data for filelayer
Summary: Node::projectionPixelData returns 0s for grouplayer and wrong data for filelayer
Status: RESOLVED NOT A BUG
Alias: None
Product: krita
Classification: Applications
Component: Scripting (show other bugs)
Version: nightly build (please specify the git hash!)
Platform: Appimage Linux
: NOR normal
Target Milestone: ---
Assignee: Krita Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-12-20 14:42 UTC by Razvan Radulescu
Modified: 2019-01-23 16:43 UTC (History)
1 user (show)

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


Attachments
test kra and export files (249.60 KB, application/zip)
2018-12-20 14:42 UTC, Razvan Radulescu
Details
Other test kra file (659.25 KB, application/x-krita)
2019-01-21 15:30 UTC, wolthera
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Razvan Radulescu 2018-12-20 14:42:04 UTC
Created attachment 117026 [details]
test kra and export files

SUMMARY
Node::projectionPixelData should return data even in case of grouplayer as per libkis documentation: <<projectionPixelData reads the given rectangle from the Node's projection (that is, what the node looks like after all sub-Nodes (like layers in a group or masks on a layer) have been applied, and returns it as a byte array.>>

It turns out Node::projectionPixelData for grouplayer returns all 0s and for filelayer it looks to be screwed up.

STEPS TO REPRODUCE
This is very tricky because it's based on a script. One option would be to clone/download https://github.com/razcore-art/Krita-designer-tools and place in pykrita. Create a `Dependencies` folder inside the plugin folder (gdquest_art_tools) and install a compatible Pillow version with your Krita Python version with `pip install --target=Dependencies link_to_pillow`. `link_to_pillow` can be found from https://pypi.org/project/Pillow/#files. Then open up Krita with uploaded `test.kra` file. Be sure to have `test_convertion.kra` in there as well since `test.kra` uses `test_convertion.kra` as a file layer. Turn on the plugin (called GDquest Art Tools), open the docker with the same name and press "All Layers". You can also press "Selected Layers" while selecting some of them. Try the group/file layers. See further info at this PR: https://github.com/GDquest/Krita-designer-tools/pull/12#issue-240184606.

Another option is to just explore the attached files via Scripter.

I've included the export operation in the attachment as well.

OBSERVED RESULT
Open the files and see that group layer exports are completely transparent, no data (all 0s) while file layer exports are all screwed up, it's as if the column/row order in the bytearray is inverted.


EXPECTED RESULT
All layers should be exported as they appear in Krita.


SOFTWARE/OS VERSIONS
OS Information
  Build ABI: x86_64-little_endian-lp64
  Build CPU: x86_64
  CPU: x86_64
  Kernel Type: linux
  Kernel Version: 4.18.0-12-generic
  Pretty Productname: Ubuntu 18.10
  Product Type: ubuntu
  Product Version: 18.10

Qt
  Version (compiled): 5.10.0
  Version (loaded): 5.10.0

ADDITIONAL INFORMATION
Krita 4.2.0-pre-alpha (git c1b8345)
Comment 1 wolthera 2019-01-21 14:16:06 UTC
That group layers don't work is weird because it does seem to work in the save_group_layers function in layers->export, in code as 'KisSaveGroupVisitor.cpp)

---------------------------------------------------------------------------------

KisImageSP dst = new KisImage(exportDocument->createUndoStore(), r.width(), r.height(), m_image->colorSpace(), layer->name());
          dst->setResolution(m_image->xRes(), m_image->yRes());
          exportDocument->setCurrentImage(dst);
          KisPaintLayer* paintLayer = new KisPaintLayer(dst, "projection", layer->opacity());
          KisPainter gc(paintLayer->paintDevice());
          gc.bitBlt(QPoint(0, 0), layer->projection(), r);
          dst->addNode(paintLayer, dst->rootLayer(), KisLayerSP(0));

          dst->refreshGraph();
----------------------------------------------------------------------------

File layer in turn use the projection() defined in Kis_Layer.cc, which is also used by clone layers.

I'm at this point going to do a test script first.
Comment 2 wolthera 2019-01-21 15:30:56 UTC
Created attachment 117597 [details]
Other test kra file

Okay, I made a test file and a test script. The script basically copies the pixeldata to a seperate document.

I am not seeing any issues with vector, clone, file or group layers. I am seeing issues with mask-style layers, and I am seeing crashes when we call projectionPixelData on transform masks. Colorize masks work sensibly. I guess this is caused by colorize masks having an rgba color projection, while the alpha based masks do not. These alpha based masks report the color model as RGBA despite them being alpha cs too...

Note that the below script would need to be modified to handle multiple depths, so groups inside groups, but it should otherwise work for most files.
---------------------------------------------------------------------------------
from krita import *

doc =  Application.activeDocument()

destDoc = Application.createDocument(doc.width(), doc.height(), "projection", doc.colorModel(), doc.colorDepth(), doc.colorProfile(), doc.resolution())

for node in doc.rootNode().childNodes():
    newNode = destDoc.createNode(node.type(), "paintlayer")
    ba = node.projectionPixelData(0, 0, doc.width(), doc.height())
    newNode.setPixelData(ba, 0, 0, doc.width(), doc.height())
    print(node.type(), node.name(), node.colorModel(), ba.size())
    destDoc.rootNode().addChildNode(newNode, None)
    if len(node.childNodes())>0:
        for childNode in node.childNodes():
            if str(childNode.type()) != "transformmask":
                newNode = destDoc.createNode(childNode.type(), "paintlayer")
                ba = childNode.projectionPixelData(0, 0, doc.width(), doc.height())
                print(childNode.type(), childNode.name(), childNode.colorModel(), ba.size())
                newNode.setPixelData(ba, 0, 0, doc.width(), doc.height())
                destDoc.rootNode().addChildNode(newNode, None)
    
destDoc.refreshProjection()
Application.activeWindow().addView(destDoc)
Comment 3 wolthera 2019-01-21 15:34:27 UTC
My script cannot reproduce with the test file offered by Razvan, there must be an issue with his script.

That said, the transparency, filter and selection masks need to report the appropriate color model for the bytearray they deliver(this is currently incorrect, it delivers a Alpha colorspace bytearray, but reports RGBA).

Also, we need to stop the transform mask from crashing when requesting projection data.

I'll set it confirmed for those two.
Comment 4 wolthera 2019-01-21 16:50:17 UTC
Git commit c90bdf5301ca24460c0039e642860c01ac754605 by Wolthera van Hövell tot Westerflier.
Committed on 21/01/2019 at 16:50.
Pushed by woltherav into branch 'master'.

Fix crash when trying to access projectionpixeldata on transform mask.

This one was found when trying to figure out whether projection data works properly.

M  +2    -0    libs/libkis/Node.cpp

https://commits.kde.org/krita/c90bdf5301ca24460c0039e642860c01ac754605
Comment 5 wolthera 2019-01-21 17:12:42 UTC
Git commit 301ebfc6ef375cda5a8f9997cffa8bcdea63f145 by Wolthera van Hövell tot Westerflier.
Committed on 21/01/2019 at 17:09.
Pushed by woltherav into branch 'master'.

Return the colorspace of the projection before returning the colorspace of the node.

This is necessary to access the alpha color space of the mask and transparency masks. This way the
user can first convert a layer to that colorspace, then copy over the bytearray and then convert back.

This works with both projectionPixelData and regular pixelData.

Auditors: rempt

M  +6    -3    libs/libkis/Node.cpp

https://commits.kde.org/krita/301ebfc6ef375cda5a8f9997cffa8bcdea63f145
Comment 6 wolthera 2019-01-21 17:13:37 UTC
Ok, I've fixed both issues I've found. I can only reproduce this bug when I use Node::pixelData, but not with Node::projectionPixelData now. Please check.
Comment 7 wolthera 2019-01-21 17:14:51 UTC
And by reproduce I mean it is sorta expected with Node::pixeldata, the bug would only be if it happened with node::projectionpixeldata.
Comment 8 Razvan Radulescu 2019-01-23 16:43:04 UTC
OK so I think we went through a lot in the IRC chat. I'll have to book mark this for later, the script is really helpful.

At the end of the day it's because of Node.setColorProfile() and likewise I tried Document.setColorProfile() with no luck.

As for the file layer I've tried another .kra file so that was the issue there. I'm going to close this as pretty much all has been answered, as much as it could have been :)

Thanks for all the help Wolthera