0

Merge pull request #1526 from CounterPillow/webp-support

Add WebP image format support
This commit is contained in:
Nicolas F
2019-03-06 13:54:21 +01:00
committed by GitHub
5 changed files with 46 additions and 11 deletions

View File

@@ -694,16 +694,29 @@ Image options
``imgformat``
This is which image format to render the tiles into. Its value should be a
string containing "png", "jpg", or "jpeg".
string containing "png", "jpg", "jpeg" or "webp".
.. note::
For WebP, your PIL/Pillow needs to be built with WebP support. Do
keep in mind that not all browsers support WebP images.
**Default:** ``"png"``
``imgquality``
This is the image quality used when saving the tiles into the JPEG image
format. Its value should be an integer between 0 and 100.
This is the image quality used when saving the tiles into the JPEG or WebP
image format. Its value should be an integer between 0 and 100.
For WebP images in lossless mode, it determines how much effort is spent
on compressing the image.
**Default:** ``95``
``imglossless``
Determines whether a WebP image is saved in lossless or lossy mode. Has
no effect on other image formats.
**Default:** ``True``
``optimizeimg``
.. warning::

View File

@@ -533,7 +533,11 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
# only pass to the TileSet the options it really cares about
render['name'] = render_name # perhaps a hack. This is stored here for the asset manager
tileSetOpts = util.dict_subset(render, ["name", "imgformat", "renderchecks", "rerenderprob", "bgcolor", "defaultzoom", "imgquality", "optimizeimg", "rendermode", "worldname_orig", "title", "dimension", "changelist", "showspawn", "overlay", "base", "poititle", "maxzoom", "showlocationmarker", "minzoom"])
tileSetOpts = util.dict_subset(render, [
"name", "imgformat", "renderchecks", "rerenderprob", "bgcolor", "defaultzoom",
"imgquality", "imglossless", "optimizeimg", "rendermode", "worldname_orig", "title",
"dimension", "changelist", "showspawn", "overlay", "base", "poititle", "maxzoom",
"showlocationmarker", "minzoom"])
tileSetOpts.update({"spawn": w.find_true_spawn()}) # TODO find a better way to do this
for rset in rsets:
tset = tileset.TileSet(w, rset, assetMrg, tex, tileSetOpts, tileset_dir)

View File

@@ -71,6 +71,8 @@ renders = Setting(required=True, default=util.OrderedDict(),
"forcerender": Setting(required=False, validator=validateBool, default=None),
"imgformat": Setting(required=True, validator=validateImgFormat, default="png"),
"imgquality": Setting(required=False, validator=validateImgQuality, default=95),
"imglossless": Setting(required=False, validator=validateBool,
default=True),
"bgcolor": Setting(required=True, validator=validateBGColor, default="1a1a1a"),
"defaultzoom": Setting(required=True, validator=validateDefaultZoom, default=1),
"optimizeimg": Setting(required=True, validator=validateOptImg, default=[]),

View File

@@ -115,9 +115,14 @@ def validateRerenderprob(s):
return val
def validateImgFormat(fmt):
if fmt not in ("png", "jpg", "jpeg"):
if fmt not in ("png", "jpg", "jpeg", "webp"):
raise ValidationException("%r is not a valid image format" % fmt)
if fmt == "jpeg": fmt = "jpg"
if fmt == "webp":
try:
from PIL import _webp
except ImportError:
raise ValidationException("WebP is not supported by your PIL/Pillow installation")
return fmt
def validateImgQuality(qual):

View File

@@ -261,12 +261,15 @@ class TileSet(object):
rest of this discussion.
imgformat
A string indicating the output format. Must be one of 'png' or
'jpeg'
A string indicating the output format. Must be one of 'png',
'jpeg' or 'webp'
imgquality
An integer 1-100 indicating the quality of the jpeg output. Only
relevant in jpeg mode.
relevant in jpeg and webp mode.
imglossless
A boolean indicating whether to save a webp image in lossless mode.
optimizeimg
A list of optimizer instances to use.
@@ -387,8 +390,10 @@ class TileSet(object):
self.imgextension = 'png'
elif self.options['imgformat'] in ('jpeg', 'jpg'):
self.imgextension = 'jpg'
elif self.options['imgformat'] == 'webp':
self.imgextension = 'webp'
else:
raise ValueError("imgformat must be one of: 'png' or 'jpg'")
raise ValueError("imgformat must be one of: 'png', 'jpg' or 'webp'")
# This sets self.treedepth, self.xradius, and self.yradius
self._set_map_size()
@@ -1000,8 +1005,11 @@ class TileSet(object):
if imgformat == 'jpg':
img.convert('RGB').save(tmppath, "jpeg", quality=self.options['imgquality'],
subsampling=0)
else: # PNG
elif imgformat == 'png': # PNG
img.save(tmppath, "png")
elif imgformat == 'webp':
img.save(tmppath, "webp", quality=self.options['imgquality'],
lossless=self.options['imglossless'])
if self.options['optimizeimg']:
optimize_image(tmppath, imgformat, self.options['optimizeimg'])
@@ -1101,8 +1109,11 @@ class TileSet(object):
if self.imgextension == 'jpg':
tileimg.convert('RGB').save(tmppath, "jpeg", quality=self.options['imgquality'],
subsampling=0)
else: # PNG
elif self.imgextension == 'png': # PNG
tileimg.save(tmppath, "png")
elif self.imgextension == 'webp':
tileimg.save(tmppath, "webp", quality=self.options['imgquality'],
lossless=self.options['imglossless'])
if self.options['optimizeimg']:
optimize_image(tmppath, self.imgextension, self.options['optimizeimg'])
os.utime(tmppath, (max_chunk_mtime, max_chunk_mtime))