Added code to convert colors to #RRGGBB format
This commit is contained in:
parent
823c8c45e3
commit
a7d2593a58
4 changed files with 250 additions and 18 deletions
238
scour.py
238
scour.py
|
|
@ -30,9 +30,6 @@
|
|||
# * Specify a limit to the precision of all positional elements.
|
||||
# * Clean up Definitions
|
||||
# * Collapse duplicate gradient definitions
|
||||
# * Clean up CSS
|
||||
# * Convert RGB colours from RGB(r,g,b) to #RRGGBB format
|
||||
# * Convert RGB colours from #RRGGBB to #RGB if possible
|
||||
# * Clean up paths
|
||||
# * Eliminate last segment in a polygon
|
||||
# * Collapse straight curves.
|
||||
|
|
@ -46,10 +43,10 @@
|
|||
# Next Up:
|
||||
# + Up-revved enthought's path parser for integer coords with sci notation:
|
||||
# https://svn.enthought.com/enthought/changeset/23583?format=diff&new=23583
|
||||
# + Convert rgb() into #RRGGBB
|
||||
# + Convert #RRGGBB into #RGB where possible
|
||||
# - prevent elements from being stripped if they are referenced in a <style> element
|
||||
# (for instance, filter, marker, pattern) - need a crude CSS parser
|
||||
# - Convert all colors to #RRGGBB format
|
||||
# - Reduce #RRGGBB format to #RGB format when possible
|
||||
# - Remove any unused glyphs from font elements?
|
||||
|
||||
# necessary to get true division
|
||||
|
|
@ -125,7 +122,156 @@ svgAttributes = [
|
|||
'visibility'
|
||||
]
|
||||
|
||||
|
||||
colors = {
|
||||
'aliceblue': 'rgb(240, 248, 255)',
|
||||
'antiquewhite': 'rgb(250, 235, 215)',
|
||||
'aqua': 'rgb( 0, 255, 255)',
|
||||
'aquamarine': 'rgb(127, 255, 212)',
|
||||
'azure': 'rgb(240, 255, 255)',
|
||||
'beige': 'rgb(245, 245, 220)',
|
||||
'bisque': 'rgb(255, 228, 196)',
|
||||
'black': 'rgb( 0, 0, 0)',
|
||||
'blanchedalmond': 'rgb(255, 235, 205)',
|
||||
'blue': 'rgb( 0, 0, 255)',
|
||||
'blueviolet': 'rgb(138, 43, 226)',
|
||||
'brown': 'rgb(165, 42, 42)',
|
||||
'burlywood': 'rgb(222, 184, 135)',
|
||||
'cadetblue': 'rgb( 95, 158, 160)',
|
||||
'chartreuse': 'rgb(127, 255, 0)',
|
||||
'chocolate': 'rgb(210, 105, 30)',
|
||||
'coral': 'rgb(255, 127, 80)',
|
||||
'cornflowerblue': 'rgb(100, 149, 237)',
|
||||
'cornsilk': 'rgb(255, 248, 220)',
|
||||
'crimson': 'rgb(220, 20, 60)',
|
||||
'cyan': 'rgb( 0, 255, 255)',
|
||||
'darkblue': 'rgb( 0, 0, 139)',
|
||||
'darkcyan': 'rgb( 0, 139, 139)',
|
||||
'darkgoldenrod': 'rgb(184, 134, 11)',
|
||||
'darkgray': 'rgb(169, 169, 169)',
|
||||
'darkgreen': 'rgb( 0, 100, 0)',
|
||||
'darkgrey': 'rgb(169, 169, 169)',
|
||||
'darkkhaki': 'rgb(189, 183, 107)',
|
||||
'darkmagenta': 'rgb(139, 0, 139)',
|
||||
'darkolivegreen': 'rgb( 85, 107, 47)',
|
||||
'darkorange': 'rgb(255, 140, 0)',
|
||||
'darkorchid': 'rgb(153, 50, 204)',
|
||||
'darkred': 'rgb(139, 0, 0)',
|
||||
'darksalmon': 'rgb(233, 150, 122)',
|
||||
'darkseagreen': 'rgb(143, 188, 143)',
|
||||
'darkslateblue': 'rgb( 72, 61, 139)',
|
||||
'darkslategray': 'rgb( 47, 79, 79)',
|
||||
'darkslategrey': 'rgb( 47, 79, 79)',
|
||||
'darkturquoise': 'rgb( 0, 206, 209)',
|
||||
'darkviolet': 'rgb(148, 0, 211)',
|
||||
'deeppink': 'rgb(255, 20, 147)',
|
||||
'deepskyblue': 'rgb( 0, 191, 255)',
|
||||
'dimgray': 'rgb(105, 105, 105)',
|
||||
'dimgrey': 'rgb(105, 105, 105)',
|
||||
'dodgerblue': 'rgb( 30, 144, 255)',
|
||||
'firebrick': 'rgb(178, 34, 34)',
|
||||
'floralwhite': 'rgb(255, 250, 240)',
|
||||
'forestgreen': 'rgb( 34, 139, 34)',
|
||||
'fuchsia': 'rgb(255, 0, 255)',
|
||||
'gainsboro': 'rgb(220, 220, 220)',
|
||||
'ghostwhite': 'rgb(248, 248, 255)',
|
||||
'gold': 'rgb(255, 215, 0)',
|
||||
'goldenrod': 'rgb(218, 165, 32)',
|
||||
'gray': 'rgb(128, 128, 128)',
|
||||
'grey': 'rgb(128, 128, 128)',
|
||||
'green': 'rgb( 0, 128, 0)',
|
||||
'greenyellow': 'rgb(173, 255, 47)',
|
||||
'honeydew': 'rgb(240, 255, 240)',
|
||||
'hotpink': 'rgb(255, 105, 180)',
|
||||
'indianred': 'rgb(205, 92, 92)',
|
||||
'indigo': 'rgb( 75, 0, 130)',
|
||||
'ivory': 'rgb(255, 255, 240)',
|
||||
'khaki': 'rgb(240, 230, 140)',
|
||||
'lavender': 'rgb(230, 230, 250)',
|
||||
'lavenderblush': 'rgb(255, 240, 245)',
|
||||
'lawngreen': 'rgb(124, 252, 0)',
|
||||
'lemonchiffon': 'rgb(255, 250, 205)',
|
||||
'lightblue': 'rgb(173, 216, 230)',
|
||||
'lightcoral': 'rgb(240, 128, 128)',
|
||||
'lightcyan': 'rgb(224, 255, 255)',
|
||||
'lightgoldenrodyellow': 'rgb(250, 250, 210)',
|
||||
'lightgray': 'rgb(211, 211, 211)',
|
||||
'lightgreen': 'rgb(144, 238, 144)',
|
||||
'lightgrey': 'rgb(211, 211, 211)',
|
||||
'lightpink': 'rgb(255, 182, 193)',
|
||||
'lightsalmon': 'rgb(255, 160, 122)',
|
||||
'lightseagreen': 'rgb( 32, 178, 170)',
|
||||
'lightskyblue': 'rgb(135, 206, 250)',
|
||||
'lightslategray': 'rgb(119, 136, 153)',
|
||||
'lightslategrey': 'rgb(119, 136, 153)',
|
||||
'lightsteelblue': 'rgb(176, 196, 222)',
|
||||
'lightyellow': 'rgb(255, 255, 224)',
|
||||
'lime': 'rgb( 0, 255, 0)',
|
||||
'limegreen': 'rgb( 50, 205, 50)',
|
||||
'linen': 'rgb(250, 240, 230)',
|
||||
'magenta': 'rgb(255, 0, 255)',
|
||||
'maroon': 'rgb(128, 0, 0)',
|
||||
'mediumaquamarine': 'rgb(102, 205, 170)',
|
||||
'mediumblue': 'rgb( 0, 0, 205)',
|
||||
'mediumorchid': 'rgb(186, 85, 211)',
|
||||
'mediumpurple': 'rgb(147, 112, 219)',
|
||||
'mediumseagreen': 'rgb( 60, 179, 113)',
|
||||
'mediumslateblue': 'rgb(123, 104, 238)',
|
||||
'mediumspringgreen': 'rgb( 0, 250, 154)',
|
||||
'mediumturquoise': 'rgb( 72, 209, 204)',
|
||||
'mediumvioletred': 'rgb(199, 21, 133)',
|
||||
'midnightblue': 'rgb( 25, 25, 112)',
|
||||
'mintcream': 'rgb(245, 255, 250)',
|
||||
'mistyrose': 'rgb(255, 228, 225)',
|
||||
'moccasin': 'rgb(255, 228, 181)',
|
||||
'navajowhite': 'rgb(255, 222, 173)',
|
||||
'navy': 'rgb( 0, 0, 128)',
|
||||
'oldlace': 'rgb(253, 245, 230)',
|
||||
'olive': 'rgb(128, 128, 0)',
|
||||
'olivedrab': 'rgb(107, 142, 35)',
|
||||
'orange': 'rgb(255, 165, 0)',
|
||||
'orangered': 'rgb(255, 69, 0)',
|
||||
'orchid': 'rgb(218, 112, 214)',
|
||||
'palegoldenrod': 'rgb(238, 232, 170)',
|
||||
'palegreen': 'rgb(152, 251, 152)',
|
||||
'paleturquoise': 'rgb(175, 238, 238)',
|
||||
'palevioletred': 'rgb(219, 112, 147)',
|
||||
'papayawhip': 'rgb(255, 239, 213)',
|
||||
'peachpuff': 'rgb(255, 218, 185)',
|
||||
'peru': 'rgb(205, 133, 63)',
|
||||
'pink': 'rgb(255, 192, 203)',
|
||||
'plum': 'rgb(221, 160, 221)',
|
||||
'powderblue': 'rgb(176, 224, 230)',
|
||||
'purple': 'rgb(128, 0, 128)',
|
||||
'red': 'rgb(255, 0, 0)',
|
||||
'rosybrown': 'rgb(188, 143, 143)',
|
||||
'royalblue': 'rgb( 65, 105, 225)',
|
||||
'saddlebrown': 'rgb(139, 69, 19)',
|
||||
'salmon': 'rgb(250, 128, 114)',
|
||||
'sandybrown': 'rgb(244, 164, 96)',
|
||||
'seagreen': 'rgb( 46, 139, 87)',
|
||||
'seashell': 'rgb(255, 245, 238)',
|
||||
'sienna': 'rgb(160, 82, 45)',
|
||||
'silver': 'rgb(192, 192, 192)',
|
||||
'skyblue': 'rgb(135, 206, 235)',
|
||||
'slateblue': 'rgb(106, 90, 205)',
|
||||
'slategray': 'rgb(112, 128, 144)',
|
||||
'slategrey': 'rgb(112, 128, 144)',
|
||||
'snow': 'rgb(255, 250, 250)',
|
||||
'springgreen': 'rgb( 0, 255, 127)',
|
||||
'steelblue': 'rgb( 70, 130, 180)',
|
||||
'tan': 'rgb(210, 180, 140)',
|
||||
'teal': 'rgb( 0, 128, 128)',
|
||||
'thistle': 'rgb(216, 191, 216)',
|
||||
'tomato': 'rgb(255, 99, 71)',
|
||||
'turquoise': 'rgb( 64, 224, 208)',
|
||||
'violet': 'rgb(238, 130, 238)',
|
||||
'wheat': 'rgb(245, 222, 179)',
|
||||
'white': 'rgb(255, 255, 255)',
|
||||
'whitesmoke': 'rgb(245, 245, 245)',
|
||||
'yellow': 'rgb(255, 255, 0)',
|
||||
'yellowgreen': 'rgb(154, 205, 50)',
|
||||
}
|
||||
|
||||
coord = re.compile("\\-?\\d+\\.?\\d*")
|
||||
scinumber = re.compile("[\\-\\+]?(\\d*\\.?)?\\d+[eE][\\-\\+]?\\d+")
|
||||
number = re.compile("[\\-\\+]?(\\d*\\.?)?\\d+")
|
||||
|
|
@ -281,6 +427,7 @@ numAttrsRemoved = 0
|
|||
numRastersEmbedded = 0
|
||||
numPathSegmentsReduced = 0
|
||||
numBytesSavedInPathData = 0
|
||||
numBytesSavedInColors = 0
|
||||
|
||||
# removes all unreferenced elements except for <svg>, <font>, <metadata>, <title>, and <desc>
|
||||
# also vacuums the defs of any non-referenced renderable elements
|
||||
|
|
@ -643,12 +790,78 @@ def repairStyle(node, options):
|
|||
node.setAttribute('style', fixedStyle)
|
||||
else:
|
||||
node.removeAttribute('style')
|
||||
|
||||
|
||||
# recurse for our child elements
|
||||
for child in node.childNodes :
|
||||
num += repairStyle(child,options)
|
||||
|
||||
return num
|
||||
|
||||
# convert blue to rgb(r,g,b)
|
||||
# convert rgb(r%,g%,b%) to rgb(r,g,b)
|
||||
# convert rgb(r,g,b) to #RRGGBB
|
||||
# finally convert #RRGGBB to #RGB if possible
|
||||
rgb = re.compile("\\s*rgb\\(\\s*(\\d+)\\s*\\,\\s*(\\d+)\\s*\\,\\s*(\\d+)\\s*\\)\\s*")
|
||||
rgbp = re.compile("\\s*rgb\\(\\s*(\\d*\\.?\\d+)\\%\\s*\\,\\s*(\\d*\\.?\\d+)\\%\\s*\\,\\s*(\\d*\\.?\\d+)\\%\\s*\\)\\s*")
|
||||
def convertColor(value):
|
||||
|
||||
s = value
|
||||
|
||||
if s in colors.keys():
|
||||
s = colors[s]
|
||||
|
||||
rgbpMatch = rgbp.match(s)
|
||||
if rgbpMatch != None :
|
||||
r = int( string.atof( rgbpMatch.group(1) ) * 255.0 / 100.0 )
|
||||
g = int( string.atof( rgbpMatch.group(2) ) * 255.0 / 100.0 )
|
||||
b = int( string.atof( rgbpMatch.group(3) ) * 255.0 / 100.0 )
|
||||
s = 'rgb(%d,%d,%d)' % (r,g,b)
|
||||
|
||||
rgbMatch = rgb.match(s)
|
||||
if rgbMatch != None :
|
||||
r = hex( int( rgbMatch.group(1) ) )[2:].upper()
|
||||
g = hex( int( rgbMatch.group(2) ) )[2:].upper()
|
||||
b = hex( int( rgbMatch.group(3) ) )[2:].upper()
|
||||
if len(r) == 1: r='0'+r
|
||||
if len(g) == 1: g='0'+g
|
||||
if len(b) == 1: b='0'+b
|
||||
s = '#'+r+g+b
|
||||
|
||||
if s[0] == '#' and s[1]==s[2] and s[3]==s[4] and s[5]==s[6]:
|
||||
s = s.upper()
|
||||
s = '#'+s[1]+s[3]+s[5]
|
||||
|
||||
return s
|
||||
|
||||
def convertColors(element) :
|
||||
numBytes = 0
|
||||
|
||||
if element.nodeType != 1: return 0
|
||||
|
||||
# set up list of color attributes for each element type
|
||||
attrsToConvert = []
|
||||
if element.nodeName in ['rect', 'circle', 'ellipse', 'polygon', \
|
||||
'line', 'polyline', 'path', 'g', 'a']:
|
||||
attrsToConvert = ['fill', 'stroke']
|
||||
elif element.nodeName in ['stop']:
|
||||
attrsToConvert = ['stop-color']
|
||||
elif element.nodeName in ['solidColor']:
|
||||
attrsToConvert = ['solid-color']
|
||||
|
||||
# now convert all the color formats
|
||||
for attr in attrsToConvert:
|
||||
val = element.getAttribute(attr)
|
||||
oldBytes = len(val)
|
||||
if val != '':
|
||||
element.setAttribute(attr, convertColor(val))
|
||||
numBytes += (oldBytes - len(element.getAttribute(attr)))
|
||||
|
||||
# now recurse for our child elements
|
||||
for child in element.childNodes :
|
||||
numBytes += convertColors(child)
|
||||
|
||||
return numBytes
|
||||
|
||||
def cleanPath(element) :
|
||||
global numBytesSavedInPathData
|
||||
global numPathSegmentsReduced
|
||||
|
|
@ -981,6 +1194,7 @@ def scourString(in_string, options=[]):
|
|||
global numAttrsRemoved
|
||||
global numStylePropsFixed
|
||||
global numElemsRemoved
|
||||
global numBytesSavedInColors
|
||||
doc = xml.dom.minidom.parseString(in_string)
|
||||
|
||||
# for whatever reason this does not always remove all inkscape/sodipodi attributes/elements
|
||||
|
|
@ -1005,8 +1219,9 @@ def scourString(in_string, options=[]):
|
|||
# repair style (remove unnecessary style properties and change them into XML attributes)
|
||||
numStylePropsFixed = repairStyle(doc.documentElement, options)
|
||||
|
||||
# TODO: change color properties to #RRGGBB format
|
||||
# TODO: change color properties to #RGB where possible
|
||||
# convert colors to #RRGGBB format
|
||||
if not '--disable-simplify-colors' in options:
|
||||
numBytesSavedInColors = convertColors(doc.documentElement)
|
||||
|
||||
# remove empty defs, metadata, g
|
||||
# NOTE: these elements will be removed even if they have (invalid) text nodes
|
||||
|
|
@ -1098,6 +1313,7 @@ def printSyntaxAndQuit():
|
|||
print 'If the output file is not specified, stdout is used.'
|
||||
print 'If an option is not available below that means it occurs automatically'
|
||||
print 'when scour is invoked. Available OPTIONS:\n'
|
||||
print ' --disable-simplify-colors : Scour will not convert all colors to #RRGGBB format'
|
||||
print ' --disable-style-to-xml : Scour will not convert style properties into XML attributes'
|
||||
print ' --disable-group-collapsing : Scour will not collapse <g> elements'
|
||||
print ' --enable-id-stripping : Scour will remove all un-referenced ID attributes'
|
||||
|
|
@ -1116,6 +1332,7 @@ def parseCLA():
|
|||
output = sys.stdout
|
||||
options = []
|
||||
validOptions = [
|
||||
'--disable-simplify-colors',
|
||||
'--disable-style-to-xml',
|
||||
'--disable-group-collapsing',
|
||||
'--enable-id-stripping',
|
||||
|
|
@ -1191,7 +1408,10 @@ if __name__ == '__main__':
|
|||
print ' Number of raster images embedded inline:', numRastersEmbedded
|
||||
print ' Number of path segments reduced/removed:', numPathSegmentsReduced
|
||||
print ' Number of bytes saved in path data:', numBytesSavedInPathData
|
||||
print ' Number of bytes saved in colors:', numBytesSavedInColors
|
||||
oldsize = os.path.getsize(inputfilename)
|
||||
newsize = os.path.getsize(outputfilename)
|
||||
sizediff = (newsize / oldsize);
|
||||
print ' Original file size:', oldsize, 'bytes; new file size:', newsize, 'bytes (' + str(sizediff)[:5] + 'x)'
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue