def pil_image(source, exif_orientation=True, **options):
    """
    Try to open the source file directly using PIL, ignoring any errors.

    exif_orientation

        If EXIF orientation data is present, perform any required reorientation
        before passing the data along the processing pipeline.

    """
    # Use a BytesIO wrapper because if the source is an incomplete file like
    # object, PIL may have problems with it. For example, some image types
    # require tell and seek methods that are not present on all storage
    # File objects.
    if not source:
        return
    source = BytesIO(source.read())
    try:
        image = Image.open(source)
        # Fully load the image now to catch any problems with the image
        # contents.
        image.load()
    except Exception:
        return

    if exif_orientation:
        image = utils.exif_orientation(image)
    return image
Exemple #2
0
def dquery_drupal_update_recommended_release(project, compatibility, cache=True):
    data = dquery_drupal_update_info_data(compatibility, project)
    f = StringIO(data)
    tree = lxml.etree.parse(f)
    error = tree.xpath('/error/text()')
    version_data = None
    #with context manager possible for f?
    try:
        if len(error):
            message = 'error requesting update information for {0!r}: {1!r}'
            raise DQueryException(message.format(project, error[0]))
        project_status = tree.xpath('/project/project_status/text()')[0]
        #just hacking this together for now
        if project_status == 'unsupported':
            message = 'project {0!r} is unsupported'
            raise DQueryException(message.format(project))
        #Check drupal logic for this
        recommended_major = tree.xpath('/project/recommended_major/text()')
        if len(recommended_major):
            major = recommended_major[0]
        else:
            default_major = tree.xpath('/project/default_major/text()')
            major = default_major[0]

        recommended_release = tree.xpath('/project/releases/release[version_major = $major][1]', major = major)[0]
        version = recommended_release.xpath('version/text()')[0]
        tag = recommended_release.xpath('tag/text()')[0]
        version_data = {'version' : str(version), 'tag' : str(tag)}
    except DQueryException as e:
        warnings.warn(e.message, DQueryWarning)
    finally:
        f.close()
    return version_data
Exemple #3
0
def save(filename, im, options, destination=None):
    pil_options = options.copy()
    if destination is None:
        destination = BytesIO()
    # Ensure plugins are fully loaded so that Image.EXTENSION is populated.
    Image.init()
    fmt = Image.EXTENSION.get(
        os.path.splitext(filename)[1].lower(), 'JPEG')
    if fmt in ('JPEG', 'WEBP'):
        pil_options.setdefault('quality', 85)
    saved = False
    if fmt == 'JPEG':
        progressive = pil_options.pop('progressive', 100)
        if progressive:
            if progressive is True or max(im.size) >= int(progressive):
                pil_options['progressive'] = True
        try:
            im.save(destination, format=fmt, optimize=1, **pil_options)
            saved = True
        except IOError:
            # Try again, without optimization (PIL can't optimize an image
            # larger than ImageFile.MAXBLOCK, which is 64k by default).
            # This shouldn't be triggered very often these days, as recent
            # versions of pillow avoid the MAXBLOCK limitation.
            pass
    if not saved:
        im.save(destination, format=fmt, **pil_options)
    if hasattr(destination, 'seek'):
        destination.seek(0)
    return destination
Exemple #4
0
def save_image(image, destination=None, filename=None, **options):
    """
    Save a PIL image.
    """
    if destination is None:
        destination = BytesIO()
    filename = filename or ''
    # Ensure plugins are fully loaded so that Image.EXTENSION is populated.
    Image.init()
    format = Image.EXTENSION.get(os.path.splitext(filename)[1].lower(), 'JPEG')
    if format in ('JPEG', 'WEBP'):
        options.setdefault('quality', 85)
    saved = False
    if format == 'JPEG':
        if settings.THUMBNAIL_PROGRESSIVE and (max(image.size) >=
                                               settings.THUMBNAIL_PROGRESSIVE):
            options['progressive'] = True
        try:
            image.save(destination, format=format, optimize=1, **options)
            saved = True
        except IOError:
            # Try again, without optimization (PIL can't optimize an image
            # larger than ImageFile.MAXBLOCK, which is 64k by default). This
            # shouldn't be triggered very often these days, as recent versions
            # of pillow avoid the MAXBLOCK limitation.
            pass
    if not saved:
        image.save(destination, format=format, **options)
    if hasattr(destination, 'seek'):
        destination.seek(0)
    return destination
Exemple #5
0
def save_image(image, destination=None, filename=None, **options):
    """
    Save a PIL image.
    """
    if destination is None:
        destination = BytesIO()
    filename = filename or ''
    # Ensure plugins are fully loaded so that Image.EXTENSION is populated.
    Image.init()
    format = Image.EXTENSION.get(os.path.splitext(filename)[1].lower(), 'JPEG')
    if format in ('JPEG', 'WEBP'):
        options.setdefault('quality', 85)
    saved = False
    if format == 'JPEG':
        if settings.THUMBNAIL_PROGRESSIVE and (
                max(image.size) >= settings.THUMBNAIL_PROGRESSIVE):
            options['progressive'] = True
        try:
            image.save(destination, format=format, optimize=1, **options)
            saved = True
        except IOError:
            # Try again, without optimization (PIL can't optimize an image
            # larger than ImageFile.MAXBLOCK, which is 64k by default). This
            # shouldn't be triggered very often these days, as recent versions
            # of pillow avoid the MAXBLOCK limitation.
            pass
    if not saved:
        image.save(destination, format=format, **options)
    if hasattr(destination, 'seek'):
        destination.seek(0)
    return destination
Exemple #6
0
def pil_image(source, exif_orientation=True, **options):
    """
    Try to open the source file directly using PIL, ignoring any errors.

    exif_orientation

        If EXIF orientation data is present, perform any required reorientation
        before passing the data along the processing pipeline.

    """
    # Use a BytesIO wrapper because if the source is an incomplete file like
    # object, PIL may have problems with it. For example, some image types
    # require tell and seek methods that are not present on all storage
    # File objects.
    if not source:
        return
    source = BytesIO(source.read())

    image = Image.open(source)
    # Fully load the image now to catch any problems with the image
    # contents.
    image.load()

    if exif_orientation:
        image = utils.exif_orientation(image)
    return image
Exemple #7
0
def pil_image(source, exif_orientation=True, **options):
    """
    Try to open the source file directly using PIL, ignoring any errors.

    exif_orientation

        If EXIF orientation data is present, perform any required reorientation
        before passing the data along the processing pipeline.

    """
    # Use a BytesIO wrapper because if the source is an incomplete file like
    # object, PIL may have problems with it. For example, some image types
    # require tell and seek methods that are not present on all storage
    # File objects.
    if not source:
        return
    source = BytesIO(source.read())

    image = Image.open(source)
    # Fully load the image now to catch any problems with the image contents.
    try:
        # An "Image file truncated" exception can occur for some images that
        # are still mostly valid -- we'll swallow the exception.
        image.load()
    except IOError:
        pass
    # Try a second time to catch any other potential exceptions.
    image.load()

    if exif_orientation:
        image = utils.exif_orientation(image)
    return image
 def test_nearly_image(self):
     """
     Broken images raise an exception.
     """
     data = self.create_image(None, None)
     trunc_data = BytesIO()
     trunc_data.write(data.read()[:-10])
     trunc_data.seek(0)
     self.assertRaises(IOError, source_generators.pil_image, data)
 def test_nearly_image(self):
     """
     Broken images are passed silently.
     """
     data = self.create_image(None, None)
     trunc_data = BytesIO()
     trunc_data.write(data.read()[:-10])
     trunc_data.seek(0)
     self.assertEqual(source_generators.pil_image(data), None)
Exemple #10
0
 def test_nearly_image(self):
     """
     Broken images raise an exception.
     """
     data = self.create_image(None, None)
     trunc_data = BytesIO()
     trunc_data.write(data.read()[:-10])
     trunc_data.seek(0)
     self.assertRaises(IOError, source_generators.pil_image, data)
Exemple #11
0
 def test_nearly_image(self):
     """
     Broken images are passed silently.
     """
     data = self.create_image(None, None)
     trunc_data = BytesIO()
     trunc_data.write(data.read()[:-10])
     trunc_data.seek(0)
     self.assertEqual(source_generators.pil_image(data), None)
Exemple #12
0
 def to_string(self, indent="", newl="", addindent=""):
     '''
     Returns a string representation of the XMLi element.
     @return: str
     '''
     buf = StringIO()
     self.to_xml().writexml(buf, indent=indent, addindent=addindent,
                            newl=newl)
     return buf.getvalue()
Exemple #13
0
def saveObscurement(image):
    """
    Return a 1-bit PNG byte string from the PIL image
    """
    output = StringIO()
    output.name = '__obscurement.png'
    image.save(output, optimize=True, transparency=TRANS, bits=1)
    output.seek(0)

    return output.read()
def saveObscurement(image):
    """
    Return a 1-bit PNG byte string from the PIL image
    """
    output = StringIO()
    output.name = '__obscurement.png'
    image.save(output, optimize=True, transparency=TRANS, bits=1)
    output.seek(0)

    return output.read()
Exemple #15
0
 def run(self):
     while True:
         try:
             self.loop()
         except SystemExit:
             raise
         except Exception as e:
             S=StringIO()
             traceback.print_exc(S)
             self.send(error=str(e), stack=S.getvalue(), success=False)
             time.sleep(1)
 def test_nearly_image(self):
     """
     Truncated images *don't* raise an exception if they can still be read.
     """
     data = self.create_image(None, None)
     reference = source_generators.pil_image(data)
     data.seek(0)
     trunc_data = BytesIO()
     trunc_data.write(data.read()[:-10])
     trunc_data.seek(0)
     im = source_generators.pil_image(trunc_data)
     # im will be truncated, but it should be the same dimensions.
     self.assertEqual(im.size, reference.size)
 def test_nearly_image(self):
     """
     Truncated images *don't* raise an exception if they can still be read.
     """
     data = self.create_image(None, None)
     reference = source_generators.pil_image(data)
     data.seek(0)
     trunc_data = BytesIO()
     trunc_data.write(data.read()[:-10])
     trunc_data.seek(0)
     im = source_generators.pil_image(trunc_data)
     # im will be truncated, but it should be the same dimensions.
     self.assertEqual(im.size, reference.size)
    def create_image(self, storage, filename, size=(800, 600), image_mode="RGB", image_format="JPEG"):
        """
        Generate a test image, returning the filename that it was saved as.

        If ``storage`` is ``None``, the BytesIO containing the image data
        will be passed instead.
        """
        data = BytesIO()
        Image.new(image_mode, size).save(data, image_format)
        data.seek(0)
        if not storage:
            return data
        image_file = ContentFile(data.read())
        return storage.save(filename, image_file)
Exemple #19
0
class FFmpegInput(BaseInput, AbstractOpus):
    def __init__(self,
                 source='-',
                 command='avconv',
                 streaming=False,
                 **kwargs):
        super(FFmpegInput, self).__init__(**kwargs)
        if source:
            self.source = source
        self.streaming = streaming
        self.command = command

        self._buffer = None
        self._proc = None

    def read(self, sz):
        if self.streaming:
            raise TypeError('Cannot read from a streaming FFmpegInput')

        # First read blocks until the subprocess finishes
        if not self._buffer:
            data, _ = self.proc.communicate()
            self._buffer = BufferedIO(data)

        # Subsequent reads can just do dis thang
        return self._buffer.read(sz)

    def fileobj(self):
        if self.streaming:
            return self.proc.stdout
        else:
            return self

    @property
    def proc(self):
        if not self._proc:
            if callable(self.source):
                self.source = self.source(self)

            if isinstance(self.source, (tuple, list)):
                self.source, self.metadata = self.source

            args = [
                self.command,
                '-i',
                str(self.source),
                '-f',
                's16le',
                '-ar',
                str(self.sampling_rate),
                '-ac',
                str(self.channels),
                '-loglevel',
                'warning',
                'pipe:1',
            ]
            self._proc = subprocess.Popen(args,
                                          stdin=None,
                                          stdout=subprocess.PIPE)
        return self._proc
Exemple #20
0
    def create_image(self,
                     storage,
                     filename,
                     size=(800, 600),
                     image_mode='RGB',
                     image_format='JPEG'):
        """
        Generate a test image, returning the filename that it was saved as.

        If ``storage`` is ``None``, the BytesIO containing the image data
        will be passed instead.
        """
        data = BytesIO()
        Image.new(image_mode, size).save(data, image_format)
        data.seek(0)
        if not storage:
            return data
        image_file = ContentFile(data.read())
        return storage.save(filename, image_file)
Exemple #21
0
    def read(self, sz):
        if self.streaming:
            raise TypeError('Cannot read from a streaming FFmpegInput')

        # First read blocks until the subprocess finishes
        if not self._buffer:
            data, _ = self.proc.communicate()
            self._buffer = BufferedIO(data)

        # Subsequent reads can just do dis thang
        return self._buffer.read(sz)
Exemple #22
0
def save_image(image, destination=None, filename=None, **options):
    """
    Save a PIL image.
    """
    if destination is None:
        destination = BytesIO()
    filename = filename or ''
    format = Image.EXTENSION.get(os.path.splitext(filename)[1], 'JPEG')
    if format == 'JPEG':
        options.setdefault('quality', 85)
        try:
            image.save(destination, format=format, optimize=1, **options)
        except IOError:
            # Try again, without optimization (PIL can't optimize an image
            # larger than ImageFile.MAXBLOCK, which is 64k by default)
            pass
    image.save(destination, format=format, **options)
    if hasattr(destination, 'seek'):
        destination.seek(0)
    return destination
Exemple #23
0
def gzip_bytes(bytestring, level=6):
    """Turn some bytes into some compressed bytes.

    >>> len(gzip_bytes(b'a' * 10000))
    46

    Args:
        bytestring (bytes): Bytes to be compressed
        level (int): An integer, 1-9, controlling the
          speed/compression. 1 is fastest, least compressed, 9 is
          slowest, but most compressed.

    Note that all levels of gzip are pretty fast these days, though
    it's not really a competitor in compression, at any level.
    """
    out = StringIO()
    f = GzipFile(fileobj=out, mode='wb', compresslevel=level)
    f.write(bytestring)
    f.close()
    return out.getvalue()
def save_image(image, destination=None, filename=None, **options):
    """
    Save a PIL image.
    """
    if destination is None:
        destination = BytesIO()
    filename = filename or ''
    format = Image.EXTENSION.get(os.path.splitext(filename)[1], 'JPEG')
    if format == 'JPEG':
        options.setdefault('quality', 85)
        try:
            image.save(destination, format=format, optimize=1, **options)
        except IOError:
            # Try again, without optimization (PIL can't optimize an image
            # larger than ImageFile.MAXBLOCK, which is 64k by default)
            pass
    image.save(destination, format=format, **options)
    if hasattr(destination, 'seek'):
        destination.seek(0)
    return destination
Exemple #25
0
def gzip_bytes(bytestring, level=6):
    """Turn some bytes into some compressed bytes.

    >>> len(gzip_bytes(b'a' * 10000))
    46

    Args:
        bytestring (bytes): Bytes to be compressed
        level (int): An integer, 1-9, controlling the
          speed/compression. 1 is fastest, least compressed, 9 is
          slowest, but most compressed.

    Note that all levels of gzip are pretty fast these days, though
    it's not really a competitor in compression, at any level.
    """
    out = StringIO()
    f = GzipFile(fileobj=out, mode='wb', compresslevel=level)
    f.write(bytestring)
    f.close()
    return out.getvalue()
Exemple #26
0
def save_image(image, destination=None, filename=None, **options):
    """
    Save a PIL image.
    """
    if destination is None:
        destination = BytesIO()
    filename = filename or ''
    # Ensure plugins are fully loaded so that Image.EXTENSION is populated.
    Image.init()
    format = Image.EXTENSION.get(os.path.splitext(filename)[1].lower(), 'JPEG')
    if format in ('JPEG', 'WEBP'):
        options.setdefault('quality', 85)
    if format == 'JPEG':
        try:
            image.save(destination, format=format, optimize=1, **options)
        except IOError:
            # Try again, without optimization (PIL can't optimize an image
            # larger than ImageFile.MAXBLOCK, which is 64k by default)
            pass
    image.save(destination, format=format, **options)
    if hasattr(destination, 'seek'):
        destination.seek(0)
    return destination
Exemple #27
0
def save_image(image, destination=None, filename=None, **options):
    """
    Save a PIL image.
    """
    if destination is None:
        destination = BytesIO()
    filename = filename or ''
    # Ensure plugins are fully loaded so that Image.EXTENSION is populated.
    Image.init()
    format = Image.EXTENSION.get(os.path.splitext(filename)[1].lower(), 'JPEG')
    if format in ('JPEG', 'WEBP'):
        options.setdefault('quality', 85)
    if format == 'JPEG':
        try:
            image.save(destination, format=format, optimize=1, **options)
        except IOError:
            # Try again, without optimization (PIL can't optimize an image
            # larger than ImageFile.MAXBLOCK, which is 64k by default)
            pass
    image.save(destination, format=format, **options)
    if hasattr(destination, 'seek'):
        destination.seek(0)
    return destination
Exemple #28
0
def render_claims_to_pdf(request, slug, claim_group, deferred_awards):
    """Currently hard-coded to print to Avery 22805 labels"""

    metrics = dict(
        page_width=(8.5 * inch),
        page_height=(11.0 * inch),
        top_margin=(0.5 * inch),
        left_margin=((25.0 / 32.0) * inch),
        qr_overlap=((1.0 / 32.0) * inch),
        padding=((1.0 / 16.0) * inch),
        horizontal_spacing=((5.0 / 16.0) * inch),
        vertical_spacing=((13.0 / 64.0) * inch),
        width=(1.5 * inch),
        height=(1.5 * inch),
    )

    debug = request.GET.get("debug", False) is not False

    pagesize = (metrics["page_width"], metrics["page_height"])
    cols = int((metrics["page_width"] - metrics["left_margin"]) / (metrics["width"] + metrics["horizontal_spacing"]))
    rows = int((metrics["page_height"] - metrics["top_margin"]) / (metrics["height"] + metrics["vertical_spacing"]))
    per_page = cols * rows
    label_ct = len(deferred_awards)
    page_ct = math.ceil(label_ct / per_page)

    pages = [deferred_awards[x : x + (per_page)] for x in range(0, label_ct, per_page)]

    response = HttpResponse(content_type="application/pdf; charset=utf-8")
    if not debug:
        # If debugging, don't force download.
        response["Content-Disposition"] = 'attachment; filename="%s-%s.pdf"' % (
            slug.encode("utf-8", "replace"),
            claim_group,
        )

    badge_img = None

    fout = StringIO()
    c = canvas.Canvas(fout, pagesize=pagesize)

    for page in pages:
        c.translate(metrics["left_margin"], metrics["page_height"] - metrics["top_margin"])

        for row in range(0, rows, 1):
            c.translate(0.0, 0 - metrics["height"])
            c.saveState()

            for col in range(0, cols, 1):

                try:
                    da = page.pop(0)
                except IndexError:
                    continue

                if not badge_img:
                    image_fin = da.badge.image.file
                    image_fin.open()
                    badge_img = ImageReader(StringIO(image_fin.read()))

                c.saveState()
                render_label(request, c, metrics, da, badge_img, debug)
                c.restoreState()

                dx = metrics["width"] + metrics["horizontal_spacing"]
                c.translate(dx, 0.0)

            c.restoreState()
            c.translate(0.0, 0 - metrics["vertical_spacing"])

        c.showPage()

    c.save()
    response.write(fout.getvalue())
    return response
Exemple #29
0
def writeGif(images, duration=0.1, repeat=True, dither=False,
                nq=0, subRectangles=True, dispose=None):
    """ writeGif(images, duration=0.1, repeat=True, dither=False,
                    nq=0, subRectangles=True, dispose=None)

    Write an animated gif from the specified images.

    Parameters
    ----------
    images : list
        Should be a list consisting of PIL images or numpy arrays.
        The latter should be between 0 and 255 for integer types, and
        between 0 and 1 for float types.
    duration : scalar or list of scalars
        The duration for all frames, or (if a list) for each frame.
    repeat : bool or integer
        The amount of loops. If True, loops infinitetely.
    dither : bool
        Whether to apply dithering
    nq : integer
        If nonzero, applies the NeuQuant quantization algorithm to create
        the color palette. This algorithm is superior, but slower than
        the standard PIL algorithm. The value of nq is the quality
        parameter. 1 represents the best quality. 10 is in general a
        good tradeoff between quality and speed. When using this option,
        better results are usually obtained when subRectangles is False.
    subRectangles : False, True, or a list of 2-element tuples
        Whether to use sub-rectangles. If True, the minimal rectangle that
        is required to update each frame is automatically detected. This
        can give significant reductions in file size, particularly if only
        a part of the image changes. One can also give a list of x-y
        coordinates if you want to do the cropping yourself. The default
        is True.
    dispose : int
        How to dispose each frame. 1 means that each frame is to be left
        in place. 2 means the background color should be restored after
        each frame. 3 means the decoder should restore the previous frame.
        If subRectangles==False, the default is 2, otherwise it is 1.

    """
    # Check PIL
    if PIL is None:
        raise RuntimeError("Need PIL to write animated gif files.")

    # Check images
    images = checkImages(images)

    # Instantiate writer object
    gifWriter = GifWriter()
    gifWriter.transparency = False # init transparency flag used in GifWriter functions

    # Check loops
    if repeat is True:
        loops = 0 # zero means infinite
    elif repeat is False or repeat == 1:
        loops = -1
    else:
        loops = int(repeat-1)

    # Check duration
    if hasattr(duration, '__len__'):
        if len(duration) == len(images):
            duration = [d for d in duration]
        else:
            raise ValueError("len(duration) doesn't match amount of images.")
    else:
        duration = [duration for im in images]

    # Check subrectangles
    if subRectangles:
        images, xy, images_info = gifWriter.handleSubRectangles(images, subRectangles)
        defaultDispose = 1 # Leave image in place
    else:
        # Normal mode
        xy = [(0,0) for im in images]
        defaultDispose = 2 # Restore to background color.

    # Check dispose
    if dispose is None:
        dispose = defaultDispose
    if hasattr(dispose, '__len__'):
        if len(dispose) != len(images):
            raise ValueError("len(xy) doesn't match amount of images.")
    else:
        dispose = [dispose for im in images]

    # Make images in a format that we can write easy
    images = gifWriter.convertImagesToPIL(images, dither, nq)

    # Write
    try:
        from cStringIO import cStringIO as BytesIO
    except ImportError:
        from django.utils.six import BytesIO
    fp = BytesIO()
    gifWriter.writeGifToFile(fp, images, duration, loops, xy, dispose)
    fp.seek(0)
    return fp
Exemple #30
0
def render_claims_to_pdf(request, slug, claim_group, deferred_awards):
    """Currently hard-coded to print to Avery 22805 labels"""

    metrics = dict(
        page_width=(8.5 * inch),
        page_height=(11.0 * inch),

        top_margin=(0.5 * inch),
        left_margin=((25.0/32.0) * inch),

        qr_overlap=((1.0/32.0) * inch),
        padding=((1.0/16.0) * inch),
        
        horizontal_spacing=((5.0/16.0) * inch),
        vertical_spacing=((13.0/64.0) * inch),

        width=(1.5 * inch),
        height=(1.5 * inch),
    )

    debug = (request.GET.get('debug', False) is not False)

    pagesize = (metrics['page_width'], metrics['page_height'])
    cols = int((metrics['page_width'] - metrics['left_margin']) / 
               (metrics['width'] + metrics['horizontal_spacing']))
    rows = int((metrics['page_height'] - metrics['top_margin']) /
               (metrics['height'] + metrics['vertical_spacing']))
    per_page = (cols * rows)
    label_ct = len(deferred_awards)
    page_ct = math.ceil(label_ct / per_page)

    pages = [deferred_awards[x:x+(per_page)]
             for x in range(0, label_ct, per_page)]

    response = HttpResponse(content_type='application/pdf; charset=utf-8')
    if not debug:
        # If debugging, don't force download.
        response['Content-Disposition'] = ('attachment; filename="%s-%s.pdf"' %
                (slug.encode('utf-8', 'replace'), claim_group))

    badge_img = None

    fout = StringIO()
    c = canvas.Canvas(fout, pagesize=pagesize)

    for page in pages:
        c.translate(metrics['left_margin'],
                    metrics['page_height']-metrics['top_margin'])

        for row in range(0, rows, 1):
            c.translate(0.0, 0 - metrics['height'])
            c.saveState()

            for col in range(0, cols, 1):

                try:
                    da = page.pop(0)
                except IndexError:
                    continue

                if not badge_img:
                    image_fin = da.badge.image.file
                    image_fin.open()
                    badge_img = ImageReader(StringIO(image_fin.read()))

                c.saveState()
                render_label(request, c, metrics, da, badge_img, debug)
                c.restoreState()

                dx = (metrics['width'] + metrics['horizontal_spacing'])
                c.translate(dx, 0.0)

            c.restoreState()
            c.translate(0.0, 0 - metrics['vertical_spacing'])

        c.showPage()

    c.save()
    response.write(fout.getvalue())
    return response
Exemple #31
0
def writeGif(images,
             duration=0.1,
             repeat=True,
             dither=False,
             nq=0,
             subRectangles=True,
             dispose=None):
    """ writeGif(images, duration=0.1, repeat=True, dither=False,
                    nq=0, subRectangles=True, dispose=None)

    Write an animated gif from the specified images.

    Parameters
    ----------
    images : list
        Should be a list consisting of PIL images or numpy arrays.
        The latter should be between 0 and 255 for integer types, and
        between 0 and 1 for float types.
    duration : scalar or list of scalars
        The duration for all frames, or (if a list) for each frame.
    repeat : bool or integer
        The amount of loops. If True, loops infinitetely.
    dither : bool
        Whether to apply dithering
    nq : integer
        If nonzero, applies the NeuQuant quantization algorithm to create
        the color palette. This algorithm is superior, but slower than
        the standard PIL algorithm. The value of nq is the quality
        parameter. 1 represents the best quality. 10 is in general a
        good tradeoff between quality and speed. When using this option,
        better results are usually obtained when subRectangles is False.
    subRectangles : False, True, or a list of 2-element tuples
        Whether to use sub-rectangles. If True, the minimal rectangle that
        is required to update each frame is automatically detected. This
        can give significant reductions in file size, particularly if only
        a part of the image changes. One can also give a list of x-y
        coordinates if you want to do the cropping yourself. The default
        is True.
    dispose : int
        How to dispose each frame. 1 means that each frame is to be left
        in place. 2 means the background color should be restored after
        each frame. 3 means the decoder should restore the previous frame.
        If subRectangles==False, the default is 2, otherwise it is 1.

    """
    # Check PIL
    if PIL is None:
        raise RuntimeError("Need PIL to write animated gif files.")

    # Check images
    images = checkImages(images)

    # Instantiate writer object
    gifWriter = GifWriter()
    gifWriter.transparency = False  # init transparency flag used in GifWriter functions

    # Check loops
    if repeat is True:
        loops = 0  # zero means infinite
    elif repeat is False or repeat == 1:
        loops = -1
    else:
        loops = int(repeat - 1)

    # Check duration
    if hasattr(duration, '__len__'):
        if len(duration) == len(images):
            duration = [d for d in duration]
        else:
            raise ValueError("len(duration) doesn't match amount of images.")
    else:
        duration = [duration for im in images]

    # Check subrectangles
    if subRectangles:
        images, xy, images_info = gifWriter.handleSubRectangles(
            images, subRectangles)
        defaultDispose = 1  # Leave image in place
    else:
        # Normal mode
        xy = [(0, 0) for im in images]
        defaultDispose = 2  # Restore to background color.

    # Check dispose
    if dispose is None:
        dispose = defaultDispose
    if hasattr(dispose, '__len__'):
        if len(dispose) != len(images):
            raise ValueError("len(xy) doesn't match amount of images.")
    else:
        dispose = [dispose for im in images]

    # Make images in a format that we can write easy
    images = gifWriter.convertImagesToPIL(images, dither, nq)

    # Write
    try:
        from cStringIO import cStringIO as BytesIO
    except ImportError:
        from django.utils.six import BytesIO
    fp = BytesIO()
    gifWriter.writeGifToFile(fp, images, duration, loops, xy, dispose)
    fp.seek(0)
    return fp
Exemple #32
0
def render_claims_to_pdf(request, slug, claim_group, deferred_awards):
    """Currently hard-coded to print to Avery 22805 labels"""

    metrics = dict(
        page_width=(8.5 * inch),
        page_height=(11.0 * inch),

        top_margin=(0.5 * inch),
        left_margin=((25.0/32.0) * inch),
        
        horizontal_spacing=((5.0/16.0) * inch),
        vertical_spacing=((13.0/64.0) * inch),

        width=(1.5 * inch),
        height=(1.5 * inch),
    )

    debug = (request.GET.get('debug', False) is not False)

    pagesize = (metrics['page_width'], metrics['page_height'])
    cols = int((metrics['page_width'] - metrics['left_margin']) / 
               (metrics['width'] + metrics['horizontal_spacing']))
    rows = int((metrics['page_height'] - metrics['top_margin']) /
               (metrics['height'] + metrics['vertical_spacing']))
    per_page = (cols * rows)
    label_ct = len(deferred_awards)
    page_ct = math.ceil(label_ct / per_page)

    pages = [deferred_awards[x:x+(per_page)]
             for x in range(0, label_ct, per_page)]

    response = HttpResponse(content_type='application/pdf; charset=utf-8')
    if not debug:
        # If debugging, don't force download.
        response['Content-Disposition'] = ('attachment; filename="%s-%s.pdf"' %
                (slug.encode('utf-8', 'replace'), claim_group))

    fout = StringIO()
    c = canvas.Canvas(fout, pagesize=pagesize)

    for page in pages:
        c.translate(metrics['left_margin'],
                    metrics['page_height']-metrics['top_margin'])

        for row in range(0, rows, 1):
            c.translate(0.0, 0 - metrics['height'])
            c.saveState()

            for col in range(0, cols, 1):

                try:
                    da = page.pop(0)
                except IndexError:
                    continue

                c.saveState()
                render_label(request, c, metrics, da)
                c.restoreState()

                dx = (metrics['width'] + metrics['horizontal_spacing'])
                c.translate(dx, 0.0)

            c.restoreState()
            c.translate(0.0, 0 - metrics['vertical_spacing'])

        c.showPage()

    c.save()
    response.write(fout.getvalue())
    return response
Exemple #33
0
def iiif_image_api(request, identifier_param, region_param, size_param,
                   rotation_param, quality_param, format_param):
    """ Image repurposing endpoint for IIIF Image API 2.1 """
    ik_image, image = _get_image_or_404(identifier_param, load_image=True)

    is_transparent = et_utils.is_transparent(image)
    is_grayscale = image.mode in ('L', 'LA')

    # Map format names used for IIIF URL path extension to proper name
    format_mapping = {
        'jpg': 'jpeg',
        'tif': 'tiff',
    }

    try:
        # Parse region
        x, y, r_width, r_height = parse_region(region_param, image.width,
                                               image.height)

        # Parse size
        s_width, s_height = parse_size(size_param, r_width, r_height)

        # Parse rotation
        is_mirrored, rotation_degrees = \
            parse_rotation(rotation_param, s_width, s_height)

        # Parse quality
        quality = parse_quality(quality_param)

        # Parse format
        # TODO Add support for unsupported formats (see `parse_format`)
        image_format = os.path.splitext(ik_image.image.name)[1][1:].lower()
        output_format = parse_format(format_param, image_format)
        corrected_format = format_mapping.get(output_format, output_format)

        # Redirect to canonical URL if appropriate, per
        # http://iiif.io/api/image/2.1/#canonical-uri-syntax
        canonical_path = make_canonical_path(
            identifier_param,
            image.width,
            image.height,
            (x, y, r_width, r_height),  # Region
            (s_width, s_height),  # Size
            (is_mirrored, rotation_degrees),  # Rotation
            quality,
            output_format)
        if request.path != canonical_path:
            return HttpResponseRedirect(canonical_path)

        # Determine storage file name for item
        if iiif_storage:
            storage_path = build_iiif_file_storage_path(
                canonical_path, ik_image, iiif_storage)
        else:
            storage_path = None

        # Load pre-generated image from storage if one exists and is up-to-date
        # with the original image (per timestampt info embedded in the storage
        # path)
        # TODO The exists lookup is slow for S3 storage, cache metadata?
        # TODO Detect when original image would be unchanged & use it directly?
        if (storage_path and iiif_storage.exists(storage_path)):
            if is_remote_storage(iiif_storage, storage_path):
                return HttpResponseRedirect(iiif_storage.url(storage_path))
            else:
                return FileResponse(
                    iiif_storage.open(storage_path),
                    content_type='image/%s' % corrected_format,
                )

        ##################
        # Generate image #
        ##################

        # Apply region
        if x or y or r_width != image.width or r_height != image.height:
            box = (x, y, x + r_width, y + r_height)
            image = image.crop(box)

        # Apply size
        if s_width != r_width or s_height != r_height:
            size = (s_width, s_height)
            image = image.resize(size)

        # TODO Apply rotation

        # Apply quality
        # Much of this is cribbed from easythumbnails' `colorspace` processor
        # TODO Replace with glamkit-imagetools' sRGB colour space converter?
        if quality in ('default', 'color') and not is_grayscale:
            if is_transparent:
                new_mode = 'RGBA'
            else:
                new_mode = 'RGB'
        elif is_grayscale or quality == 'gray':
            if is_transparent:
                new_mode = 'LA'
            else:
                new_mode = 'L'
        if new_mode != image.mode:
            image = image.convert(new_mode)

        # Apply format and "save"
        result_image = BytesIO()
        image.save(result_image, format=corrected_format)

        # Save generated image to storage if possible
        if storage_path:
            iiif_storage.save(storage_path, result_image)

        if iiif_storage and is_remote_storage(iiif_storage, storage_path):
            return HttpResponseRedirect(iiif_storage.url(storage_path))
        else:
            result_image.seek(0)  # Reset image file in case it's just created
            return FileResponse(
                result_image.read(),
                content_type='image/%s' % corrected_format,
            )
    # Handle error conditions per iiif.io/api/image/2.1/#server-responses
    except ClientError, ex:
        return HttpResponseBadRequest(ex.message)  # 400 response