Week 25: Photoshop brush support II

Last week I worked on spray brush to make some room for Photoshop presets. This week I focused on abr format again.

I started with inspecting the Krita preset format. We save our presets as embedded text in PNG file. We use Qt for it, class QImageWriter is responsible for it. The preset is saved as XML. It used to be a text file, but Cyrille made it png file for few reasons. First was that the preset contains binary data – image of the preview stroke used in UI. Second reason is the performance. PNG compress the file nicely, huge amount of presets are loaded much faster at the Krita start-up compared to presets saved as XML files with binary data. Bonus is that you can see preview of the brush preset in Dolphin as the preset is image. Editing or viewing the XML became a problem. You can’t open the PNG in editor and change the XML of the preset easily. I needed to see the structure of the XML so I wrote easy viewer in few lines thanks to Qt. Reading the structure from Krita source code would be kill :)

Then I looked back at the ABR parser, python script written by Valek Filippov a.k.a. frob. Frob and Alexander Prokoudine did some work on Photoshop resources. I’m interested only in ABR brushes as it is part of our plan to support those. I ported Frob’s abr parser before, but there were some changes in the script lately. I tried to port them, but I don’t know if they were useful. The abr parser is becoming more general and contain some code that is useful for parsing other resources like Photoshop gradients. The structures used for saving binary data for Adobe resources share some ideas. The commit message to git repositary with changes was not very helpful – I found out this in chat with Frob.The parser is quite a hacky tool to discover what is in abr file. There isn’t specification available which would allow you to implement the abr brush. The whole parser is output of reverse engineering.

I decided to move to work on translator of the ABR brushes. Thanks to Alexander Prokoudine’s abr description I was able to start. I worked between the parser and translator for the rest of the week. I created new class that takes into account attribute, type and value parsed from abr as QString and then it put those values into classes. Every class has toXML method. That method specify how is the abr translated to our preset. It can create preset for Spray brush or Paint brush.

Let me show you how the abr looks like:

"Objc" "brushPreset 20"
"Nm  " "TEXT" "Hard Round 1 1 - shape dyn - rotation - all off/zero"
"Brsh" "Objc" "computedBrush 8"
"Dmtr" "UntF" "#Pxl 1"
"Hrdn" "UntF" "#Prc 100"
"Angl" "UntF" "#Ang 0"
"Rndn" "UntF" "#Prc 100"
"Spcn" "UntF" "#Prc 25"
"Intr" "bool" "1"
"flipX" "bool" "0"
"flipY" "bool" "0"
"useTipDynamics" "bool" "1"
"flipX" "bool" "0"
"flipY" "bool" "0"
"minimumDiameter" "UntF" "#Prc 0"
"minimumRoundness" "UntF" "#Prc 25"
"tiltScale" "UntF" "#Prc 200"
"szVr" "Objc" "brVr 3"
"bVTy" "long" "8"
"fStp" "long" "25"
"jitter" "UntF" "#Prc 0"
"angleDynamics" "Objc" "brVr 3"
"bVTy" "long" "0"
"fStp" "long" "25"
"jitter" "UntF" "#Prc 0"
"roundnessDynamics" "Objc" "brVr 3"

It was quite a lot of work to find out what does this mean and put all the structures together according what they mean. So far I managed to create preset only for computed brushes in Photoshop (ellipse-based), so the result produce something like this so far:

<Preset paintopid="paintbrush">
<param name="brush_definition">
<![CDATA[<Brush type="auto_brush" randomness="0" spacing="0.25" angle="0">
<MaskGenerator radius="0.5" ratio="1" type="circle" vfade="1" spikes="2" hfade="1"/>
</Brush>
]]></param>
</Preset>

It is not integrated into Krita yet. I have just class that translate the first brush parameters, I will add option to convert abr into set of kpp (Krita paintop presets). I would like to work further on translating Photoshop attributes into ours. It will require still a lot of work. Some features are missing and they need to be implemented, some parameters will be harder to map. E.g. abr structure contains image data and they are not parsed by Frob’s script so I will need to find a way how to connect the image data with presets. I ported some other abr parser which parses only brush masks – images. That’s already integrated in Krita. These two parsers will have to be merged somehow in the future.

This entry was posted in Krita. Bookmark the permalink.

Leave a Reply