00001
00002
00003
00004
00005 import getopt
00006 import subprocess
00007 from math import *
00008 import sys
00009 import globals
00010 import re
00011 import os
00012
00013 def clamp(num, minval, maxval):
00014 """Clamps the given number by given range.
00015
00016 If the number is smaller than minimum, the minimum is returned,
00017 it it's larger than maximum, the maximum is returned,
00018 otherwise, the unchanged number is returned.
00019 """
00020 if(num < minval):
00021 return minval
00022 elif(num > maxval):
00023 return maxval
00024 else:
00025 return num
00026
00027 def run_bash(cmd, err=False):
00028 """Executes Bash commands and returns their output.
00029
00030 If err is true, output is returned from stderr instead of stdout.
00031 """
00032 p = subprocess.Popen(cmd, shell = True, stdout = subprocess.PIPE,
00033 stderr = subprocess.PIPE)
00034 out, stderr = p.communicate()
00035 if err:
00036 return stderr.strip()
00037 return out.strip()
00038
00039 def clean_up():
00040 """Cleans the temporary directory when the program finishes work.
00041 """
00042 subprocess.call("rm -r " + globals.TEMPDIR, shell = True)
00043
00044 def file_size(filename):
00045 """Returns size of given file in bytes.
00046 """
00047 try:
00048 return int(run_bash("stat -c%s '" + filename + "'"))
00049 except ValueError:
00050 error("Can't determine size of a temporary file, probably because "+
00051 "it does not exist. Possible reason is not enough space"+
00052 "to generate temporary files.")
00053 clean_up()
00054 sys.exit(-1)
00055
00056 def file_quality(reference, filename):
00057 """Returns quality of given file compared to given reference file.
00058 """
00059 try:
00060 outstr = run_bash("gm compare -metric mae '"+ reference + "' '" +
00061 filename + "'" )
00062 for line in outstr.split("\n"):
00063 if "Total" in line:
00064
00065 floatre = re.compile("\d\.?\d*")
00066 errorstr = floatre.findall(line)[0]
00067 return 100.0 - 100 * float(errorstr)
00068 except ValueError:
00069 error("Can't determine quality of a temporary file, probably "+
00070 "because it is corrupted. Possible reason is not enough "+
00071 "space to generate temporary files.")
00072 clean_up()
00073 sys.exit(-1)
00074
00075 def file_convert(format, settings, filename, outfilename,
00076 sizeargs=[0, 0, False]):
00077 """Converts the given file according to given parameters.
00078 """
00079 cmd = "convert "
00080 width = sizeargs[0]
00081 height = sizeargs[1]
00082 stretch = sizeargs[2]
00083 if width or height:
00084 cmd = cmd + "-resize "
00085 if width:
00086 cmd = cmd + str(width)
00087 if height:
00088 cmd = cmd + "x"+str(height)
00089 if width and height and stretch:
00090 cmd = cmd + "!"
00091 if not globals.NOSTRIP:
00092 cmd = cmd + " +profile \"*\" "
00093 if format == "jpg":
00094 cmd = cmd + "-sampling-factor " + str(settings.SamplingFactor) + " "
00095 cmd = cmd + "-quality " + str(settings.Quality) + " "
00096 if settings.Grayscale:
00097 cmd += "-colorspace Gray -colors 256 "
00098 if settings.Interlace:
00099 cmd = cmd + "-interlace Line "
00100 if settings.Optimize:
00101 cmd = cmd + "-define jpeg:optimize-coding=true "
00102 else:
00103 cmd = cmd + "-define jpeg:optimize-coding=false "
00104 if format == "png":
00105 if settings.Interlace:
00106 cmd = cmd + "-interlace Line "
00107 if settings.Mode == "palette":
00108 cmd = cmd + "-colors " + str(2 ** settings.BitDepth) + " "
00109 if settings.Mode == "gray":
00110 cmd = cmd + "-colorspace Gray -colors "\
00111 + str(2 ** settings.BitDepth) + " "
00112 cmd = cmd + "-quality " + str(settings.Level) + str(settings.Filter)\
00113 + " "
00114 if format == "gif":
00115 if settings.Interlace:
00116 cmd = cmd + "-interlace Line "
00117 cmd = cmd + "-colors " + str(2 ** settings.BitDepth) + " "
00118 cmd = cmd + "'" + filename + "' '" + outfilename + "'"
00119 subprocess.call(cmd, shell = True)
00120 if format == "png" and settings.Advpng:
00121 subprocess.call("advpng -4 -z '" + outfilename + "'" , shell = True)
00122
00123 def valid_number(input, default, command="UNKNOWN", min=0, max=100,
00124 isfloat=False):
00125 """Validates input as int and returns int.
00126
00127 If input is invalid, prints warning about given command passing
00128 wrong value and returns given default value.
00129 """
00130 try:
00131 if isfloat:
00132 return clamp(float(input), min, max)
00133 else:
00134 return clamp(int(input), min, max)
00135 except ValueError:
00136 typestr = "int"
00137 if isfloat:
00138 typestr = "float"
00139 warning("Wrong value passed by "+ command + " : using default." +
00140 " Min value: " + str(min) + " Max value: " + str(max) +
00141 " Type of value: " + typestr + " Given value: " + input)
00142 return default
00143
00144 def valid_number_str(input, default, command="UNKNOWN", min=0, max=100,
00145 isfloat=False):
00146 """Validates input as int and returns string.
00147
00148 If input is invalid, prints warning about given command passing
00149 wrong value and returns given default value.
00150 """
00151 return str(valid_number(input, default, command, min, max, isfloat))
00152
00153 def valid_number_str_suffix(input, default, sufx, command, min, max,
00154 isfloat=False):
00155 """Validates input as int with suffix and returns string.
00156
00157 If input is invalid, prints warning about given command passing
00158 wrong value and returns given default value.
00159 """
00160 return valid_number_str(input[ :-len(sufx)], default, command +
00161 " with suffix " + sufx, min, max, isfloat) + sufx
00162
00163 def output(input, verbosity = 2):
00164 """Print output
00165 """
00166 if globals.VERBOSITY >= verbosity:
00167 print input
00168 sys.stdout.flush()
00169
00170 def warning(input):
00171 """Print a warning
00172 """
00173 output("WARNING: " + input, 1)
00174
00175 def error(input):
00176 """Print an error
00177 """
00178 output("ERROR: " + input, 0)
00179