示例#1
0
def generate_image(build_type, dpi, width, target, source):
    import wand.image
    import wand.api
    import wand.color

    with wand.image.Image(filename=source, resolution=dpi) as image:
        if image.width != width:
            image.transform(resize=str(width))

        if build_type == 'png':
            alpha = 0.0
        elif build_type == 'eps':
            alpha = 1.0
        else:
            raise TypeError(build_type + " is not supported")

        try:
            image.transparent_color(color=wand.color.Color('white'), alpha=alpha)
        except:
            pass

        with open(target, 'wb') as out:
            out.write(image.make_blob(build_type))

    logger.info('wrote: ' + target)
示例#2
0
def rasterise(source: str, target: str):
    print("""
CONVERTING SVG at   %s
                   |   |
                   |   |
                   |   |
                   |   |
                   |   |
                 __!   !__,
                 \       / \O
                  \     / \/|
                   \   /    |
                    \ /    / \ 
                     Y   _/  _\ 
        to PNG at   %s
    """ % (source, target))

    with open(source, "r") as f:
        sourceFile = f.read().encode('utf-8')
    with wand.image.Image(blob=sourceFile, format="svg") as image:
        with wand.color.Color('transparent') as background_color:
            library.MagickSetBackgroundColor(image.wand,
                                             background_color.resource)
            png_image = image.make_blob("png32")
            with open(target, "wb") as out:
                out.write(png_image)
示例#3
0
    def convert_img(state, itype, url):
        if not url:
            return None

        svgpath = Path("us/img/svg") / Path(urlparse(url).path).name
        pngpath = Path("us/img/png") / f"{name_to_id(state)}_{itype}.png"

        if not svgpath.is_file():
            svgblob = rq.get(url).content

            with svgpath.open("wb") as outfile:
                outfile.write(svgblob)

        if pngpath.is_file():
            return pngpath

        with wand.image.Image() as image:
            with wand.color.Color("transparent") as background_color:
                wandlib.MagickSetBackgroundColor(image.wand,
                                                 background_color.resource)

            image.read(blob=svgpath.read_bytes())
            image.transform(resize="x128")

            with pngpath.open("wb") as outfile:
                outfile.write(image.make_blob("png32"))

        return pngpath
示例#4
0
def map_view(request, map_id):
    export = "export_button" in request.POST

    items, enzymes, metabolites = request_extract(request)
    map_data = get_reaction_map(map_id, enzymes, metabolites, export)

    if export:
        map_data = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>""" + map_data

        import wand.image
        with wand.image.Image(blob=map_data.encode("utf-8"), format="svg") as image:
            png_image = image.make_blob("png")

        response = HttpResponse(png_image, content_type='image/png')
        response['Content-Disposition'] = 'attachment; filename={}.png'.format(map_id)

        return response

    return render_queryset_to_response(
        request=request,
        template="kegg/map.html",
        data={
            'map_id': map_id,
            'map_data': map_data,
            'enzymes': enzymes,
            'metabolites': metabolites,
            'items': items,
            'queries': [] if request.user.is_anonymous() else models.Query.objects.filter(user=request.user.profile),
            'is_anonymous': request.user.is_anonymous()
        }
    )
示例#5
0
def map_view(request, map_id):
    export = "export_button" in request.POST

    items, enzymes, metabolites = request_extract(request)
    map_data = get_reaction_map(map_id, enzymes, metabolites, export)

    if export:
        map_data = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>""" + map_data

        import wand.image
        with wand.image.Image(blob=map_data, format="svg") as image:
            png_image = image.make_blob("png")

        response = HttpResponse(png_image, content_type='image/png')
        response['Content-Disposition'] = 'attachment; filename={}.png'.format(map_id)

        return response

    return render_queryset_to_response(
        request=request,
        template="kegg/map.html",
        data={
            'map_id': map_id,
            'map_data': map_data,
            'enzymes': enzymes,
            'metabolites': metabolites,
            'items': items,
            'queries': [] if request.user.is_anonymous() else models.Query.objects.filter(user=request.user.profile),
            'is_anonymous': request.user.is_anonymous()
        }
    )
示例#6
0
def generate_image(build_type, dpi, width, target, source):
    import wand.image
    import wand.api
    import wand.color

    with wand.image.Image(filename=source, resolution=dpi) as image:
        if image.width != width:
            image.transform(resize=str(width))

        if build_type == 'png':
            alpha = 0.0
        elif build_type == 'eps':
            alpha = 1.0
        else:
            raise TypeError(build_type + " is not supported")

        try:
            image.transparent_color(color=wand.color.Color('white'),
                                    alpha=alpha)
        except:
            pass

        with open(target, 'wb') as out:
            out.write(image.make_blob(build_type))

    logger.info('wrote: ' + target)
def sample_stroke():
    [strokes, params] = model.sample(sample_args.sample_length)
    draw_strokes(strokes,
                 factor=sample_args.scale_factor,
                 svg_filename=sample_args.filename + '.normal.svg')
    draw_strokes_random_color(strokes,
                              factor=sample_args.scale_factor,
                              svg_filename=sample_args.filename + '.color.svg')
    draw_strokes_random_color(strokes,
                              factor=sample_args.scale_factor,
                              per_stroke_mode=False,
                              svg_filename=sample_args.filename +
                              '.multi_color.svg')
    draw_strokes_eos_weighted(strokes,
                              params,
                              factor=sample_args.scale_factor,
                              svg_filename=sample_args.filename +
                              '.eos_pdf.svg')
    draw_strokes_pdf(strokes,
                     params,
                     factor=sample_args.scale_factor,
                     svg_filename=sample_args.filename + '.pdf.svg')

    with wand.image.Image() as image:
        with open(sample_args.filename + '.normal.svg', 'rb') as svg_file:
            image.read(blob=svg_file.read())
            png_image = image.make_blob("png32")

    with open(sample_args.filename + '.png', "wb") as out:
        out.write(png_image)

    img = imageio.imread(sample_args.filename + '.png')

    return [strokes, params], img
示例#8
0
文件: badge.py 项目: estin/pybadge
def build_png(cache_key, svg):
    # convert
    with wand.image.Image(blob=svg, format="svg") as image:
        png = image.make_blob("png")

        # save png in cache
        Cache.update(cache_key, {"png": png})

        return png
示例#9
0
 def vd2png(self, input, output, scale):
     svg = self.vd2svg(input)
     with wand.image.Image() as image:
         with wand.color.Color('transparent') as background_color:
             library.MagickSetBackgroundColor(image.wand,
                                              background_color.resource)
         image.read(blob=svg, resolution=480)
         png_image = image.make_blob("png32")
         output.write(png_image)
示例#10
0
def quiz_user_for_label(image):
  """Present an image and request a label from the user.

  The image is printed to the screen in Sixel format. Users will type in four
  hex digits to supply a label, capital-'Q' to indicate a desire to quit, or
  ' ' to decline to label the image.

  Args:
    image: wand.image.Image to display to the user.

  Returns:
    4-character string of hex digits, 'XXXX' if the user believes the image has
    been corrupted by the image spanning multiple frames, 'Q' if the user has
    indicated that they wish to quit, or '' if they decline to label the image.
  """
  # Display the image and print prompt (note cursor positioning).
  sys.stdout.buffer.write(image.make_blob('sixel'))
  sys.stdout.write('\n   label >>    <<\b\b\b\b\b\b')
  sys.stdout.flush()

  # Obtain label characters from user.
  label_chars = [None] * 4
  pos = 0
  while None in label_chars:
    char = getch()

    if char in '0123456789abcdefABCDEF':
      label_chars[pos] = char.upper()
      pos += 1
      sys.stdout.write(char.upper())
    elif char == '\x7f' and pos > 0:  # Did the user type backspace?
      pos -= 1
      label_chars[pos] = None
      sys.stdout.write('\b \b')
    elif char in 'zZ':  # Did the user type 'Z'?
      print()           # Image is all zeroes.
      print()
      return '0000'
    elif char in 'mM':  # Did the user type 'M'?
      print()           # Image is corrupted by screen transition.
      print()
      return 'XXXX'
    elif char == 'Q':  # Did the user want to quit?
      print()
      return 'Q'
    elif char == ' ':  # Did the user decide not to label this image?
      print()
      return ''

    sys.stdout.flush()

  print()
  print()
  return ''.join(label_chars)
示例#11
0
def add_emoji(client, image, name):
    """Uploads an image file as an emoji to Slack. The image is expected to be
    at most 128x128 and 64k."""

    # Use requests rather than the slack client because the syntax to make the
    # SlackClient upload the image is unclear.
    assert_emoji(client, not_exists=name)
    data = {'mode': 'data', 'name': name, 'token': client.token}
    files = {'image': ('emoji_filename', image.make_blob(), image.mimetype)}
    response = requests.post('https://slack.com/api/emoji.add',
                             data=data,
                             files=files)
    response.raise_for_status()
示例#12
0
def Svg2Png(svgfile):
	output_filename = svgfile+'.png'
	input_filename = svgfile+'.svg'

	svg_file = open(input_filename,"r")

	with wand.image.Image() as image:
	    with wand.color.Color('transparent') as background_color:
		library.MagickSetBackgroundColor(image.wand, background_color.resource) 
	    image.read(blob=svg_file.read())
	    png_image = image.make_blob("png32")

	with open(output_filename, "wb") as out:
	    out.write(png_image)
示例#13
0
def trans(name, src, dst):
    print name, os.getpid()
    svg_file = open(src + "\\" + name)
    print svg_file
    svg_id = name[0 : len(name) - 4]
    with wand.image.Image() as image:
        with wand.color.Color('snow') as background_color:
            library.MagickSetBackgroundColor(image.wand,
                                             background_color.resource)
        image.read(blob=svg_file.read())
        png_image = image.make_blob("png32")
 
    with open(dst + '\\' + svg_id + ".png", "wb") as out:
        out.write(png_image)    
示例#14
0
def Svg2Png(svgfile):
	output_filename = svgfile+'.png'
	input_filename = svgfile+'.svg'

	svg_file = open(input_filename,"r")

	with wand.image.Image() as image:
	    with wand.color.Color('transparent') as background_color:
		library.MagickSetBackgroundColor(image.wand, background_color.resource) 
	    image.read(blob=svg_file.read())
	    png_image = image.make_blob("png32")

	with open(output_filename, "wb") as out:
	    out.write(png_image)
示例#15
0
def trans(name, src, dst):
    print name, os.getpid()
    svg_file = open(src + "\\" + name)
    print svg_file
    svg_id = name[0:len(name) - 4]
    with wand.image.Image() as image:
        with wand.color.Color('snow') as background_color:
            library.MagickSetBackgroundColor(image.wand,
                                             background_color.resource)
        image.read(blob=svg_file.read())
        png_image = image.make_blob("png32")

    with open(dst + '\\' + svg_id + ".png", "wb") as out:
        out.write(png_image)
示例#16
0
def draw_text(text, width, height):
    font_size = 400
    image = wand.image.Image(width=width,
                             height=height,
                             background=wand.color.Color('#fff'))
    with wand.drawing.Drawing() as draw:
        draw.fill_color = wand.color.Color('#000')
        draw.font_size = font_size
        draw.text_alignment = 'center'
        draw.text(width / 2, height / 2 + font_size / 2, text)

        draw.draw(image)
        blob = image.make_blob('png')
    return cStringIO.StringIO(blob)
示例#17
0
def convert_image(source_dir, svg_file, img_format, width=None, height=None):
    """ Convert the svg to png or jpg and scale as directed """
    if DEBUG:
        print(source_dir, svg_file, img_format, str(width), str(height))

    if img_format not in IMAGE_FORMATS.keys():
        return None

    if (width and width > MAX_DIMENSION) or (height and height > MAX_DIMENSION):
        return None

    real_width = width
    real_height = height
    image_result = None

    if not width or not height:
        try:
            doc = minidom.parse(os.path.join(source_dir, svg_file))
        except FileNotFoundError:
            return None

        svg_width = int(round(float(re.sub("[^0-9.]", "",
                                           [path.getAttribute('width') for path
                                            in doc.getElementsByTagName('svg')][0]))))
        svg_height = int(round(float(re.sub("[^0-9.]", "",
                                            [path.getAttribute('height') for path
                                             in doc.getElementsByTagName('svg')][0]))))
        doc.unlink()
        if width and not height:
            real_height = int(round((float(width) * float(svg_height)/float(svg_width))))
        elif height and not width:
            real_width = int(round((float(height) * float(svg_width)/float(svg_height))))
        else:
            real_width = svg_width
            real_height = svg_height

    try:
        with wand.image.Image() as image:
            with wand.color.Color('transparent') as background_color:
                library.MagickSetBackgroundColor(image.wand, background_color.resource)
            image.read(filename=os.path.join(source_dir, svg_file))
            if real_width and real_height:
                image.resize(real_width, real_height)
            image_result = image.make_blob(IMAGE_FORMATS[img_format])
    except wand.exceptions.BlobError:
        return None

    return image_result
示例#18
0
    def build(self, env=None, force=None, output=None, disable_cache=None):
        """Build this bundle, meaning create the file given by the ``output``
        attribute, applying the configured filters etc.

        If the bundle is a container bundle, then multiple files will be built.

        Unless ``force`` is given, the configured ``updater`` will be used to
        check whether a build is even necessary.

        If ``output`` is a file object, the result will be written to it rather
        than to the filesystem.

        The return value is a list of ``FileHunk`` objects, one for each bundle
        that was built.
        """
        version = None

        output_filename = self.resolve_output(self.env, version=version)

        # If it doesn't exist yet, create the target directory.
        output_dir = path.dirname(output_filename)
        if not path.exists(output_dir):
            os.makedirs(output_dir)

        resolved_contents = self.resolve_contents(self.env, force=True)

        from wand.api import library
        import wand.color
        import wand.image

        with wand.image.Image() as image:
            with wand.color.Color('transparent') as background_color:
                library.MagickSetBackgroundColor(image.wand,
                                                 background_color.resource)
            image.read(filename=resolved_contents[0][1])
            png_image = image.make_blob("png32")

        with open(output_filename, "wb") as out:
            # out.write(png_image)
            try:
                proc = subprocess.Popen(["pngquant", "255"], stdin=subprocess.PIPE,
                    stdout=out)
                proc.communicate(png_image)
            except OSError as e:
                raise Exception("Failed to execute pngquant: %s" % e)

        return [FileHunk(output_filename)]
示例#19
0
def make_thumbnail(pdf_blob):
    """
    Takes a PDF file (represented as a string) and returns a pair:
    - the number of pages
    - a thumbnail of its first page in PNG (as a string again),
    or None if anything failed.
    """
    try:
        resolution = int(THUMBNAIL_MAX_WIDTH / (21 / 2.54)) + 1
        num_pages = None

        try:  # We try to extract the first page of the PDF
            orig_pdf = BytesIO(pdf_blob)
            reader = PyPDF2.PdfFileReader(orig_pdf)
            num_pages = reader.getNumPages()
            if not reader.isEncrypted and num_pages == 0:
                return
            writer = PyPDF2.PdfFileWriter()
            writer.addPage(reader.getPage(0))
            first_page = BytesIO()
            writer.write(first_page)
        except PyPdfError:
            # PyPDF2 failed (maybe it believes the file is encrypted…)
            # We try to convert the file with ImageMagick (wand) anyway,
            # rendering the whole PDF as we have not been able to
            # select the first page
            pass

        # We render the PDF
        with wand.image.Image(blob=pdf_blob,
                              format='pdf',
                              resolution=resolution) as image:
            if image.height == 0 or image.width == 0:
                return
            if num_pages is None:
                num_pages = len(image.sequence)
            if num_pages == 0:
                return
            image = wand.image.Image(image=image.sequence[0])

            image.format = 'png'
            return (num_pages, image.make_blob())
    except wand.exceptions.WandException:
        # Wand failed: we consider the PDF file as invalid
        pass
    except ValueError:
        pass
示例#20
0
def draw_points(points, width, height, xoff, yoff):
    image = wand.image.Image(width=width,
                             height=height,
                             background=wand.color.Color('#fff'))

    with wand.drawing.Drawing() as draw:
        draw.fill_color = wand.color.Color('#f00')
        for p in range(len(points)):
            # draw.fill_color = wand.color.Color('#{0:x}{0:x}{0:x}'.format(r*2))
            x = points[p][0] + xoff
            y = points[p][1] + yoff
            draw_point(draw, x, y)

        draw.draw(image)
        blob = image.make_blob('png')
    return cStringIO.StringIO(blob)
    return cStringIO.StringIO(blob)
示例#21
0
文件: views.py 项目: Phyks/dissemin
def make_thumbnail(pdf_blob):
    """
    Takes a PDF file (represented as a string) and returns a pair:
    - the number of pages
    - a thumbnail of its first page in PNG (as a string again),
    or None if anything failed.
    """
    try:
        resolution = int(THUMBNAIL_MAX_WIDTH / (21/2.54))+1
        num_pages = None

        try:  # We try to extract the first page of the PDF
            orig_pdf = BytesIO(pdf_blob)
            reader = PyPDF2.PdfFileReader(orig_pdf)
            num_pages = reader.getNumPages()
            if not reader.isEncrypted and num_pages == 0:
                return
            writer = PyPDF2.PdfFileWriter()
            writer.addPage(reader.getPage(0))
            first_page = BytesIO()
            writer.write(first_page)
        except PyPdfError:
            # PyPDF2 failed (maybe it believes the file is encrypted…)
            # We try to convert the file with ImageMagick (wand) anyway,
            # rendering the whole PDF as we have not been able to
            # select the first page
            pass

        # We render the PDF
        with wand.image.Image(blob=pdf_blob, format='pdf', resolution=resolution) as image:
            if image.height == 0 or image.width == 0:
                return
            if num_pages is None:
                num_pages = len(image.sequence)
            if num_pages == 0:
                return
            image = wand.image.Image(image=image.sequence[0])

            image.format = 'png'
            return (num_pages, image.make_blob())
    except wand.exceptions.WandException:
        # Wand failed: we consider the PDF file as invalid
        pass
    except ValueError:
        pass
示例#22
0
def draw_grid(grid, width, height, xoff, yoff):
    image = wand.image.Image(width=width,
                             height=height,
                             background=wand.color.Color('#fff'))

    with wand.drawing.Drawing() as draw:
        draw.fill_color = wand.color.Color('#f00')
        for r in range(len(grid)):
            # draw.fill_color = wand.color.Color('#{0:x}{0:x}{0:x}'.format(r*2))
            for c in range(len(grid[r])):
                #logger.info("r: %s, c: %s", r, c)
                x = grid[r][c][0] + xoff
                y = grid[r][c][1] + yoff
                draw_point(draw, x, y)

        draw.draw(image)
        blob = image.make_blob('png')
    return cStringIO.StringIO(blob)
示例#23
0
def createPNG(name):
  """ Create a PNG from the generated SVG file
  """
  try:
    from wand.api import library
    import wand.color
    import wand.image
  except:
    return False
  # Do the conversion
  with wand.image.Image() as image:
    with wand.color.Color('white') as background_color:
      library.MagickSetBackgroundColor(image.wand,
                                       background_color.resource)
    image.read(filename=name + ".svg")
    image.transform(resize='620x620>')
    png_image = image.make_blob("png32")
  with open(name + ".png", "wb") as out:
      out.write(png_image)
  return True
示例#24
0
def createPNG(name):
    """ Create a PNG from the generated SVG file
  """
    try:
        from wand.api import library
        import wand.color
        import wand.image
    except:
        return False
    # Do the conversion
    with wand.image.Image() as image:
        with wand.color.Color('white') as background_color:
            library.MagickSetBackgroundColor(image.wand,
                                             background_color.resource)
        image.read(filename=name + ".svg")
        image.transform(resize='620x620>')
        png_image = image.make_blob("png32")
    with open(name + ".png", "wb") as out:
        out.write(png_image)
    return True
示例#25
0
    def drawChessboard(self,
                       screen_width,
                       screen_height,
                       cols,
                       rows,
                       color1='#fff',
                       color2='#000',
                       x=0,
                       y=0,
                       square_width=None,
                       square_height=None,
                       bgcolor='#000'):
        if square_width is None: square_width = (screen_width - x) / cols
        if square_height is None: square_height = (screen_height - y) / rows
        logger.debug("drawChessboard %s x %s", cols, rows)
        image = wand.image.Image(width=screen_width,
                                 height=screen_height,
                                 background=wand.color.Color(bgcolor))
        with wand.drawing.Drawing() as draw:
            draw.fill_color = wand.color.Color(color2)
            draw.color = wand.color.Color(color2)
            for r in range(rows):
                for c in range(cols):
                    if (c + r) % 2:
                        draw.fill_color = wand.color.Color(color2)
                        draw.color = wand.color.Color(color2)
                    else:
                        draw.fill_color = wand.color.Color(color1)
                        draw.color = wand.color.Color(color1)
                    x2 = x + square_width * c
                    y2 = y + square_height * r

                    #logger.debug("%s %s %s %s", x, y, square_width, square_height)
                    draw.rectangle(x2,
                                   y2,
                                   width=square_width - 1,
                                   height=square_height - 1)

            draw.draw(image)
            blob = image.make_blob('png')
        return cStringIO.StringIO(blob)
示例#26
0
def _generate_pil(text,
                  size='100',
                  ec_level='L',
                  style='default',
                  style_color='#000000',
                  inner_eye_style='default',
                  inner_eye_color='#000000',
                  outer_eye_style='default',
                  outer_eye_color='#000000',
                  bg_color='#FFFFFF'):

    generated_svg = qrsvg.generate_QR_for_text(text,
                                               size=size,
                                               ec_level=ec_level,
                                               style=style,
                                               style_color=style_color,
                                               inner_eye_style=inner_eye_style,
                                               inner_eye_color=inner_eye_color,
                                               outer_eye_style=outer_eye_style,
                                               outer_eye_color=outer_eye_color,
                                               bg_color=bg_color)
    converted_file = io.StringIO()

    #cairosvg.svg2png(bytestring=generated_svg.getvalue(), write_to=converted_file)

    #image = pyvips.Image.new_from_file(generated_svg.getvalue(), dpi=300)
    #image.write_to_file(converted_file)

    with wand.image.Image() as image:
        with wand.color.Color('transparent') as background_color:
            library.MagickSetBackgroundColor(image.wand,
                                             background_color.resource)
        image.read(blob=generated_svg.getvalue(), format="svg")
        png_image = image.make_blob("png32")

    with open(converted_file, "wb") as out:
        out.write(png_image)

    converted_file.seek(0)
    qr_pil = Image.open(converted_file)
    return qr_pil
示例#27
0
def convert(input_data: str, colourspace: str = "rgb", depth: int = 8,
            output_format: str = "png", resize=False, keep_aspect=False,
            resize_filter: wand.image.FILTER_TYPES='lanczos2sharp',
            compression_quality: int = None):
    with wand.image.Image(blob=input_data) as image:
        image.format = output_format

        if colourspace == "grey":
            image.type = 'grayscale'

        image.depth = depth

        if resize and keep_aspect:
            image.transform(resize + ">")
        elif resize:
            width, height = resize.split("x")

            image.resize(int(width), int(height))

        if compression_quality:
            image.compression_quality = compression_quality

        return image.make_blob()
示例#28
0
文件: svg2png.py 项目: akiniwa/hobby
# encoding: utf-8

import os
from wand.api import library
import wand.color
import wand.image

base_dir = '/Users/gree2/Downloads/glyph-iconset-master/svg/'
file_n = 'si-glyph-abacus.svg'
file_i = os.path.join(base_dir, file_n)
file_o = os.path.join(base_dir, file_i.replace('.svg', '.png'))

with wand.image.Image() as image:
    with wand.color.Color('transparent') as background_color:
        library.MagickSetBackgroundColor(image.wand, background_color.resource)
    with open(file_i) as svg_file:
        image.read(filename=file_i)
        # image.read(blob=svg_file.read(), format="svg")
        image.resize(1024, 1024)
        png_image = image.make_blob("png32")
    with open(file_o, "wb") as out:
        out.write(png_image)
示例#29
0
def create_bbox(
        height=200,
        width=200,
        outer_border_color="#1f6a31",
        inner_border_color="#299b5d",
        border_color="#000000",
        save_path=os.path.expanduser("~"),
        save_prefix="",
):
    # We have to init an empty box with stroke width 2 to start at 1, 1.
    boundaries = [
        {
            "stroke_width": 1
        },
        {
            "stroke_width": 2,
            "color": border_color,
            "r": 5,
            "id": "outer_border"
        },
        {
            "stroke_width": 4,
            "color": outer_border_color,
            "r": 3,
            "id": "outer_outer_border",
        },
        {
            "stroke_width": 4,
            "color": inner_border_color,
            "r": 0,
            "id": "inner"
        },
        {
            "stroke_width": 4,
            "color": outer_border_color,
            "r": 0,
            "id": "inner_outer_border",
        },
        {
            "stroke_width": 2,
            "color": border_color,
            "r": 0,
            "id": "inner_border"
        },
    ]

    stroke_width_sum = (sum([b["stroke_width"]
                             for b in boundaries]) - 2)  # minus the init

    bounding_boxes_total_size = 2 * stroke_width_sum
    svg_height = height + bounding_boxes_total_size
    svg_width = width + bounding_boxes_total_size

    _xml = f"""<svg xmlns="http://www.w3.org/2000/svg"
        xmlns:xlink= "http://www.w3.org/1999/xlink" width="{svg_width}px" height="{svg_height}px">"""

    h, w, x, y = svg_height, svg_width, 0, 0
    rect_list = []
    for idx in range(1, len(boundaries)):
        h, w, x, y, txt = create_inner_bbox(
            box_height=h,
            box_width=w,
            box_x=x,
            box_y=y,
            box_stroke_width=boundaries[idx - 1]["stroke_width"],
            bbox_stroke_width=boundaries[idx]["stroke_width"],
            bbox_color=boundaries[idx]["color"],
            bbox_r=boundaries[idx]["r"],
            xml_id=boundaries[idx]["id"],
        )
        rect_list.append(txt)

    # Inner has to be first to get overlapped.
    # This may not work for any more than N=5 borders.
    # TODO: Maybe make this cleaner.
    inner_bd = rect_list.pop(int(math.ceil(len(rect_list) / 2)))
    _xml += (inner_bd + "\n" + "\n".join(rect_list)) + "</svg>"

    file_name = (
        f"{height}h_{width}w_{outer_border_color[1:]}out_{inner_border_color[1:]}in.svg"
    )

    if save_prefix:
        file_name = save_prefix + "_" + file_name

    file_loc = os.path.join(save_path, file_name)
    new_file_loc = os.path.splitext(file_loc)[0] + ".png"
    with open(file_loc, "w+") as f:
        f.write(_xml)

    # Render pngs.
    with open(file_loc, "r") as svg_file:
        with wand.image.Image() as image:
            with wand.color.Color("transparent") as background_color:
                library.MagickSetBackgroundColor(image.wand,
                                                 background_color.resource)
            svg_blob = svg_file.read().encode("utf-8")
            image.read(blob=svg_blob)
            png_image = image.make_blob("png32")

        with open(new_file_loc, "wb") as out:
            out.write(png_image)
示例#30
0
</svg>
"""

from wand.api import library
import wand.color
import wand.image
from PIL import Image

name = 'chelsea'

file_object = open(name + '.svg', 'r')

with wand.image.Image() as image:
    with wand.color.Color('transparent') as background_color:
        library.MagickSetBackgroundColor(image.wand, 
                                         background_color.resource) 
    image.read(blob=file_object.read())
    png_image = image.make_blob("png32")

with open(name + '.png', "wb") as out:
    out.write(png_image)

img = Image.open(name + '.png').convert('LA')
img.save('greyscale.png')

im = Image.open(name + '.png')
foreground = Image.open('greyscale.png')

bg = Image.new("RGB", im.size, (255,255,255))
bg.paste(im, (0, 0), im)
bg.save("test.png")
示例#31
0
def simulate(request, pk):
    if not all(x in request.POST for x in ["changes", "objectives", "display", "auto_flux"]):
        return HttpResponseBadRequest("Request incomplete")

    output_format = request.POST.get("format", "json")
    dry_run = request.POST.get("dry_run", False)

    try:
        model = DesignModel.objects.get(user=UserProfile.get_profile(request.user), pk=pk)
    except ObjectDoesNotExist:
        return HttpResponseBadRequest("Bad Model")

    try:
        revision = request.POST["revision"]
        try:
            revision = Revision.objects.get(model=model, pk=revision)
        except ObjectDoesNotExist:
            return HttpResponseBadRequest("Bad Revision")
    except KeyError:
        revision = model.get_latest_revision()

    org = model_from_string(revision.content)

    try:
        changes = json.loads(request.POST["changes"])
        objectives = json.loads(request.POST["objectives"])
        display = json.loads(request.POST["display"])
        auto_flux = json.loads(request.POST["auto_flux"])
    except ValueError:
        return HttpResponseBadRequest("Invalid JSON data")

    try:
        auto_flux = bool(auto_flux)
    except ValueError:
        return HttpResponseBadRequest("Invalid data type")

    try:
        apply_commandlist(org, changes)
        org = model_from_string(revision.content)
        changes = compress_command_list(changes)
        apply_commandlist(org, changes)

        if not objectives:
            raise ValueError("No objective specified")
        org.objectives = []
        for obj in objectives:
            if len(obj["name"]) > 0:
                obj_reac = org.get_reaction(obj["name"])
                if obj_reac is None:
                    raise ValueError("Objective not in model: " + obj["name"])

                if obj_reac.disabled:
                    return HttpResponseBadRequest("Objective disabled: " + obj_reac.name)

                org.objectives.append(JsonModel.Objective(**obj))
            else:
                raise ValueError("No objective specified")
    except ValueError as e:
        return HttpResponseBadRequest("Model error: " + str(e))

    display = filter(lambda x: not len(x) == 0, display)

    for item in display:
        if not org.has_reaction(item):
            return HttpResponseBadRequest("Unknown reaction in display list: " + item)

    org = org.to_model()

    try:
       fba = org.fba()
    except ValueError as e:
        return HttpResponseBadRequest("FBA error: " + str(e))

    if dry_run:
        return HttpResponse(
            json.dumps({"solution": fba.get_status()}),
            content_type="application/json")

    full_g, nodeIDs = calc_reactions(org, fba)

    display = json.loads(request.POST["display"])
    display = list(filter(lambda x: len(x) > 0 and org.has_reaction(x), display))

    dflux = {}
    for reac, flux in zip(map(lambda x: x.name, fba.reacs), fba.flux):
        dflux[reac] = flux

    # Auto filter by FBA
    if auto_flux:
        if len(full_g.edges()) <= 30:
            full_eg = full_g
        else:
            full_eg = nx.ego_graph(full_g.reverse(), nodeIDs[org.obj[0][0]], radius=3, center=False, undirected=False)

        full_g.remove_edges_from(full_g.in_edges(nodeIDs[org.obj[0][0]]) + full_g.out_edges(nodeIDs[org.obj[0][0]]))
        all_edges = map(lambda x: full_eg.get_edge_data(*x)["object"].name, full_eg.edges())
        # Get fluxes of "edges"
        flux = []
        for reac in all_edges:
            flux.append([reac, dflux[reac]])
        flux = sorted(flux, key=lambda x: -x[1])
        display = list(map(lambda x: x[0], flux[:30]))
    else:
        full_g.remove_edges_from(full_g.in_edges(nodeIDs[org.obj[0][0]]) + full_g.out_edges(nodeIDs[org.obj[0][0]]))

    display.append(org.obj[0][0])

    g = get_selected_reaction(json_graph.node_link_data(full_g), nodeIDs, display, org)

    graph = nx.to_agraph(g)
    graph.graph_attr.update(splines=True, overlap=False, rankdir="LR")
    graph.node_attr.update(style="filled", colorscheme="pastel19")
    outgraph = str(graph.to_string())
    outgraph = pygraphviz.AGraph(outgraph)
    outgraph = outgraph.draw(format="svg", prog="dot")

    if output_format == "json":
        return HttpResponse(json.dumps(
            {"graph": outgraph.decode("utf-8"),
            "solution": fba.get_status(),
            "flux": dflux
            }),
            content_type="application/json"
        )
    elif output_format == "png":
        import wand.image
        with wand.image.Image(blob=outgraph, format="svg") as image:
            png_image = image.make_blob("png")

        r = HttpResponse(png_image, content_type="image/png")
        r['Content-Disposition'] = 'attachment; filename={}.png'.format(model.filename)
        return r
    elif output_format == "svg":
        r = HttpResponse(outgraph.decode("utf-8"), content_type="image/svg+xml")
        r['Content-Disposition'] = 'attachment; filename={}.svg'.format(model.filename)
        return r
    elif output_format == "csv":
        s = StringIO()
        for reac, flux in zip(fba.reacs, fba.flux):
            s.write(reac.name)
            s.write("\t")
            s.write(str(flux))
            s.write("\r\n")
        r = HttpResponse(s.getvalue(), content_type="text/csv")
        r['Content-Disposition'] = 'attachment; filename={}.csv'.format(model.filename)
        return r
    else:
        return HttpResponseBadRequest("Unknown format")
示例#32
0
def make_thumbnail(pdf_blob):
    """
    Takes a PDF file (represented as a string) and returns a pair:
    - the number of pages
    - a thumbnail of its first page in PNG (as a string again),
    or None if anything failed.
    """
    try:
        resolution = int(THUMBNAIL_MAX_WIDTH / (21 / 2.54)) + 1
        num_pages = None

        try:  # We try to extract the first page of the PDF
            orig_pdf = StringIO(pdf_blob)
            reader = PyPDF2.PdfFileReader(orig_pdf)
            num_pages = reader.getNumPages()
            if not reader.isEncrypted and num_pages == 0:
                print "No pages"
                return
            writer = PyPDF2.PdfFileWriter()
            writer.addPage(reader.getPage(0))
            first_page = StringIO()
            writer.write(first_page)
        except PyPdfError as e:
            # PyPDF2 failed (maybe it believes the file is encrypted…)
            # We try to convert the file with ImageMagick (wand) anyway,
            # rendering the whole PDF as we have not been able to
            # select the first page
            print "PyPDF error: " + str(e)

        # We render the PDF (or only its first page if we succeeded to extract
        # it)
        with wand.image.Image(blob=pdf_blob,
                              format='pdf',
                              resolution=resolution) as image:
            if image.height == 0 or image.width == 0:
                print "0 width or height"
                return
            if num_pages is None:
                num_pages = len(image.sequence)
            if num_pages == 0:
                print "No pages"
                return
            image = wand.image.Image(image=image.sequence[0])

            # Resizing disabled, we computed a reasonable resolution.
            # But anyway it costs much less than rendering…

            #ratio = float(image.width)/image.height
            #ref_ratio = float(THUMBNAIL_MAX_WIDTH)/THUMBNAIL_MAX_HEIGHT
            # if ratio < ref_ratio:
            #    new_height = THUMBNAIL_MAX_HEIGHT
            #    new_width = int(new_height * ratio)
            # else:
            #    new_width = THUMBNAIL_MAX_WIDTH
            #    new_height = int(new_width / ratio)
            # print "Resizing to %d/%d" % (new_height,new_width)
            #image.resize(new_width, new_height)

            image.format = 'png'
            return (num_pages, image.make_blob())
    except wand.exceptions.WandException as e:
        # Wand failed: we consider the PDF file as invalid
        print "Wand exception: " + unicode(e)
    except ValueError as e:
        print "ValueError: " + unicode(e)
示例#33
0
def __svg2png(data):
    with wand.image.Image(blob=data, format="svg") as image:
        return image.make_blob("png")
示例#34
0
def simulate(request, pk):
    if not all(x in request.POST for x in [
            "changes", "objectives", "design_objectives", "target_reactions",
            "display", "auto_flux", "type"
    ]):
        return HttpResponseBadRequest("Request incomplete")

    output_format = request.POST.get("format", "json")
    dry_run = request.POST.get("dry_run", False)

    try:
        model = DesignModel.objects.get(user=UserProfile.get_profile(
            request.user),
                                        pk=pk)
    except ObjectDoesNotExist:
        return HttpResponseBadRequest("Bad Model")

    try:
        revision = request.POST["revision"]
        try:
            revision = Revision.objects.get(model=model, pk=revision)
        except ObjectDoesNotExist:
            return HttpResponseBadRequest("Bad Revision")
    except KeyError:
        revision = model.get_latest_revision()

    org = Metabolism(StringIO(revision.content))

    try:
        changes = json.loads(request.POST["changes"])
        objectives = json.loads(request.POST["objectives"])
        design_objectives = json.loads(request.POST["design_objectives"])
        target_reactions = json.loads(request.POST["target_reactions"])
        display = json.loads(request.POST["display"])
        auto_flux = json.loads(request.POST["auto_flux"])
        simtype = json.loads(request.POST["type"])
    except ValueError:
        return HttpResponseBadRequest("Invalid JSON data")

    try:
        auto_flux = bool(auto_flux)
    except ValueError:
        return HttpResponseBadRequest("Invalid data type")

    if str(simtype) not in ["fba", "mba", "sa"]:
        return HttpResponseBadRequest(
            "Unsupported simulation type: {}".format(simtype))

    try:
        apply_commandlist(org, changes)
        org = Metabolism(StringIO(revision.content))
        changes = compress_command_list(changes)
        apply_commandlist(org, changes)

        if not objectives:
            raise ValueError("No objective specified")
        org.obj = []
        for obj in objectives:
            obj_reac = org.get_reaction(obj["name"])
            if obj_reac is None:
                raise ValueError("Objective not in model: " + obj["name"])

            if obj_reac.disabled:
                return HttpResponseBadRequest("Objective disabled: " +
                                              obj_reac.name)

            org.obj.append([obj["name"], "1" if obj["maximize"] else "0"])

        if simtype == "mba" or simtype == "sa":
            org.design_obj = []
            for obj in design_objectives:
                obj_reac = org.get_reaction(obj["name"])
                if obj_reac is None:
                    raise ValueError("Design objective not in model: " +
                                     obj["name"])

                if obj_reac.disabled:
                    return HttpResponseBadRequest(
                        "Design objective disabled: " + obj_reac.name)

                org.design_obj.append(
                    [obj["name"], "1" if obj["maximize"] else "0"])

            org.target_reactions = []
            if simtype == "sa":
                for obj in target_reactions:
                    obj_reac = org.get_reaction(obj["name"])
                    if obj_reac is None:
                        raise ValueError("Target reaction not in model: " +
                                         obj["name"])

                    if obj_reac.disabled:
                        return HttpResponseBadRequest(
                            "Target reaction disabled: " + obj_reac.name)

                    org.target_reactions.append(
                        [obj["name"], "1" if obj["maximize"] else "0"])

    except ValueError as e:
        return HttpResponseBadRequest("Model error: " + str(e))

    try:
        fba = org.fba()
    except ValueError as e:
        return HttpResponseBadRequest("FBA error: " + str(e))

    if simtype == "fba":
        if dry_run:
            return HttpResponse(json.dumps({"solution": fba.get_status()}),
                                content_type="application/json")

        full_g, nodeIDs = calc_reactions(org, fba)

        display = list(
            filter(lambda x: len(x) > 0 and org.has_reaction(x), display))

        dflux = {}
        for reac, flux in zip(map(lambda x: x, fba.reacs), fba.flux):
            dflux[reac.id] = flux

        # Auto filter by FBA
        if auto_flux:
            if len(full_g.edges()) <= 30:
                full_eg = full_g
            else:
                full_eg = nx.ego_graph(full_g.reverse(),
                                       nodeIDs[org.obj[0][0]],
                                       radius=3,
                                       center=False,
                                       undirected=False)

            full_g.remove_edges_from(
                full_g.in_edges(nodeIDs[org.obj[0][0]]) +
                full_g.out_edges(nodeIDs[org.obj[0][0]]))
            all_edges = map(
                lambda x: full_eg.get_edge_data(*x)["object"]["id"],
                full_eg.edges())
            # Get fluxes of "edges"
            flux = []
            for reac in set(all_edges):
                flux.append([reac, dflux[reac]])
            flux = sorted(flux, key=lambda x: -x[1])
            display = list(map(lambda x: x[0], flux[:30]))
        else:
            full_g.remove_edges_from(
                full_g.in_edges(nodeIDs[org.obj[0][0]]) +
                full_g.out_edges(nodeIDs[org.obj[0][0]]))

        display.append(org.obj[0][0])

        g = get_selected_reaction(json_graph.node_link_data(full_g), nodeIDs,
                                  display, org)

        # Work around a bug in nx 1.11 breaking nx.to_agraph function
        graph = nx.drawing.nx_agraph.to_agraph(g)
        graph.graph_attr.update(splines=True, overlap=False, rankdir="LR")
        graph.node_attr.update(style="filled", colorscheme="pastel19")
        outgraph = str(graph.to_string())
        outgraph = pygraphviz.AGraph(outgraph)
        #outgraph = outgraph.draw(format="svg", prog="dot")

        if output_format == "json":
            return HttpResponse(json.dumps({
                "graph": None,
                "graphstr": str(graph.to_string()),
                "solution": fba.get_status(),
                "flux": dflux
            }),
                                content_type="application/json")
        elif output_format == "png":
            import wand.image
            with wand.image.Image(blob=outgraph, format="svg") as image:
                png_image = image.make_blob("png")

            r = HttpResponse(png_image, content_type="image/png")
            r['Content-Disposition'] = 'attachment; filename={}.png'.format(
                model.filename)
            return r
        elif output_format == "svg":
            r = HttpResponse(outgraph.decode("utf-8"),
                             content_type="image/svg+xml")
            r['Content-Disposition'] = 'attachment; filename={}.svg'.format(
                model.filename)
            return r
        elif output_format == "csv":
            s = StringIO()
            for reac, flux in zip(fba.reacs, fba.flux):
                s.write(reac.name)
                s.write("\t")
                s.write(str(flux))
                s.write("\r\n")
            r = HttpResponse(s.getvalue(), content_type="text/csv")
            r['Content-Disposition'] = 'attachment; filename={}.csv'.format(
                model.filename)
            return r
        else:
            return HttpResponseBadRequest("Unknown format")
    elif simtype == "mba":
        # Determine optimal steps
        obj = org.obj[:]
        dobj = org.design_obj[:]

        # Absolute
        design_result = [["x"], [dobj[0][0]]]
        #design_result[0] += [0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1]
        sim_result = fba.design_fba()
        #dflux = [list(str(x[fba.reac_names.index(obj[0][0])]) for x in sim_result),
        #         list(x[fba.reac_names.index(dobj[0][0])] for x in sim_result)]

        dflux = list([x[0]] for x in sim_result)
        for lst, sim_res in zip(dflux, sim_result):
            lst.append({})
            for name, flux in zip(fba.reac_names, sim_res[1]):
                lst[1][name] = flux

        graph = [["x"], [dobj[0][0]]]

        for d in dflux:
            graph[0].append(d[0])
            graph[1].append(d[1][dobj[0][0]])

        if output_format == "json":
            return HttpResponse(json.dumps({
                "solution": fba.get_status(),
                "flux": dflux,
                "graph": graph
            }),
                                content_type="application/json")
        else:
            return HttpResponseBadRequest("Unknown format")
    elif simtype == "sa":
        # Percentage
        # 1. WT conditions
        obj = org.obj[:]
        dobj = org.design_obj[:]
        tobj = target_reactions[0]["name"]
        obj_r = org.get_reaction(obj[0][0])
        target = org.get_reaction(tobj)
        target_flux = fba.flux[fba.reac_names.index(target.id)]

        design_result = [["x"], [obj[0][0]], [dobj[0][0]], ["Yield"]]

        dflux = list([x] for x in [1.0, 0.8, 0.6, 0.4, 0.2, 0.0])

        # 2. Limit target reaction
        for i, limit in enumerate([1.0, 0.8, 0.6, 0.4, 0.2, 0.0]):
            # Limit to a % of the target flux
            target.constraint = (target.constraint[0], target_flux * limit)

            # Optimize limited growth
            org.obj = obj
            fba = org.fba()
            growth = fba.Z

            # Optimize production
            obj_r.constraint = (growth, growth)
            org.obj = dobj
            fba = org.fba()
            production = fba.Z

            # Reset production constraint
            obj_r.constraint = (0, None)

            design_result[0].append(str(int(limit * 100)) + "%")
            design_result[1].append(round(growth, 4))
            design_result[2].append(round(production, 4))
            design_result[3].append(round(growth * production, 4))

            dflux[i].append({})

            for reac, flux in zip(map(lambda x: x.name, fba.reacs), fba.flux):
                dflux[i][-1][reac] = flux

        dflux.append(target_flux)

        if output_format == "json":
            return HttpResponse(json.dumps({
                "solution": fba.get_status(),
                "flux": dflux,
                "graph": design_result
            }),
                                content_type="application/json")
        else:
            return HttpResponseBadRequest("Unknown format")
示例#35
0
文件: views.py 项目: Lysxia/dissemin
def make_thumbnail(pdf_blob):
    """
    Takes a PDF file (represented as a string) and returns a pair:
    - the number of pages
    - a thumbnail of its first page in PNG (as a string again),
    or None if anything failed.
    """
    try:
        resolution = int(THUMBNAIL_MAX_WIDTH / (21/2.54))+1
        num_pages = None

        first_blob = False
        try: # We try to extract the first page of the PDF
            orig_pdf = StringIO(pdf_blob)
            reader = PyPDF2.PdfFileReader(orig_pdf)
            num_pages = reader.getNumPages()
            if not reader.isEncrypted and num_pages == 0:
                print "No pages"
                return
            writer = PyPDF2.PdfFileWriter()
            writer.addPage(reader.getPage(0))
            first_page = StringIO()
            writer.write(first_page)
            first_blob = first_page.getvalue()
        except PyPdfError as e:
            # PyPDF2 failed (maybe it believes the file is encrypted…)
            # We try to convert the file with ImageMagick (wand) anyway,
            # rendering the whole PDF as we have not been able to 
            # select the first page
            print "PyPDF error: "+str(e)
            first_blob = pdf_blob

        # We render the PDF (or only its first page if we succeeded to extract it)
        with wand.image.Image(blob=pdf_blob, format='pdf', resolution=resolution) as image:
            if image.height == 0 or image.width == 0:
                print "0 width or height"
                return
            if num_pages is None:
                num_pages = len(image.sequence)
            if num_pages == 0:
                print "No pages"
                return
            image = wand.image.Image(image=image.sequence[0])
            
            # Resizing disabled, we computed a reasonable resolution.
            # But anyway it costs much less than rendering…

            #ratio = float(image.width)/image.height
            #ref_ratio = float(THUMBNAIL_MAX_WIDTH)/THUMBNAIL_MAX_HEIGHT
            #if ratio < ref_ratio:
            #    new_height = THUMBNAIL_MAX_HEIGHT
            #    new_width = int(new_height * ratio)
            #else:
            #    new_width = THUMBNAIL_MAX_WIDTH
            #    new_height = int(new_width / ratio)
            #print "Resizing to %d/%d" % (new_height,new_width)
            #image.resize(new_width, new_height)

            image.format = 'png'
            return (num_pages,image.make_blob())
    except wand.exceptions.WandException as e:
        # Wand failed: we consider the PDF file as invalid
        print "Wand exception: "+unicode(e)
        pass
    except ValueError as e:
        print "ValueError: "+unicode(e)
        pass
示例#36
0
def ui(db, traces, images, wf_innermost_dir):

    # This code is generally horrible, write-once stuff. Do not emulate!

    # Interface state:
    pos_traces = 0  # Current byte position in the traces.
    pos_images = 0  # Index of the current image.
    status = 'Ready!'  # Status message to print.
    search = []  # Last search query, as an array of char (so: mutable).

    all_trace_bytes = ''.join(b for d, b in traces)  # For searching.

    sys.stdout.write('\x1b[H\x1b[J')  # Clear screen

    # UI loop.
    while True:
        # Load image file.
        image = wand.image.Image(filename=images[pos_images])

        # Draw user interface.
        sys.stdout.write('\x1b[H')  # Back to top left.
        print('  \x1b[32m-=[ Trace alignment tool ]=-\x1b[0m')
        print()
        sys.stdout.buffer.write(image.make_blob('sixel'))
        print_trace_bytes(traces[pos_traces:pos_traces + 32])
        print()
        print('\x1b[32mfirst byte:\x1b[34m', pos_traces, '\x1b[0m     ')
        print('\x1b[32m     image:\x1b[34m', images[pos_images],
              '\x1b[0m     ')
        print()
        print('\x1b[32m')
        print(
            '  \x1b[1mA)\x1b[0;32m <--1-bytes  \x1b[1mD)\x1b[0;32m bytes-1-->   '
            '    \x1b[1mJ)\x1b[0;32m <--1-image  \x1b[1mL)\x1b[0;32m image-1-->'
        )
        print(
            '  \x1b[1mZ)\x1b[0;32m <-32-bytes  \x1b[1mC)\x1b[0;32m bytes-32->   '
            '    \x1b[1m?)\x1b[0;32m <---search  \x1b[1m/)\x1b[0;32m search--->'
        )
        print()
        print(
            '  \x1b[1mR)\x1b[0;32m remark '
            '  \x1b[1mQ)\x1b[0;32m quit '
            '  \x1b[1mSPACE)\x1b[0;32m commit     '
            '  \x1b[0K\x1b[33;1m', status)
        print('\x1b[0m')

        # Clear status line.
        status = ''

        # Get and handle user key input
        ch = getch().upper()
        if ch == 'Q':
            print('    \x1b[33;1mPlease wait, saving... \x1b[0m')
            return
        elif ch == 'A':
            pos_traces = max(0, pos_traces - 1)
        elif ch == 'D':
            pos_traces = min(pos_traces + 1, len(traces) - 32)
        elif ch == 'Z':
            pos_traces = max(0, pos_traces - 32)
        elif ch == 'C':
            pos_traces = min(pos_traces + 32, len(traces) - 32)
        elif ch == 'J':
            pos_images = max(0, pos_images - 1)
        elif ch == 'L':
            pos_images = min(pos_images + 1, len(images) - 1)
        elif ch == 'R':
            # Allow user to type a message for video recordings.
            sys.stdout.write('\x1b[1;35m  Remark >:  \x1b[1;36m')
            sys.stdout.flush()
            while True:
                ch = getch()
                if ch in '\n\r':
                    break
                elif ch in '\b\x7f':
                    sys.stdout.write('\b \b')
                else:
                    sys.stdout.write(ch)
                sys.stdout.flush()
            sys.stdout.write('\x1b[0m\x1b[2K')
        elif ch == ' ':
            # Commit these bytes to the label database.
            sf_parts = images[pos_images].split(os.sep)
            sf_root, sf_ext = os.path.splitext(sf_parts[-1])
            wordstem = os.sep.join(sf_parts[:-2] + [wf_innermost_dir, sf_root])
            wordext = sf_ext
            for i, word_pos in enumerate([
                    '_0_1', '_0_2', '_0_3', '_0_4', '_0_5', '_0_6', '_0_7',
                    '_0_8', '_1_1', '_1_2', '_1_3', '_1_4', '_1_5', '_1_6',
                    '_1_7', '_1_8'
            ]):
                wordfile = wordstem + word_pos + wordext
                label = traces[pos_traces + 2 * i][1] + traces[pos_traces +
                                                               2 * i + 1][1]
                db.label(wordfile,
                         label)  # Label twice to confirm the label as a
                db.label(wordfile, label)  # "sure thing".
            status = 'Committed.'
        elif ch in '/?':
            # Forward or backward search. Which one to use?
            find_fn = (all_trace_bytes.find
                       if ch == '/' else all_trace_bytes.rfind)
            next_fn = ((lambda s: find_fn(s, 2 * pos_traces + 2))
                       if ch == '/' else
                       (lambda s: find_fn(s, 0, max(0, 2 * pos_traces - 1))))
            # Now obtain the search query.
            sys.stdout.write('\x1b[1;35m  Search >:  \x1b[1;36m')
            sys.stdout.write(''.join(search))
            sys.stdout.flush()
            while True:
                ch = getch()
                if ch in '\n\r':
                    break
                elif ch in '\b\x7f' and search:
                    sys.stdout.write('\b \b')
                    search.pop()
                elif ch.upper() in '0123456789ABCDEF':
                    sys.stdout.write(ch.upper())
                    search.append(ch.upper())
                sys.stdout.flush()
            sys.stdout.write('\x1b[0m\x1b[2K')
            # Next, perform the search.
            if search:
                query = ''.join(search)
                for search_fn, success_str in [(next_fn, 'Found!'),
                                               (find_fn,
                                                'Found after wrapping.')]:
                    pos = search_fn(query)
                    if pos != -1:
                        # Convert nybble index to byte index, and don't allow a window that
                        # extends beyond the end of the traces. Note that this introduces
                        # a bug such that if the search query is in the final 32 bytes,
                        # continuing to search forward won't wrap around to the start of
                        # the traces. Oh well.
                        pos_traces = min(pos // 2, len(traces) - 32)
                        status = success_str
                        break
                else:
                    status = 'Not found.'
            else:
                status = 'Search cancelled.'
def _imshow(filename):
  """Show an image file using Sixel graphics."""
  image = wand.image.Image(filename=filename)
  image.resize(width=(image.width * 2), height=(image.height * 2))
  sys.stdout.buffer.write(image.make_blob('sixel'))