0

Clarify optimizeimg docs; add warnings

The validator will now warn if it detects that a crushed output
is fed into something that is not a crusher.

The is_crusher method of an optimizer shall return True if the
optimisation process is lossless, and does try to find optimal
encoding parameters as opposed to only removing unneeded channels
or reducing palettes.
This commit is contained in:
CounterPillow
2014-05-08 20:49:41 +02:00
parent a39c45d473
commit 6d28942626
3 changed files with 34 additions and 9 deletions

View File

@@ -39,6 +39,10 @@ class Optimizer:
if (not exists_in_path(self.binaryname)) and (not exists_in_path(self.binaryname + ".exe")):
raise Exception("Optimization program '%s' was not found!" % self.binaryname)
def is_crusher(self):
"""Should return True if the optimization is lossless, i.e. none of the actual image data will be changed."""
raise NotImplementedError("I'm so abstract I can't even say whether I'm a crusher.")
class NonAtomicOptimizer(Optimizer):
@@ -84,6 +88,9 @@ class pngnq(NonAtomicOptimizer, PNGOptimizer):
NonAtomicOptimizer.fire_and_forget(self, args, img)
def is_crusher(self):
return False
class pngcrush(NonAtomicOptimizer, PNGOptimizer):
binaryname = "pngcrush"
# really can't be bothered to add some interface for all
@@ -98,6 +105,9 @@ class pngcrush(NonAtomicOptimizer, PNGOptimizer):
NonAtomicOptimizer.fire_and_forget(self, args, img)
def is_crusher(self):
return True
class optipng(Optimizer, PNGOptimizer):
binaryname = "optipng"
@@ -106,6 +116,9 @@ class optipng(Optimizer, PNGOptimizer):
def optimize(self, img):
Optimizer.fire_and_forget(self, [self.binaryname, "-o" + str(self.olevel), "-quiet", img])
def is_crusher(self):
return True
def optimize_image(imgpath, imgformat, optimizers):

View File

@@ -160,16 +160,25 @@ def validateBGColor(color):
def validateOptImg(optimizers):
if isinstance(optimizers, (int, long)):
from optimizeimages import pngcrush
logging.warning("You're using a deprecated definition of optimizeimg. We'll do what you say for now, but please fix this as soon as possible.")
logging.warning("You're using a deprecated definition of optimizeimg. "\
"We'll do what you say for now, but please fix this as soon as possible.")
optimizers = [pngcrush()]
if not isinstance(optimizers, list):
raise ValidationException("optimizeimg is not a list. Make sure you specify them like [foo()], with square brackets.")
for opt in optimizers:
raise ValidationException("What you passed to optimizeimg is not a list. "\
"Make sure you specify them like [foo()], with square brackets.")
for opt, next_opt in zip(optimizers, optimizers[1:]) + [(optimizers[-1], None)]:
if not isinstance(opt, Optimizer):
raise ValidationException("Invalid Optimizer!")
opt.check_availability()
# Check whether the chaining is somewhat sane
if next_opt:
if opt.is_crusher() and not next_opt.is_crusher():
logging.warning("You're feeding a crushed output into an optimizer that does not crush. "\
"This is most likely pointless, and wastes time.")
return optimizers
def validateTexturePath(path):