def split(): image = pystacia.read(sys.args[1]) rawdata = image.get_blob('png') r.set("image_dimensions", json.dumps([image.width, image.height])) x = 0 y = 0 while x < image.width: y = 0 while y < image.height: tmpimg = pystacia.read_blob(rawdata) x1 = x y1 = y x2 = x + 80 if x2 > image.width: x2 = image.width y2 = y + 80 if y2 > image.height: y2 = image.height print "r:", x1, y1, x2, y2 # crop is resize ohhh ? # http://liquibits.bitbucket.org/image.html#resizing # params are: width, height, x, y data = tmpimg.resize(x2-x1, y2-y1, x1, y1) key = "img_%s_%s_%s_%s" % (x1, y1, x2, y2) r.set(key, pickle.dumps(data.get_blob('png'))) r.lpush("image_parts", key) y += 80 x += 80 return r.execute_command("LGETALL", 'image_parts')
def hydrate(self, inst, col_vals, dict_, session): super(Image, self).hydrate(inst, col_vals, dict_, session) blob = dict_.get(self.name) if blob and blob.data is not None: dict_[self.name] = pystacia.read_blob(blob.data, self.img_format) dict_[self.name].filename = blob.filename else: dict_[self.name] = None
def test(self): import pystacia from pystacia import image with catch_warnings(record=True) as w: simplefilter('always') self.assertTrue( image.blank(30, 30).is_same(pystacia.blank(30, 30))) self.assertTrue('blank' in w[-1].message.args[0]) if lena_available(): self.assertTrue(image.lena().is_same(pystacia.lena())) self.assertTrue('lena' in w[-1].message.args[0]) tmpname = mkstemp()[1] + '.bmp' img = sample() img.write(tmpname) self.assertTrue( pystacia.read(tmpname).is_same(image.read(tmpname))) self.assertTrue('read' in w[-1].message.args[0]) self.assertTrue( pystacia.read_blob(img.get_blob('bmp')).is_same( image.read_blob(img.get_blob('bmp')))) self.assertTrue( pystacia.read_raw(**img.get_raw('rgb')).is_same( image.read_raw(**img.get_raw('rgb')))) img.close() for symbol in [ 'magick_logo', 'wizard', 'netscape', 'granite', 'rose' ]: self.assertTrue( getattr(image, symbol)().is_same(getattr(pystacia, symbol)())) self.assertTrue(symbol in w[-1].message.args[0]) self.assertIsInstance(pystacia.Image(), image.Image) names = [ 'composites', 'types', 'filters', 'colorspaces', 'compressions', 'axes' ] for name in names: self.assertEqual( getattr(pystacia, name).x, getattr(image, name).x) self.assertTrue(name in w[-1].message.args[0])
def do_apply_fx(self, key): while True: part = r.lpop(key) if not part: return print "part", part, key data = pickle.loads(r.get(part)) image = pystacia.read_blob(data) image.fx(noise) retkey = part.replace('img_', 'completed_') r.set(retkey, pickle.dumps(image.get_blob('png'))) r.lpush('completed_parts', retkey)
def to_python(self, value, bf): value = super(ImageField, self).to_python(value, bf) try: img = pystacia.read_blob(value.file.read()) except TinyException: raise ValidationError(_('Cannot read the image')) img.filename = value.filename if self.scale_down is not None: to_width, to_height = self.scale_down factor = min(to_width/img.width, to_height/img.height) if factor < 1: img.rescale(factor=factor) return img
def check_png_pattern(png_bytes, x2=False, blank=False): from .test_draw import _, r, B, assert_pixels_equal if blank: expected_pixels = [ _+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_, ] size = 8 elif x2: expected_pixels = [ _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, _+_+_+_+r+r+B+B+B+B+B+B+_+_+_+_, _+_+_+_+r+r+B+B+B+B+B+B+_+_+_+_, _+_+_+_+B+B+B+B+B+B+B+B+_+_+_+_, _+_+_+_+B+B+B+B+B+B+B+B+_+_+_+_, _+_+_+_+B+B+B+B+B+B+B+B+_+_+_+_, _+_+_+_+B+B+B+B+B+B+B+B+_+_+_+_, _+_+_+_+B+B+B+B+B+B+B+B+_+_+_+_, _+_+_+_+B+B+B+B+B+B+B+B+_+_+_+_, _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, ] size = 16 else: expected_pixels = [ _+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_, _+_+r+B+B+B+_+_, _+_+B+B+B+B+_+_, _+_+B+B+B+B+_+_, _+_+B+B+B+B+_+_, _+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_, ] size = 8 with contextlib.closing(pystacia.read_blob(png_bytes)) as image: assert image.size == (size, size) pixels = image.get_raw('rgba')['raw'] assert_pixels_equal('api_png', size, size, pixels, b''.join(expected_pixels))
def join(): w, h = json.loads(r.get('image_dimensions')) image = pystacia.blank(w, h) for key in r.execute_command('LGETALL', 'completed_parts'): print "key:", key data = pickle.loads(r.get(key)) # f = open("./tmp/%s.png" % key, 'w') # f.write(data) # f.close() i, x1, x2, y1, y2 = key.split('_') print x1, x2 t = pystacia.read_blob(data) image.overlay(t, int(x1), int(x2)) image.write("foo.png")
def check_png_pattern(png_bytes): with contextlib.closing(pystacia.read_blob(png_bytes)) as image: assert image.size == (8, 8) lines = image.get_raw('rgba')['raw'] from .test_draw import _, r, B, assert_pixels_equal assert_pixels_equal('api_png', 8, 8, lines, b''.join([ _+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_, _+_+r+B+B+B+_+_, _+_+B+B+B+B+_+_, _+_+B+B+B+B+_+_, _+_+B+B+B+B+_+_, _+_+_+_+_+_+_+_, _+_+_+_+_+_+_+_, ]))
def test(self): import pystacia from pystacia import image with catch_warnings(record=True) as w: simplefilter('always') self.assertTrue(image.blank(30, 30). is_same(pystacia.blank(30, 30))) self.assertTrue('blank' in w[-1].message.args[0]) if lena_available(): self.assertTrue(image.lena().is_same(pystacia.lena())) self.assertTrue('lena' in w[-1].message.args[0]) tmpname = mkstemp()[1] + '.bmp' img = sample() img.write(tmpname) self.assertTrue(pystacia.read(tmpname). is_same(image.read(tmpname))) self.assertTrue('read' in w[-1].message.args[0]) self.assertTrue(pystacia.read_blob(img.get_blob('bmp')). is_same(image.read_blob(img.get_blob('bmp')))) self.assertTrue(pystacia.read_raw(**img.get_raw('rgb')). is_same(image.read_raw(**img.get_raw('rgb')))) img.close() for symbol in ['magick_logo', 'wizard', 'netscape', 'granite', 'rose']: self.assertTrue(getattr(image, symbol)(). is_same(getattr(pystacia, symbol)())) self.assertTrue(symbol in w[-1].message.args[0]) self.assertIsInstance(pystacia.Image(), image.Image) names = ['composites', 'types', 'filters', 'colorspaces', 'compressions', 'axes'] for name in names: self.assertEqual(getattr(pystacia, name).x, getattr(image, name).x) self.assertTrue(name in w[-1].message.args[0])
def fallback_handler(file_obj, string, uri): """ Parse a byte stream with PIL and return a cairo Surface. PIL supports many raster image formats and does not take a `format` parameter, it guesses the format from the content. """ if file_obj: string = file_obj.read() from pystacia import read_blob with contextlib.closing(read_blob(string)) as image: # This 'quality' value disables compression and has been found # faster than the other values in 0-10. # http://www.imagemagick.org/script/command-line-options.php#quality # We don’t care about file size here, only speed. png_bytes = image.get_blob('png', quality=2) # Go through PNG as cairo.ImageSurface.create_for_data is not yet # available on Python 3. return png_handler(None, png_bytes, uri)
def fallback_handler(file_like, uri): """ Parse a byte stream with PIL and return a cairo Surface. PIL supports many raster image formats and does not take a `format` parameter, it guesses the format from the content. """ try: import pystacia as _ except ImportError as exception: return exception from pystacia import read_blob from pystacia.util import TinyException try: with contextlib.closing(read_blob(file_like.read())) as image: png_bytes = image.get_blob('png') except TinyException as exception: return exception else: return png_handler(BytesIO(png_bytes), uri)
def test_low_level_api(): """Test the low-level Python API with various parameters.""" _png_filename, svg_filename = FILES[0] expected_content = cairosvg.svg2png(url=svg_filename) # Same as above, longer version tree = cairosvg.parser.Tree(url=svg_filename) file_like = io.BytesIO() surface = cairosvg.surface.PNGSurface(tree, file_like, 96) surface.finish() assert file_like.getvalue() == expected_content png_result = pystacia.read_blob(expected_content) expected_width, expected_height = png_result.size # Abstract surface surface = cairosvg.surface.PNGSurface(tree, None, 96) assert surface.width == expected_width assert surface.height == expected_height assert cairo.SurfacePattern(surface.cairo).get_surface() is surface.cairo assert_raises(TypeError, cairo.SurfacePattern, 'Not a cairo.Surface.')
def test_script(): """Test the ``cairosvg`` script and the ``main`` function.""" _png_filename, svg_filename = FILES[0] script = os.path.join(os.path.dirname(__file__), '..', 'cairosvg.py') expected_png = cairosvg.svg2png(url=svg_filename) expected_pdf = cairosvg.svg2pdf(url=svg_filename) def run(*script_args, **kwargs): """Same as ``subprocess.check_output`` which is new in 2.7.""" process = subprocess.Popen( [sys.executable, script] + list(script_args), stdout=subprocess.PIPE, **kwargs) output = process.communicate()[0] return_code = process.poll() assert return_code == 0 return output def test_main(args, exit_=False, input_=None): """Test main called with given ``args``. If ``exit_`` is ``True``, check that ``SystemExit`` is raised. We then assume that the program output is an unicode string. If ``input_`` is given, use this stream as input stream. """ sys.argv = ['cairosvg.py'] + args old_stdin, old_stdout = sys.stdin, sys.stdout output_buffer = io.BytesIO() if sys.version_info[0] >= 3: sys.stdout = io.TextIOWrapper(output_buffer) else: sys.stdout = output_buffer if input_: kwargs = {'stdin': open(input_, 'rb')} sys.stdin = open(input_, 'rb') else: kwargs = {} if exit_: try: main() except SystemExit: pass else: raise Exception('CairoSVG did not exit') else: main() sys.stdout.flush() output = output_buffer.getvalue() sys.stdin, sys.stdout = old_stdin, old_stdout eq_(output, run(*args, **kwargs)) return output assert test_main([], exit_=True).startswith(b'Usage: ') assert test_main(['--help'], exit_=True).startswith(b'Usage: ') assert test_main(['--version'], exit_=True).strip() == \ cairosvg.VERSION.encode('ascii') assert test_main([svg_filename]) == expected_pdf assert test_main([svg_filename, '-d', '72', '-f', 'Pdf']) == expected_pdf assert test_main([svg_filename, '-f', 'png']) == expected_png assert test_main(['-'], input_=svg_filename) == expected_pdf # Test DPI output = test_main([svg_filename, '-d', '10', '-f', 'png']) width, height = pystacia.read_blob(output).size eq_(width, 47) eq_(height, 20) temp = tempfile.mkdtemp() try: temp_1 = os.path.join(temp, 'result_1') # Default to PDF assert not test_main([svg_filename, '-o', temp_1]) assert read_file(temp_1) == expected_pdf temp_2 = os.path.join(temp, 'result_2.png') # Guess from the file extension assert not test_main([svg_filename, '-o', temp_2]) assert read_file(temp_2) == expected_png temp_3 = os.path.join(temp, 'result_3.png') # Explicit -f wins assert not test_main([svg_filename, '-o', temp_3, '-f', 'pdf']) assert read_file(temp_3) == expected_pdf finally: shutil.rmtree(temp)
def image(surface, node): """Draw an image ``node``.""" url = node.get("{http://www.w3.org/1999/xlink}href") if not url: return if url.startswith("data:"): image_bytes = open_data_url(url) else: base_url = node.get("{http://www.w3.org/XML/1998/namespace}base") if base_url: url = urlparse.urljoin(base_url, url) if node.url: url = urlparse.urljoin(node.url, url) if urlparse.urlparse(url).scheme: input_ = urlopen(url) else: input_ = open(url, 'rb') # filename image_bytes = input_.read() if len(image_bytes) < 5: return x, y = size(surface, node.get("x"), "x"), size(surface, node.get("y"), "y") width = size(surface, node.get("width"), "x") height = size(surface, node.get("height"), "y") surface.context.rectangle(x, y, width, height) surface.context.clip() if image_bytes[:4] == b"\x89PNG": png_bytes = image_bytes elif image_bytes[:5] in (b"\x3csvg ", b"\x3c?xml"): surface.context.save() surface.context.translate(x, y) if "x" in node: del node["x"] if "y" in node: del node["y"] if "viewBox" in node: del node["viewBox"] tree = Tree(url=url, bytestring=image_bytes) tree_width, tree_height, viewbox = node_format(surface, tree) if not tree_width or not tree_height: tree_width = tree["width"] = width tree_height = tree["height"] = height node.image_width = tree_width or width node.image_height = tree_height or height scale_x, scale_y, translate_x, translate_y = \ preserve_ratio(surface, node) surface.set_context_size(*node_format(surface, tree)) surface.context.translate(*surface.context.get_current_point()) surface.context.scale(scale_x, scale_y) surface.context.translate(translate_x, translate_y) surface.draw(tree) surface.context.restore() # Restore twice, because draw does not restore at the end of svg tags surface.context.restore() return else: try: from pystacia import read_blob png_bytes = read_blob(image_bytes).get_blob('png') except: # No way to handle the image return image_surface = cairo.ImageSurface.create_from_png(BytesIO(png_bytes)) node.image_width = image_surface.get_width() node.image_height = image_surface.get_height() scale_x, scale_y, translate_x, translate_y = preserve_ratio(surface, node) surface.context.rectangle(x, y, width, height) pattern_pattern = cairo.SurfacePattern(image_surface) surface.context.save() surface.context.translate(*surface.context.get_current_point()) surface.context.scale(scale_x, scale_y) surface.context.translate(translate_x, translate_y) surface.context.set_source(pattern_pattern) surface.context.fill() surface.context.restore()
def image(surface, node): """Draw an image ``node``.""" url = node.get("{http://www.w3.org/1999/xlink}href") if not url: return if url.startswith("data:"): image_bytes = open_data_url(url) else: base_url = node.get("{http://www.w3.org/XML/1998/namespace}base") if base_url: url = urlparse.urljoin(base_url, url) if node.url: url = urlparse.urljoin(node.url, url) if urlparse.urlparse(url).scheme: input_ = urlopen(url) else: input_ = open(url, 'rb') # filename image_bytes = input_.read() if len(image_bytes) < 5: return x, y = size(surface, node.get("x"), "x"), size(surface, node.get("y"), "y") width = size(surface, node.get("width"), "x") height = size(surface, node.get("height"), "y") surface.context.rectangle(x, y, width, height) surface.context.clip() if image_bytes[:4] == b"\x89PNG": png_bytes = image_bytes elif image_bytes[:5] == b"\x3csvg ": surface.context.save() surface.context.translate(x, y) if "x" in node: del node["x"] if "y" in node: del node["y"] if "viewBox" in node: del node["viewBox"] tree = Tree(bytestring = image_bytes) tree_width, tree_height, viewbox = node_format(surface, tree) if not tree_width or not tree_height: tree_width = tree["width"] = width tree_height = tree["height"] = height node.image_width = tree_width or width node.image_height = tree_height or height scale_x, scale_y, translate_x, translate_y = \ preserve_ratio(surface, node) surface.set_context_size(*node_format(surface, tree)) surface.context.translate(*surface.context.get_current_point()) surface.context.scale(scale_x, scale_y) surface.context.translate(translate_x, translate_y) surface.draw(tree) surface.context.restore() # Restore twice, because draw does not restore at the end of svg tags surface.context.restore() return else: try: from pystacia import read_blob png_bytes = read_blob(image_bytes).get_blob('png') except: # No way to handle the image return image_surface = cairo.ImageSurface.create_from_png(BytesIO(png_bytes)) node.image_width = image_surface.get_width() node.image_height = image_surface.get_height() scale_x, scale_y, translate_x, translate_y = preserve_ratio(surface, node) surface.context.rectangle(x, y, width, height) pattern_pattern = cairo.SurfacePattern(image_surface) surface.context.save() surface.context.translate(*surface.context.get_current_point()) surface.context.scale(scale_x, scale_y) surface.context.translate(translate_x, translate_y) surface.context.set_source(pattern_pattern) surface.context.fill() surface.context.restore()