Last week was devoted to add support for abr and vbr brushes. The abr file format comes from Adobe Photoshop, the later comes from Gimp. The motivation for this were the big collections on the web. Sites like deviantart.com are full of the artist’s collection of the abr brushes. The motivation is also interoperability with GIMP and with proprietary Adobe Photoshop. vbr brush support was postponed because it was too much work just to support abr brushes.
First day I started with exploring the abr format, so that we know each other a bit. I started to write simple code to parse it, but I found out that the issue is so complicated. Valek Filippov is working on the python script which parses abr brush, so I started with that one. Important note: We support only brush format v1, v2 and v6.2 (Photoshop CS2). The newest format is not documented at all and there is not open-source implementation around. It would require a lot of reverse engineering and that takes so much time, that we would need much more time then one week for it.
Next day I realized that it would go too slow to just work with the script and I felt that we need to draw soon. So me and Boudewijn, we googled for other sources and we found GIMP plug-in which is maintained version of the work based on this code. It parses just the bitmaps from the abr file format. That’s the basic thing you need to parse out of the brush file format. There are many other options saved in abr brushes, like the setting of the brush engine (attributes like diameter, spacing, angle…) but we don’t parse them yet. Valek Filippov’s script does. We have chance to have better support for the brushes, the settings look like our brush engine presets.
I was porting the ANSI C code which used the glib to Qt. It took two days to port it correctly. Next two days has been devoted to integration into Krita. The architecture for the brushes is powerful, but it is not easy, so I spent time investigating how it works and what do you need to do so that your brushes are correctly displayed and painted.We load all the brushes in the memory when Krita starts. Krita uses nice resource architecture, but it did not have support for importing one file as many resources. Abr brush consists of many bitmaps, which we use as brush masks so far. Sven Langkamp helped with that. Boudewijn Rempt helped a lot by doing preliminary integration code and then I was fixing it so that it works. We decided to reuse the brush chooser dialog we use for gbr brushes (other Gimp brush format). For the future it would be cool to have more features in the brush chooser dialog, or maybe we will need to write different widget for abr brushes. Some categories would be useful.
The painting with abr brushes does not work yet. I will work on the bugs. We get the correct image in the brush generation code, but we paint plain colored rectangle instead. There are some minor bugs that needs to be fixed too.
For the future it would be useful to support the attributes of the brush engine saved in the format. Our brush engine should support most of them, maybe some features will have to be coded and some are hard to implement as there is no specification for them.
Here is screenshot showing loaded abr brush into our brush chooser. The code is already in trunk, so you can at least see your brushes in the chooser. I hope we will be able to paint tonight!
13:57 update: The problem is fixed and now I paint with the abr brushes!
You may want to take a look at this too:
As if noone else was doing the reverse engineering
@Jonas: Thanks fot the link, I already contacted the author
@Alexandre: Yep, you,Valek, Alexa and me made virtual team for reverse engineering the abr brush
Thank you for this post, finally some useful piece of information. I’m doing a research on this subject, as I need to add PS brushes in my application, but haven’t found much and was just about to give up… but now, at least I have some idea where to look next… good luck with your work and please keep us posted on the progress
I’ve written an ABR viewer for Windows (didn’t like the one that’s already out there), it works fine apart from one thing. The order of the bitmap data does not match the order of the brush name information. Is this something you’ve come across? If I wasn’t displaying the brush name with the bitmap it would be fine but I’d like to match up the correct name…
Typical, now that I’ve posed the question the answer was staring me in the face! The brush data contains a ‘sampleDataTEXT’ tag which contains an ID code which matches the code in the bitmap data header!