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:
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):
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:
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.