Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: packagerChrome.py

Issue 11544056: Prepared buildtools for Safari (Closed)
Patch Set: Created Sept. 9, 2013, 9:25 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: packagerChrome.py
===================================================================
--- a/packagerChrome.py
+++ b/packagerChrome.py
@@ -18,6 +18,9 @@
import sys, os, re, json, struct
from StringIO import StringIO
+import PIL.Image
+import PIL.ImageMath
Wladimir Palant 2013/09/10 10:15:27 Please don't require these modules at the top leve
+
import packager
from packager import readMetadata, getMetadataPath, getDefaultFileName, getBuildVersion, getTemplate, Files
@@ -279,10 +282,11 @@
files[operaFile] = files[chromeFile]
del files[chromeFile]
- # Hack: Replace "Chrome" by "Opera" in the locales
+ if params['type'] in ('opera', 'safari'):
+ # Hack: Replace "Chrome" by "Opera" or "Safari" in the locales
for path, data in files.iteritems():
if path.startswith("_locales/") and path.endswith("/messages.json"):
- files[path] = re.sub(r"\bChrome\b", "Opera", data)
+ files[path] = re.sub(r"\bChrome\b", params['type'].capitalize(), data)
def signBinary(zipdata, keyFile):
import M2Crypto
@@ -308,6 +312,126 @@
file.write(signature)
file.write(zipdata)
+class ImageConverter(object):
+ def convert(self, params, files):
Wladimir Palant 2013/09/10 10:15:27 Does this need to be an object? You are never real
Sebastian Noack 2013/09/10 12:40:43 I'm using self to access the filters. Yes, I could
Felix Dahlke 2013/09/11 14:44:35 I'd vote for having this as a bunch of free functi
+ for filename, chain in params['metadata'].items('convert_img'):
+ steps = re.split(r'\s*->\s*', chain)
+ image = PIL.Image.open(steps.pop(0))
Wladimir Palant 2013/09/10 10:15:27 This path should be relative to the metadata file
+
+ for step in steps:
+ filter, args = re.match(r'([^(]+)(?:\((.*)\))?', step).groups()
+ args = tuple(re.split(r'\s*,\s*', args)) if args else ()
+ image = getattr(self, 'filter_' + filter)(image, *args)
+
+ f = StringIO()
+ f.name = filename
+ image.save(f)
+ files[filename] = f.getvalue()
+
+ def filter_blend(self, image, *args):
+ if len(args) == 2: # args = (filename, opacity)
+ overlay = PIL.Image.open(args[0])
Wladimir Palant 2013/09/10 10:15:27 This file name should be resolved relative to the
+
+ if image.mode != overlay.mode or image.mode == 'P':
Wladimir Palant 2013/09/10 10:15:27 Please comment here that 'P' means "palette" (whic
+ overlay = overlay.convert('RGBA')
+ image = image.convert('RGBA')
Wladimir Palant 2013/09/10 10:15:27 Style nit: we don't usually align equal signs and
+ elif len(args) == 4: # args = (red, green, blue, opacity)
+ overlay = PIL.Image.new('RGB', image.size, tuple(map(int, args[:3])))
+
+ if image.mode == 'P':
+ image = image.convert('RGBA')
+
+ if image.mode in ('RGBA', 'LA'):
+ overlay = PIL.Image.merge('RGBA', overlay.split() + image.split()[-1:])
+
+ if image.mode != overlay.mode:
+ image = image.convert(overlay.mode)
+ else:
+ raise TypeError
Wladimir Palant 2013/09/10 10:15:27 How about: raise TypeError("Wrong number of b
+
+ return PIL.Image.blend(image, overlay, float(args[-1]))
Wladimir Palant 2013/09/10 10:15:27 I suggest processing the opacity parameter when yo
+
+ def filter_grayscale(self, image):
+ if image.mode == 'P':
+ image = image.convert('RGBA')
+
+ bands = list(image.split())
+ alpha = bands.pop(-1) if image.mode in ('RGBA', 'LA') else None
+
+ if len(bands) == 1:
+ return image
+
+ new_image = PIL.ImageMath.eval(
+ "convert((%s) / %d, 'L')" % (
+ ' + '.join('image%d' % i for i in xrange(len(bands))),
+ len(bands)
+ ),
+ **dict(('image%d' % i, band) for i, band in enumerate(bands))
+ )
Wladimir Palant 2013/09/10 10:15:27 Won't image.convert("LA", dither=None) do the righ
+
+ if alpha:
+ new_image = PIL.Image.merge('LA', [new_image, alpha])
+
+ return new_image
+
+ def filter_colorToAlpha(self, image, *color):
Wladimir Palant 2013/09/10 10:15:27 I cannot really imagine what we would use this for
Sebastian Noack 2013/09/10 12:40:43 Safari ignores all image data except the alpha cha
+ bands = [band.convert('F') for band in image.convert('RGBA').split()]
+ color = map(float, color)
Wladimir Palant 2013/09/10 14:02:12 Shouldn't we verify that three colors are given an
Sebastian Noack 2013/09/10 16:50:05 I'm not a big fan of adding extra code to throw an
Felix Dahlke 2013/09/11 14:44:35 I agree somewhat. However, in this case, I think i
+
+ # Find the maximum difference rate between source and color. I had to use two
+ # difference functions because ImageMath.eval only evaluates the expression
+ # once.
+ alpha = PIL.ImageMath.eval('''\
+ float(
+ max(
+ max(
+ max(
+ difference1(red_band, cred_band),
+ difference1(green_band, cgreen_band)
+ ),
+ difference1(blue_band, cblue_band)
+ ),
+ max(
+ max(
+ difference2(red_band, cred_band),
+ difference2(green_band, cgreen_band)
+ ),
+ difference2(blue_band, cblue_band)
+ )
+ )
+ )''',
+ difference1=lambda source, col: (source - col) / (255.0 - col),
+ difference2=lambda source, col: (col - source) / col,
Wladimir Palant 2013/09/10 14:02:12 I have a pretty hard time judging whether this alg
Sebastian Noack 2013/09/10 16:50:05 Yes you could do that in plain python instead of w
Wladimir Palant 2013/09/11 06:41:36 Given the complexity of this implementation I'm go
Felix Dahlke 2013/09/11 14:44:35 I prefer the approach suggested by Wladimir for th
Sebastian Noack 2013/09/11 15:48:06 I still don't see how not using PIL.ImageMath woul
Wladimir Palant 2013/09/11 16:14:56 As I said, converting to greyscale and taking any
+
+ red_band = bands[0],
+ green_band= bands[1],
+ blue_band = bands[2],
+
+ cred_band = color[0],
+ cgreen_band= color[1],
+ cblue_band = color[2],
+ )
Wladimir Palant 2013/09/10 14:02:12 Please indicate the source of your code whenever y
+
+ # Calculate the new image colors after the removal of the selected color
+ new_bands = [
+ PIL.ImageMath.eval(
+ "convert((image - color) / alpha + color, 'L')",
+ image=band,
+ color=col,
+ alpha=alpha
+ )
+ for band, col in zip(bands, color)
+ ]
+
+ # Add the new alpha band
+ new_bands.append(PIL.ImageMath.eval(
+ "convert(alpha_band * alpha, 'L')",
+ alpha = alpha,
+ alpha_band = bands[3]
+ ))
+
+ return PIL.Image.merge('RGBA', new_bands)
+
def createBuild(baseDir, type='chrome', outFile=None, buildNum=None, releaseBuild=False, keyFile=None, experimentalAPI=False, devenv=False):
metadata = readMetadata(baseDir, type)
version = getBuildVersion(baseDir, metadata, releaseBuild, buildNum)
@@ -335,6 +459,9 @@
if metadata.has_section('convert_js'):
convertJS(params, files)
+ if metadata.has_section('convert_img'):
+ ImageConverter().convert(params, files)
+
if metadata.has_section('import_locales'):
importGeckoLocales(params, files)

Powered by Google App Engine
This is Rietveld