A Pathfinder Hero Lab to Maptool converter

Show off your RPG maps, campaigns, and tokens. Share your gaming experiences and stories under General Discussion and save this forum for things you've created that may help others run their own games. Use the subforums when appropriate.

Moderators: Azhrei, dorpond, trevor, Gamerdude

gunnerhauklund
Kobold
Posts: 2
Joined: Wed Jul 13, 2011 11:14 am

Re: A Pathfinder Hero Lab to Maptool converter

Post by gunnerhauklund »

This is pretty spectacular. Thanks for the hard work. Do you know why the macros might be doubling up on some of the outputs though?

[spoiler=||| IMAGE |||]Image[/spoiler]

Here is the undedited code


Code: Select all

<table border='1' cellpadding='0' cellspacing='0' style='width:200px'>
<tr bgcolor='red'>
<td><span style='color:white'><b>Greatclub(×2)</b></span></td>
<td><span style='color:white'><b>Damage</b></span></td>
</tr>
<tr>
<td>[e:d20 + 7]</td>
<td>[e:2d8+7]</td>
</tr>
</table>
Last edited by aliasmask on Wed Mar 19, 2014 11:19 pm, edited 1 time in total.
Reason: Fixed image tag and added spoiler

User avatar
aliasmask
Deity
Posts: 8580
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: A Pathfinder Hero Lab to Maptool converter

Post by aliasmask »

I noticed this as well and didn't really think about it. Try and uncheck "insert smiles" under Edit | Preferences in the Interactions TAB in the Chat grouping and see if that works. There's a known bug with smiles that can cause duplicate output on rolls.

gunnerhauklund
Kobold
Posts: 2
Joined: Wed Jul 13, 2011 11:14 am

Re: A Pathfinder Hero Lab to Maptool converter

Post by gunnerhauklund »

That did the trick. Thank you so much!

Tinalles
Kobold
Posts: 24
Joined: Sun May 27, 2012 9:39 pm

Re: A Pathfinder Hero Lab to Maptool converter

Post by Tinalles »

Hi! Sorry to bump this somewhat older thread.

I've just started using hl2mt. Mainly since Hero Lab 5.3 appears to have broken TokenLab -- something about the exported XML that TokenLab depends on changed, and now it chokes with a Null Pointer exception.

Anyway, I've gotten hl2mt up and running. Is there any way to make it stop shrinking the handout images to thumbnail size? The whole point of a handout is to present the full size picture. Having a "handout" that's only 10 pixels larger than the mouse-over thumbnail kind of defeats the purpose.

Also, is there anyway to conceal the results of rolls? I'm the GM, and I'd like to have the option to fudge rolls (either to save my players' butts or make their lives more complicated). It's hard to do that when everyone can see the rolls in plain sight in the chat log.

Still experimenting. Parts of it I like very much. TokenLab's lack of any way to determine the basic ability scores of a character was a constant pain. So the ability check buttons are much appreciated. I miss the automagic critical calculation TokenLab had; but it'll be okay. Clicking the button again to confirm a crit is not a difficult task.

So far my least favorite aspect is that TokenLab apparently uses a different Pathfinder framework than the one hl2mt uses -- so either I need to figure out how to adjust hl2mt so that it generates tokens that work with the TokenLab framework, or else I need to reconfigure my campaign files and remake ALL my existing tokens. Yikes.

Tinalles
Kobold
Posts: 24
Joined: Sun May 27, 2012 9:39 pm

Re: A Pathfinder Hero Lab to Maptool converter

Post by Tinalles »

Aaaand starting off my career on this forum with a double post! Oh, my aching karma. But apparently I don't have permission to edit my own posts. Sorry.

I've been poking through the hl2mt source code and found the function that handles making a token portrait:

Code: Select all

   def make_portrait(self, image_name):

      im = Image.open(str(image_name))
      size = (200, 200)
      im.thumbnail(size, Image.ANTIALIAS)

      output = StringIO.StringIO()
      im.save(output, 'png')
      self.portrait_md5 = hashlib.md5(output.getvalue()).hexdigest()
      output.close()

      self.portrait_asset = self.portrait_md5 + '.png'
      self.portrait_xml = '<net.rptools.maptool.model.Asset>\n <id>\n <id>' + self.portrait_md5 + \
                     '</id>\n </id>\n <name>' + self.name + \
                     '</name>\n <extension>png</extension>\n <image/>\n</net.rptools.maptool.model.Asset>\n'

      self.portrait = im


I don't know a whole lot about Python, but it looks like the code is automatically shrinking everything to 200x200 pixels (but retaining the original aspect ratio, so nothing gets squished/stretched). Then it's saving that thumbnail in PNG format and attaching it to the token. At a guess, I'd say the whole point of this routine is to reduce the file size of the finished token.

Great! Except that for this specific purpose, using these specific types of images, PNG is an objectively bad file format. Let's take a look at an example. Here's a character portrait I found on DeviantArt:

Image

That's pretty typical for a character portrait. This is in JPG format, it looks fine, and its file size is 97.37 KB.

Now here's the same image, resized to 200px wide and saved as a PNG (I used Paint.net for this):

Image

It's a lot smaller (1/3rd as wide), so much of the fine detail is lost. The fancy script that says "Tarja" is notably more difficult to read. And the file size is 114.66 KB. That's right, we lost visual detail AND increased the finished file size!

Don't get me wrong; PNG is a great file format for many applications. Its support for transparency is terrific, and it's got lossless compression that does a pretty good job of keeping the file size reasonable. BUT, for this specific application, transparency is irrelevant: MapTool doesn't use transparency on handout images. It just fills in the background with a solid color -- grey, I think.

And as for file size, well, PNG's compression algorithms are designed, first and foremost, to preserve an exact, bit-for-bit representation of the image. It's lossless compression. That's great, but it tends to work best on things with large areas of solid color with sharply defined boundaries between them. For example, PNG compression works great on sports logos.

Character portraits, however, are not like that. They tend to be much more like photographs: they have many subtle gradations of color value, often in quite small areas. PNG compression struggles with that. But JPEG format was specifically designed to handle that kind of data, and it does it well. Here's a third variant of the image:

Image

This one has the same dimensions as the original (600x762). It's in JPG format, with 70% quality (compared to 95% on the original). It looks pretty much identical. Try putting the original side by side with the variant and flipping back and forth between them. There is some loss of detail -- notably around the highlights of her cheekbones -- but you have to be looking really close to notice it. And the file size is only 53.54 KB, compared to 97.37 KB for the original. The 70% quality one is roughly half the size of the original, with a degradation in visual quality so minor that probably no one will ever notice without being told to look for it.

So, could I please suggest two improvements?

1) Use JPG for the format of handout images. 70% quality ratio would be fine; I sometimes go lower, but not often. You'd need to do the resizing and saving as two steps, though, as per this StackOverflow answer.

2) Make the portrait resizing configurable. This could be a textbox labeled "Target portrait dimensions": enter a value that would be used as the target width/height, defaulting to 600. If it's set to zero then it passes the images through without rescaling them.

If there's a way to submit patches to hl2mt, I might fumble my way through enough Python to make these changes myself and submit a patch.

[1] "Tarja" image licensed Creative Commons Attribution 3.0, courtesy of Arianart.

Dracones
Cave Troll
Posts: 68
Joined: Mon Nov 14, 2011 8:04 pm
Location: Fort Pierce, FL

Re: A Pathfinder Hero Lab to Maptool converter

Post by Dracones »

You're correct, that bit of code is what gets the image file, shrinks it(thumbnail function) and then re-outputs to PNG. The primary reason for the shrinking is because hl2mt is designed to work on large sets of tokens where you can just throw together some Hero Lab files, token images and portrait images and have it bundle it all together with decent defaults. The resize is there so you can just toss in all sorts of image sizes into your portraits folder and have it produce decent results in the tokens.

I'll look into putting an option field in for that and converting over to JPG.

For anyone who wants to hack on this, it's written in Python 2.7 using PyQt4. It uses some other Python modules(re, glob, zipfile) but they're all pretty standard outside of PyQt4. I then use PyInstaller to compile the project into binary files, but that isn't needed at all to run it if you have the Python stuff installed(just use: "python hl2mt.py" to run it via the code).

Tinalles
Kobold
Posts: 24
Joined: Sun May 27, 2012 9:39 pm

Re: A Pathfinder Hero Lab to Maptool converter

Post by Tinalles »

Nice, thanks. I've got a dev environment properly set up now, I think. aboutDialog.ui and htmlDialog.ui needed to be run through pyuuic4 to create the .py versions for import.

It looks like the source distribution is missing ui/macrosDialog ...? At any rate, Python claims it can't import macrosDialog, and the ui folder doesn't seem to have any files of that name.

Dracones
Cave Troll
Posts: 68
Joined: Mon Nov 14, 2011 8:04 pm
Location: Fort Pierce, FL

Re: A Pathfinder Hero Lab to Maptool converter

Post by Dracones »

Tinalles wrote:Nice, thanks. I've got a dev environment properly set up now, I think. aboutDialog.ui and htmlDialog.ui needed to be run through pyuuic4 to create the .py versions for import.

It looks like the source distribution is missing ui/macrosDialog ...? At any rate, Python claims it can't import macrosDialog, and the ui folder doesn't seem to have any files of that name.


Yeah, it's missing that. I've added it now. I was using PyCharm back then to commit things and it can miss the UI files since those aren't tracked by the IDE.

But yeah, pyuic4 creates python files from the UI files which are created from designer-qt4. That's all called from hl2mt.py for the user interface, which calls herolab.py for dealing with finding/going over all the Hero Lab files which calls token.py which is what does pretty much all the work creating the token.

This was my first PyQt project and I really found it to be a pleasure to work with.

Tinalles
Kobold
Posts: 24
Joined: Sun May 27, 2012 9:39 pm

Re: A Pathfinder Hero Lab to Maptool converter

Post by Tinalles »

Yay, it runs!

Uh, what processor architecture were you coding against? 32 bit or 64 bit? I set up a 64-bit environment without even stopping to think. Then the very last thing which prevented hl2mt.py from running was that the Python Imaging Library isn't available for amd64. I substituted pillow instead, but it required replacing "import Image" in token.py with "from PIL import Image".

If I should be coding against a 32-bit environment, let me know so I can tear out everything I just did and redo it. :roll:

Dracones
Cave Troll
Posts: 68
Joined: Mon Nov 14, 2011 8:04 pm
Location: Fort Pierce, FL

Re: A Pathfinder Hero Lab to Maptool converter

Post by Dracones »

I'm using AMD64. I got PIL from the Debian python-pil package. Using pillow is fine, I only went with PIL because it's easy to install on Windows and I was making binaries for every platform.

Tinalles
Kobold
Posts: 24
Joined: Sun May 27, 2012 9:39 pm

Re: A Pathfinder Hero Lab to Maptool converter

Post by Tinalles »

Okay, great.

I have kind of an odd setup. The source repo is living on a headless Ubuntu server, and is mapped to a windows drive via Samba. When I actually need to run Python, I'm doing it from a Windows command prompt. So at any given time I have a Windows command prompt and a Linux command prompt up through PuTTY, and have to keep remembering whether I'm typing commands for Windows or Linux.

I'm working on setting up configurable handout sizes, and using JPG as the handout size. So far it's not working, but I'll keep plugging away at it and try not to bother you with noobish Python questions.

EDIT: hey, I can edit my posts now. Neat.

Progress! I have made usefulness. Specifically, I've made a new setting for the handout sizing, as described above. Setting it to 0 passes them through unresized, and any other value makes it resize them to the target value (respecting aspect ratio). And it prefers JPG for output, with 70% quality.

I haven't quite figured out how to put a label on the textbox for the setting. Currently it's unlabeled. But it works! And all it took was about 8 hours of agony.

This code will not run as expected:

Code: Select all

        if not self.settings.contains('portraitSize'):
            self.settings.setValue('portraitSize', "600")


Why not, you ask? Because something (QT perhaps?) initializes a property called "portraitSize" long before we get to this part of the file. The line setting the value to 600 never executes, because there's already a portraitSize property in the settings. And that naturally bollixes everything up. As soon as I changed the name to "handoutsize" instead, it started working.

Dracones, I'd like to contribute this code back. Do you have a procedure for that? Should I send a pull request via Mercurial? Do you want a separate branch till you've vetted it? Let me know.

Tinalles
Kobold
Posts: 24
Joined: Sun May 27, 2012 9:39 pm

Re: A Pathfinder Hero Lab to Maptool converter

Post by Tinalles »

Hi again! Had my first session last night using tokens generated by my variant of hl2mt, and ran into an odd problem: the portraits load fine on the GM side, but not on the player side. When viewing a handout or a portrait thumbnail, the player receives an error saying "Received an invalid image: " followed by the MD5 image identifier. It then defaults to the big red question mark for a missing image asset.

Furthermore, if the player switches to a map containing one of the new tokens, it will fail to load. It gets as far as the first token, reports the "invalid image" error, and then the load stalls and never completes. The player is free to switch to another map, but will be unable to view the map containing one of those tokens until the token is deleted.

I was able to reproduce the problem with the following steps:

1) GM side: Created a blank campaign with the Pathfinder hl2mt campaign properties, started a server.
2) Player side: Connected from my laptop.
3) GM side: Made a new map and placed a single affected token in it (sample token attached).
4) Player side: tried to switch to the new map; load fails.
5) GM side: delete the token.
6) Player side: switch to the map; load succeeds.
7) GM side: Place the token again.
8) Player side: token loads partially; pog is okay, macros okay, but mousing over will cause an "Invalid image" error, the thumbnail portrait won't load, and the handout won't load.

I cracked open the token and took a look at its contents. It looks okay as far as I can tell. In the case of the attached token, Trina.rptok, the invalid ID that it reports is "ce5d1126ba52ba1618c402a13bee1c0c". I checked a bunch of stuff::

- The token's assets folder contains a file named ce5d1126ba52ba1618c402a13bee1c0c

- The ce5d1126ba52ba1618c402a13bee1c0c file has the following contents:

Code: Select all

<net.rptools.maptool.model.Asset>
  <id>
    <id>ce5d1126ba52ba1618c402a13bee1c0c</id>
  </id>
  <name>Trina</name>
  <extension>jpg</extension>
  <image/>
</net.rptools.maptool.model.Asset>


The id matches, and the extension is correct.

- The file ce5d1126ba52ba1618c402a13bee1c0c.jpg exists in the assets folder, and works fine in every image program I've tried.

- The content.xml file contains the following bit:

Code: Select all

    <charsheetImage>
      <id>ce5d1126ba52ba1618c402a13bee1c0c</id>
    </charsheetImage>
    <portraitImage reference="../charsheetImage"/>


That ID matches, and the reference seems to match.

From some Googling, it looks like the error is happening somewhere in the AssetTransferHandler. But I have no earthly idea what that does, or how to make it report what it thinks the ID should actually be.

The problem is doubtless something in content.xml -- I've probably missed some necessary modification. The really weird thing is that these tokens work just fine on the GM side, and only display the broken behavior on the client side. What am I missing?

I've attached a zip file containing the full source code of my modified version of hl2mt.
Attachments
hl2mt-tinalles-broken.zip
Source code for my broken mod of hl2mt, sigh.
(1023.63 KiB) Downloaded 61 times
Trina.rptok
Malfunctioning token.
(536.63 KiB) Downloaded 65 times

Tinalles
Kobold
Posts: 24
Joined: Sun May 27, 2012 9:39 pm

Re: A Pathfinder Hero Lab to Maptool converter

Post by Tinalles »

For the sake of thoroughness, I should just say that I got this working. The problem was in my variant of hl2mt, not in MapTool.

Specifically, the problem was that hl2mt was compressing the image data twice: once when making the handout, and again when writing it to disk. In both cases, it was using PNG format. I found and modified the first one to use JPG, and recorded the MD5 sum of the JPG data. Then later, hl2mt was changing it back to PNG, so that the data's md5sum no longer matched the one recorded earlier. Any time that token got sent through a network connection, the receiving Maptool would check the MD5 sum to see if the image came through intact, the two wouldn't match, and the token therefore failed to work correctly.

The solution was to convert it to JPG format just once, when the token is created, then pass that data to the token creation routine through a variable. The data is then written to disk without further modification, the MD5 sums match, and all is well.

I'm enjoying this. It's very comprehensive, and a lot easier to use for batch creation of tokens. It's a little harder than TokenLab was when I just need a one-off token, though. Often times I'll quickly stat up a monster in Hero Lab in the midst of a session. Then making the token for that monster requires regenerating ALL the tokens for all the .por files in my tokens root folder, followed by uploading the accompanying HTML files to a server. I may look into modifying the "Process Files" button to add a step where it asks which .por files you actually want to process.

Dracones
Cave Troll
Posts: 68
Joined: Mon Nov 14, 2011 8:04 pm
Location: Fort Pierce, FL

Re: A Pathfinder Hero Lab to Maptool converter

Post by Dracones »

Yeah, the app was made with a batch workflow mindset. For myself I renamed all the Hero Lab stock files over to por and I'd batch convert them all. So something like 3000+ entries at once.

If I was working on a smaller subset I'd just work with different directories and import/export config files. For example with Skull and Shackles I'd download the community por files for the adventure path, load and clean them up, re-save and then dig around for images for tokens and portraits. Then I'd just batch covert that directory over.

Looking at my directory I have separate work areas for base(113 Por files here), PCs, crypt of the everflame, Burnt Offerings(Rise of the Runelords AP), Skull and Shackles, Master of the Fallen Fortress and a directory of Iconics(15 and 20 point builds).

Sadly Pathfinder was a little too crunchy for me and I've since moved onto 5e. :(

Tinalles
Kobold
Posts: 24
Joined: Sun May 27, 2012 9:39 pm

Re: A Pathfinder Hero Lab to Maptool converter

Post by Tinalles »

If I were running an AP, I would totally do that. And I'm working on setting up a repository that will do all the creatures in all four bestiaries -- hl2mt is perfect for that kind of thing, and it helps a lot with random encounters.

The rest of the campaign is homebrew. No pre-existing stat blocks, and fairly often I'll need to make up NPCs on the fly. hl2mt is less good at that. Is there a built-in mechanism for switching between sets of folders?

Still, this is good stuff. And I'm confident I can keep using it long-term, which is a plus. I liked TokenLab, but when the original author faded away, a Hero Lab update broke it, and I didn't know enough Java to fix it -- that left me up the creek. Python is substantially easier to deal with.

Post Reply

Return to “User Creations”