Example #1
0
    def save(self, **kwargs):
        """Returns a buffer to the image for saving, supports the
        following optional keyword arguments:

        format - The format to save as: see Image.FORMATS
        optimize - The image file size should be optimized
        preserve_exif - Preserve the Exif information in JPEGs
        progressive - The output should be progressive JPEG
        quality - The quality used to save JPEGs: integer from 1 - 100
        """
        opts = Image._normalize_options(kwargs)
        outfile = BytesIO()
        if opts["pil"]["format"]:
            fmt = opts["pil"]["format"]
        else:
            fmt = self._orig_format
        save_kwargs = dict()

        if Image._isint(opts["quality"]):
            save_kwargs["quality"] = int(opts["quality"])

        if int(opts["optimize"]):
            save_kwargs["optimize"] = True

        if int(opts["progressive"]):
            save_kwargs["progressive"] = True

        if int(opts["preserve_exif"]):
            save_kwargs["exif"] = self._exif

        color = color_hex_to_dec_tuple(opts["background"])

        if self.img.mode == "RGBA":
            self._background(fmt, color)

        if fmt == "JPEG":
            if self.img.mode == "P":
                # Converting old GIF and PNG files to JPEG can raise
                # IOError: cannot write mode P as JPEG
                # https://mail.python.org/pipermail/python-list/2000-May/036017.html
                self.img = self.img.convert("RGB")
            elif self.img.mode == "RGBA":
                # JPEG does not have an alpha channel so cannot be
                # saved as RGBA. It must be converted to RGB.
                self.img = self.img.convert("RGB")

        if self._orig_format == "JPEG":
            self.img.format = self._orig_format
            save_kwargs["subsampling"] = "keep"
            if opts["quality"] == "keep":
                save_kwargs["quality"] = "keep"

        try:
            self.img.save(outfile, fmt, **save_kwargs)
        except IOError as e:
            raise errors.ImageSaveError(str(e))
        self.img.format = fmt
        outfile.seek(0)

        return outfile
Example #2
0
    def resize(self, width, height, **kwargs):
        """Resizes the image to the supplied width/height. Returns the
        instance. Supports the following optional keyword arguments:

        mode - The resizing mode to use, see Image.MODES
        filter - The filter to use: see Image.FILTERS
        background - The hexadecimal background fill color, RGB or ARGB
        position - The position used to crop: see Image.POSITIONS for
                   pre-defined positions or a custom position ratio
        retain - The minimum percentage of the original image to retain
                 when cropping
        """
        opts = Image._normalize_options(kwargs)
        size = self._get_size(width, height)
        if opts["mode"] == "adapt":
            self._adapt(size, opts)
        elif opts["mode"] == "clip":
            self._clip(size, opts)
        elif opts["mode"] == "fill":
            self._fill(size, opts)
        elif opts["mode"] == "scale":
            self._scale(size, opts)
        else:
            self._crop(size, opts)
        return self
Example #3
0
 def _remove_alpha_channel(self, **kwargs):
     opts = Image._normalize_options(kwargs)
     if self.img.mode != "RGB" and len(self.img.split()) > 3:
         # logger.debug("removing alpha channel")
         background = PIL.Image.new("RGB", self.img.size, color_hex_to_dec_tuple(opts["background"]))
         background.paste(self.img, mask=self.img.split()[3])  # 3 is the alpha channel
         self.img = background
Example #4
0
    def save(self, **kwargs):
        """Returns a buffer to the image for saving, supports the
        following optional keyword arguments:

        format - The format to save as: see Image.FORMATS
        optimize - The image file size should be optimized
        quality - The quality used to save JPEGs: integer from 1 - 100
        """
        opts = Image._normalize_options(kwargs)
        outfile = BytesIO()
        if opts["pil"]["format"]:
            fmt = opts["pil"]["format"]
        else:
            fmt = self._orig_format
        save_kwargs = dict(quality=int(opts["quality"]))
        if int(opts["optimize"]):
            save_kwargs["optimize"] = True
        try:
            self.img.save(outfile, fmt, **save_kwargs)
        except IOError as e:
            raise errors.ImageSaveError(str(e))
        self.img.format = fmt
        outfile.seek(0)

        return outfile
Example #5
0
 def validate_options(opts):
     opts = Image._normalize_options(opts)
     if opts["mode"] not in Image.MODES:
         raise errors.ModeError("Invalid mode: %s" % opts["mode"])
     elif opts["filter"] not in Image.FILTERS:
         raise errors.FilterError("Invalid filter: %s" % opts["filter"])
     elif opts["format"] and opts["format"] not in Image.FORMATS:
         raise errors.FormatError("Invalid format: %s" % opts["format"])
     elif opts["position"] not in Image.POSITIONS \
             and not opts["pil"]["position"]:
         raise errors.PositionError(
             "Invalid position: %s" % opts["position"])
     elif not Image._isint(opts["background"], 16) \
             or len(opts["background"]) not in [3, 4, 6, 8]:
         raise errors.BackgroundError(
             "Invalid background: %s" % opts["background"])
     elif opts["optimize"] and not Image._isint(opts["optimize"]):
         raise errors.OptimizeError(
             "Invalid optimize: %s", str(opts["optimize"]))
     elif opts["quality"] != "keep" \
             and (not Image._isint(opts["quality"])
                  or int(opts["quality"]) > 100
                  or int(opts["quality"]) < 0):
         raise errors.QualityError(
             "Invalid quality: %s", str(opts["quality"]))
     elif opts["progressive"] and not Image._isint(opts["progressive"]):
         raise errors.ProgressiveError(
             "Invalid progressive: %s", str(opts["progressive"]))
Example #6
0
    def _adpat_with_padding(self,w,h,padding,**kwargs):
        opts = Image._normalize_options(kwargs)
        pad=0
        width=int(w);
        height=int(h);
        if padding:
            pad=float(padding)
        paddingH=int(width*pad)
        paddingV=int(height*pad)
        width=int(width-paddingH)
        height=int(height-paddingV)

        logger.debug("New Size : "+str([width,height]))
        self._clip((width,height), opts)
        if self.img.size == (width,height) and not padding:
            return  # No need to fill
        x= ((width+paddingH)-self.img.size[0])/2
        y= ((height+paddingV)-self.img.size[1])/2

        color = color_hex_to_dec_tuple(opts["background"])
        mode = "RGBA" if len(color) == 4 else "RGB"
        logger.debug("New Size with Padding: "+str((width+paddingH, height+paddingV)))
        img = PIL.Image.new(mode=mode, size=(width+paddingH, height+paddingV), color=(255, 255, 255))
        # If the image has an alpha channel, use it as a mask when
        # pasting onto the background.
        channels = self.img.split()
        mask = channels[3] if len(channels) == 4 else None
        img.paste(self.img, (int(x),int(y)), mask=mask)
        self._skip_background = True
        self.img = img
Example #7
0
    def rotate(self, deg, **kwargs):
        """ Rotates the image clockwise around its center.  Returns the
        instance. Supports the following optional keyword arguments:

        expand - Expand the output image to fit rotation
        """
        opts = Image._normalize_options(kwargs)

        if deg == "auto":
            if self._orig_format == "JPEG":
                try:
                    exif = self.img._getexif() or dict()
                    deg = _orientation_to_rotation.get(exif.get(274, 0), 0)
                except Exception:
                    logger.warn('unable to parse exif')
                    deg = 0
            else:
                deg = 0

        deg = 360 - (int(deg) % 360)
        if deg % 90 == 0:
            if deg == 90:
                self.img = self.img.transpose(PIL.Image.ROTATE_90)
            elif deg == 180:
                self.img = self.img.transpose(PIL.Image.ROTATE_180)
            elif deg == 270:
                self.img = self.img.transpose(PIL.Image.ROTATE_270)
        else:
            self.img = self.img.rotate(deg, expand=bool(int(opts["expand"])))

        return self
Example #8
0
 def validate_options(opts):
     opts = Image._normalize_options(opts)
     if opts["mode"] not in Image.MODES:
         raise errors.ModeError("Invalid mode: %s" % opts["mode"])
     elif opts["filter"] not in Image.FILTERS:
         raise errors.FilterError("Invalid filter: %s" % opts["filter"])
     elif opts["format"] and opts["format"] not in Image.FORMATS:
         raise errors.FormatError("Invalid format: %s" % opts["format"])
     elif opts["position"] not in Image.POSITIONS \
             and not opts["pil"]["position"]:
         raise errors.PositionError("Invalid position: %s" %
                                    opts["position"])
     elif not Image._isint(opts["background"], 16) \
             or len(opts["background"]) not in [3, 4, 6, 8]:
         raise errors.BackgroundError("Invalid background: %s" %
                                      opts["background"])
     elif opts["optimize"] and not Image._isint(opts["optimize"]):
         raise errors.OptimizeError("Invalid optimize: %s",
                                    str(opts["optimize"]))
     elif opts["quality"] != "keep" and \
         (not Image._isint(opts["quality"]) or
          int(opts["quality"]) > 100 or
          int(opts["quality"]) < 0):
         raise errors.QualityError("Invalid quality: %s",
                                   str(opts["quality"]))
     elif opts["preserve_exif"] and not Image._isint(opts["preserve_exif"]):
         raise errors.PreserveExifError("Invalid preserve_exif: %s" %
                                        str(opts["preserve_exif"]))
     elif opts["progressive"] and not Image._isint(opts["progressive"]):
         raise errors.ProgressiveError("Invalid progressive: %s",
                                       str(opts["progressive"]))
     elif (not Image._isint(opts["retain"]) or int(opts["retain"]) > 100
           or int(opts["retain"]) < 0):
         raise errors.RetainError("Invalid retain: %s" %
                                  str(opts["retain"]))
Example #9
0
    def save(self, **kwargs):
        """Returns a buffer to the image for saving, supports the
        following optional keyword arguments:

        format - The format to save as: see Image.FORMATS
        optimize - The image file size should be optimized
        quality - The quality used to save JPEGs: integer from 1 - 100
        """
        opts = Image._normalize_options(kwargs)
        outfile = BytesIO()
        if opts["pil"]["format"]:
            fmt = opts["pil"]["format"]
        else:
            fmt = self._orig_format
        save_kwargs = dict(quality=int(opts["quality"]))
        if int(opts["optimize"]):
            save_kwargs["optimize"] = True
        try:
            self.img.save(outfile, fmt, **save_kwargs)
        except IOError as e:
            raise errors.ImageSaveError(str(e))
        self.img.format = fmt
        outfile.seek(0)

        return outfile
Example #10
0
    def save(self, **kwargs):
        opts = Image._normalize_options(kwargs)
        outfile = BytesIO()
        if opts["pil"]["format"]:
            fmt = opts["pil"]["format"]
        else:
            fmt = self._orig_format
        save_kwargs = dict()

        if Image._isint(opts["quality"]):
            save_kwargs["quality"] = int(opts["quality"])

        if int(opts["optimize"]):
            save_kwargs["optimize"] = True

        if int(opts["progressive"]):
            save_kwargs["progressive"] = True

        if int(opts["preserve_exif"]):
            save_kwargs["exif"] = self._exif

        if self._orig_format == "JPEG":
            self.img.format = self._orig_format
            save_kwargs["subsampling"] = "keep"
            if opts["quality"] == "keep":
                save_kwargs["quality"] = "keep"

        try:
            self.img.save(outfile, fmt, **save_kwargs)
        except IOError as e:
            raise errors.ImageSaveError(str(e))
        self.img.format = fmt
        outfile.seek(0)

        return outfile
Example #11
0
    def resize(self, width, height, **kwargs):
        """Resizes the image to the supplied width/height. Returns the
        instance. Supports the following optional keyword arguments:

        mode - The resizing mode to use, see Image.MODES
        filter - The filter to use: see Image.FILTERS
        background - The hexadecimal background fill color, RGB or ARGB
        position - The position used to crop: see Image.POSITIONS for
                   pre-defined positions or a custom position ratio
        retain - The minimum percentage of the original image to retain
                 when cropping
        """
        opts = Image._normalize_options(kwargs)
        size = self._get_size(width, height)
        if opts["mode"] == "adapt":
            self._adapt(size, opts)
        elif opts["mode"] == "clip":
            self._clip(size, opts)
        elif opts["mode"] == "fill":
            self._fill(size, opts)
        elif opts["mode"] == "scale":
            self._scale(size, opts)
        else:
            self._crop(size, opts)
        return self
Example #12
0
    def rotate(self, deg, **kwargs):
        """ Rotates the image clockwise around its center.  Returns the
        instance. Supports the following optional keyword arguments:

        expand - Expand the output image to fit rotation
        """
        opts = Image._normalize_options(kwargs)

        if deg == "auto":
            if self._orig_format == "JPEG":
                try:
                    exif = self.img._getexif() or dict()
                    deg = _orientation_to_rotation.get(exif.get(274, 0), 0)
                except Exception:
                    logger.warn('unable to parse exif')
                    deg = 0
            else:
                deg = 0

        deg = 360 - (int(deg) % 360)
        if deg % 90 == 0:
            if deg == 90:
                self.img = self.img.transpose(PIL.Image.ROTATE_90)
            elif deg == 180:
                self.img = self.img.transpose(PIL.Image.ROTATE_180)
            elif deg == 270:
                self.img = self.img.transpose(PIL.Image.ROTATE_270)
        else:
            self.img = self.img.rotate(deg, expand=bool(int(opts["expand"])))

        return self
Example #13
0
    def save(self, **kwargs):
        """Returns a buffer to the image for saving, supports the
        following optional keyword arguments:

        format - The format to save as: see Image.FORMATS
        optimize - The image file size should be optimized
        preserve_exif - Preserve the Exif information in JPEGs
        progressive - The output should be progressive JPEG
        quality - The quality used to save JPEGs: integer from 1 - 100
        """
        opts = Image._normalize_options(kwargs)
        outfile = BytesIO()
        if opts["pil"]["format"]:
            fmt = opts["pil"]["format"]
        else:
            fmt = self._orig_format
        save_kwargs = dict()

        if Image._isint(opts["quality"]):
            save_kwargs["quality"] = int(opts["quality"])

        if int(opts["optimize"]):
            save_kwargs["optimize"] = True

        if int(opts["progressive"]):
            save_kwargs["progressive"] = True

        if int(opts["preserve_exif"]):
            save_kwargs["exif"] = self._exif

        color = color_hex_to_dec_tuple(opts["background"])

        if self.img.mode == "RGBA":
            self._background(fmt, color)

        if fmt == "JPEG":
            if self.img.mode == "P":
                # Converting old GIF and PNG files to JPEG can raise
                # IOError: cannot write mode P as JPEG
                # https://mail.python.org/pipermail/python-list/2000-May/036017.html
                self.img = self.img.convert("RGB")
            elif self.img.mode == "RGBA":
                # JPEG does not have an alpha channel so cannot be
                # saved as RGBA. It must be converted to RGB.
                self.img = self.img.convert("RGB")

        if self._orig_format == "JPEG":
            self.img.format = self._orig_format
            save_kwargs["subsampling"] = "keep"
            if opts["quality"] == "keep":
                save_kwargs["quality"] = "keep"

        try:
            self.img.save(outfile, fmt, **save_kwargs)
        except IOError as e:
            raise errors.ImageSaveError(str(e))
        self.img.format = fmt
        outfile.seek(0)

        return outfile
Example #14
0
    def rotate(self, deg, **kwargs):
        """ Rotates the image clockwise around its center.  Returns the
        instance. Supports the following optional keyword arguments:

        expand - Expand the output image to fit rotation
        """
        opts = Image._normalize_options(kwargs)
        expand = False if int(deg) % 90 == 0 else bool(int(opts["expand"]))
        self.img = self.img.rotate(360 - int(deg), expand=expand)
        return self
Example #15
0
    def rotate(self, deg, **kwargs):
        """ Rotates the image clockwise around its center.  Returns the
        instance. Supports the following optional keyword arguments:

        expand - Expand the output image to fit rotation
        """
        opts = Image._normalize_options(kwargs)
        expand = False if int(deg) % 90 == 0 else bool(int(opts["expand"]))
        self.img = self.img.rotate(360 - int(deg), expand=expand)
        return self
Example #16
0
    def watermark(self, position, **kwargs):
        pos = make_tuple(position)

        opts = Image._normalize_options(kwargs)
        watermark_txt = opts[
            "watermark_txt"] if "watermark_txt" in opts else None
        watermark_img = opts[
            "watermark_img"] if "watermark_img" in opts else None

        if watermark_txt:
            watermark_txt_size = int(opts["watermark_txt_size"]
                                     if "watermark_txt_size" in opts else 30)
            watermark_txt_color = opts[
                "watermark_txt_color"] if "watermark_txt_color" in opts else "black"

            # make the image editable
            drawing = ImageDraw.Draw(self.img)

            if watermark_txt_color == "white":
                color = (255, 255, 255)
            else:
                color = (3, 8, 12)
            #font = ImageFont.truetype("pilbox/arial.ttf", watermark_txt_size)
            font = ImageFont.truetype(
                "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
                watermark_txt_size)
            drawing.text(pos, watermark_txt, fill=color, font=font)

        elif watermark_img:
            # Get watermark image ratio
            watermark_img_ratio = int(
                opts["watermark_img_ratio"] if "watermark_img_ratio" in
                opts else 5) / 100

            # Get watermark image
            watermark = PIL.Image.open(
                BytesIO(Image.get_watermark_img(watermark_img)))

            # Get size of target image
            width, height = self.img.size
            # Resize watermark to a percentage of the target image's height
            targetHeight = int(height * watermark_img_ratio)
            hpercent = (watermark.size[0] / float(watermark.size[1]))
            wsize = int(targetHeight * float(hpercent))
            watermark = watermark.resize((wsize, targetHeight))

            # Create new watermarked images
            transparent = PIL.Image.new('RGBA', (width, height), (0, 0, 0, 0))
            transparent.paste(self.img, (0, 0))
            transparent.paste(watermark, box=pos, mask=watermark)
            self.img = transparent
Example #17
0
 def validate_options(opts):
     opts = Image._normalize_options(opts)
     if opts["mode"] not in Image.MODES:
         raise ModeError("Invalid mode: %s" % opts["mode"])
     elif opts["filter"] not in Image.FILTERS:
         raise FilterError("Invalid filter: %s" % opts["filter"])
     elif opts["position"] not in Image.POSITIONS:
         raise PositionError("Invalid position: %s" % opts["position"])
     elif not Image._isint(opts["background"], 16) \
             or len(opts["background"]) not in [3, 4, 6, 8]:
         raise BackgroundError("Invalid background: %s" % opts["background"])
     elif not Image._isint(opts["quality"]) \
             or int(opts["quality"]) > 100 or int(opts["quality"]) < 0:
         raise QualityError("Invalid quality: %s", str(opts["quality"]))
Example #18
0
 def validate_options(opts):
     opts = Image._normalize_options(opts)
     if opts["mode"] not in Image.MODES:
         raise ModeError("Invalid mode: %s" % opts["mode"])
     elif opts["filter"] not in Image.FILTERS:
         raise FilterError("Invalid filter: %s" % opts["filter"])
     elif opts["position"] not in Image.POSITIONS:
         raise PositionError("Invalid position: %s" % opts["position"])
     elif not Image._isint(opts["background"], 16) \
             or len(opts["background"]) not in [3, 4, 6, 8]:
         raise BackgroundError("Invalid background: %s" %
                               opts["background"])
     elif not Image._isint(opts["quality"]) \
             or int(opts["quality"]) > 100 or int(opts["quality"]) < 0:
         raise QualityError("Invalid quality: %s", str(opts["quality"]))
Example #19
0
    def region(self, rect, width=False, height=False, **kwargs):
        """ Selects a sub-region of the image using the supplied rectangle,
            x, y, width, height.
        """
        box = (int(rect[0]), int(rect[1]), int(rect[0]) + int(rect[2]), int(rect[1]) + int(rect[3]))
        if box[2] > self.img.size[0] or box[3] > self.img.size[1]:
            raise errors.RectangleError("Region out-of-bounds")
        self.img = self.img.crop(box)

        if width or height:
            opts = Image._normalize_options(kwargs)
            size = self._get_size(width, height)
            self._scale(size, opts)

        return self
Example #20
0
    def save(self, **kwargs):
        """Returns a buffer to the image for saving, supports the
        following optional keyword arguments:

        format - The format to save as: see Image.FORMATS
        optimize - The image file size should be optimized
        preserve_exif - Preserve the Exif information in JPEGs
        progressive - The output should be progressive JPEG
        quality - The quality used to save JPEGs: integer from 1 - 100
        """
        opts = Image._normalize_options(kwargs)
        outfile = BytesIO()
        if opts["pil"]["format"]:
            fmt = opts["pil"]["format"]
        else:
            fmt = self._orig_format
        save_kwargs = dict()

        if Image._isint(opts["quality"]):
            save_kwargs["quality"] = int(opts["quality"])

        if int(opts["optimize"]):
            save_kwargs["optimize"] = True

        if int(opts["progressive"]):
            save_kwargs["progressive"] = True

        if int(opts["preserve_exif"]):
            save_kwargs["exif"] = self._exif

        color = color_hex_to_dec_tuple(opts["background"])
        if self.img.mode == "RGBA":
            self._background(fmt, color)

        if self._orig_format == "JPEG":
            self.img.format = self._orig_format
            save_kwargs["subsampling"] = "keep"
            if opts["quality"] == "keep":
                save_kwargs["quality"] = "keep"

        try:
            self.img.save(outfile, fmt, **save_kwargs)
        except IOError as e:
            raise errors.ImageSaveError(str(e))
        self.img.format = fmt
        outfile.seek(0)

        return outfile
Example #21
0
    def save(self, **kwargs):
        """Returns a buffer to the image for saving, supports the
        following optional keyword arguments:

        format - The format to save as: see Image.FORMATS
        optimize - The image file size should be optimized
        preserve_exif - Preserve the Exif information in JPEGs
        progressive - The output should be progressive JPEG
        quality - The quality used to save JPEGs: integer from 1 - 100
        """
        opts = Image._normalize_options(kwargs)
        outfile = BytesIO()
        if opts["pil"]["format"]:
            fmt = opts["pil"]["format"]
        else:
            fmt = self._orig_format
        save_kwargs = dict()

        if Image._isint(opts["quality"]):
            save_kwargs["quality"] = int(opts["quality"])

        if int(opts["optimize"]):
            save_kwargs["optimize"] = True

        if int(opts["progressive"]):
            save_kwargs["progressive"] = True

        if int(opts["preserve_exif"]):
            save_kwargs["exif"] = self._exif

        color = color_hex_to_dec_tuple(opts["background"])
        if self.img.mode == "RGBA":
            self._background(fmt, color)

        if self._orig_format == "JPEG":
            self.img.format = self._orig_format
            save_kwargs["subsampling"] = "keep"
            if opts["quality"] == "keep":
                save_kwargs["quality"] = "keep"

        try:
            self.img.save(outfile, fmt, **save_kwargs)
        except IOError as e:
            raise errors.ImageSaveError(str(e))
        self.img.format = fmt
        outfile.seek(0)

        return outfile
Example #22
0
    def save(self, **kwargs):
        """Returns a buffer to the image for saving, supports the
        following optional keyword arguments:

        format - The format to save as: see Image.FORMATS
        quality - The quality used to save JPEGs: integer from 1 - 100
        """
        opts = Image._normalize_options(kwargs)
        outfile = BytesIO()
        if opts["pil"]["format"]:
            fmt = opts["pil"]["format"]
        else:
            fmt = self._orig_format
        self.img.save(outfile, fmt, quality=int(opts["quality"]))
        outfile.seek(0)

        return outfile
Example #23
0
    def save(self, **kwargs):
        """Returns a buffer to the image for saving, supports the
        following optional keyword arguments:

        format - The format to save as: see Image.FORMATS
        quality - The quality used to save JPEGs: integer from 1 - 100
        """
        opts = Image._normalize_options(kwargs)
        outfile = BytesIO()
        if opts["pil"]["format"]:
            fmt = opts["pil"]["format"]
        else:
            fmt = self._orig_format
        self.img.save(outfile, fmt, quality=int(opts["quality"]))
        outfile.seek(0)

        return outfile
Example #24
0
    def rotate(self, deg, **kwargs):
        """ Rotates the image clockwise around its center.  Returns the
        instance. Supports the following optional keyword arguments:

        expand - Expand the output image to fit rotation
        """
        opts = Image._normalize_options(kwargs)

        if deg == "auto":
            if self._orig_format == "JPEG":
                exif = self.img._getexif() or dict()
                deg = _orientation_to_rotation.get(exif.get(274, 0), 0)
            else:
                deg = 0

        expand = False if int(deg) % 90 == 0 else bool(int(opts["expand"]))
        self.img = self.img.rotate(360 - int(deg), expand=expand)
        return self
Example #25
0
    def resize(self, width, height, **kwargs):
        """Returns a buffer to the resized image for saving, supports the
        following optional keyword arguments:

        mode - The resizing mode to use, see Image.MODES
        filter - The filter to use: see Image.FILTERS
        background - The hexadecimal background fill color, RGB or ARGB
        position - The position used to crop: see Image.POSITIONS
        quality - The quality used to save JPEGs: integer from 1 - 100
        """
        img = PIL.Image.open(self.stream)
        if img.format.lower() not in self.FORMATS:
            raise FormatError("Unknown format: %s" % img.format)
        opts = Image._normalize_options(kwargs, self.defaults)
        resized = self._resize(img, self._get_size(img, width, height), opts)
        outfile = BytesIO()
        resized.save(outfile, img.format, quality=int(opts["quality"]))
        outfile.seek(0)
        return outfile
Example #26
0
    def resize(self, width, height, **kwargs):
        """Returns a buffer to the resized image for saving, supports the
        following optional keyword arguments:

        mode - The resizing mode to use, see Image.MODES
        filter - The filter to use: see Image.FILTERS
        background - The hexadecimal background fill color, RGB or ARGB
        position - The position used to crop: see Image.POSITIONS
        quality - The quality used to save JPEGs: integer from 1 - 100
        """
        img = PIL.Image.open(self.stream)
        if img.format.lower() not in self.FORMATS:
            raise FormatError("Unknown format: %s" % img.format)
        opts = Image._normalize_options(kwargs, self.defaults)
        resized = self._resize(img, self._get_size(img, width, height), opts)
        outfile = BytesIO()
        resized.save(outfile, img.format, quality=int(opts["quality"]))
        outfile.seek(0)
        return outfile
Example #27
0
 def validate_options(opts):
     opts = Image._normalize_options(opts)
     if opts["mode"] not in Image.MODES:
         raise errors.ModeError("Invalid mode: %s" % opts["mode"])
     elif opts["filter"] not in Image.FILTERS:
         raise errors.FilterError("Invalid filter: %s" % opts["filter"])
     elif opts["format"] and opts["format"] not in Image.FORMATS:
         raise errors.FormatError("Invalid format: %s" % opts["format"])
     elif opts["position"] not in Image.POSITIONS \
             and not opts["pil"]["position"]:
         raise errors.PositionError("Invalid position: %s" %
                                    opts["position"])
     elif not Image._isint(opts["background"], 16) \
             or len(opts["background"]) not in [3, 4, 6, 8]:
         raise errors.BackgroundError("Invalid background: %s" %
                                      opts["background"])
     elif not Image._isint(opts["quality"]) \
             or int(opts["quality"]) > 100 or int(opts["quality"]) < 0:
         raise errors.QualityError("Invalid quality: %s",
                                   str(opts["quality"]))
Example #28
0
    def rotate(self, deg, **kwargs):
        """ Rotates the image clockwise around its center.  Returns the
        instance. Supports the following optional keyword arguments:

        expand - Expand the output image to fit rotation
        """
        opts = Image._normalize_options(kwargs)

        if deg == "auto":
            if self._orig_format == "JPEG":
                try:
                    exif = self.img._getexif() or dict()
                    deg = _orientation_to_rotation.get(exif.get(274, 0), 0)
                except:
                    logger.warn('unable to parse exif')
                    deg = 0
            else:
                deg = 0

        expand = False if int(deg) % 90 == 0 else bool(int(opts["expand"]))
        self.img = self.img.rotate(360 - int(deg), expand=expand)
        return self
Example #29
0
 def validate_options(opts):
     opts = Image._normalize_options(opts)
     if opts["mode"] not in Image.MODES:
         raise errors.ModeError("Invalid mode: {}".format(opts["mode"]))
     elif opts["filter"] not in Image.FILTERS:
         raise errors.FilterError("Invalid filter: {}".format(opts["filter"]))
     elif opts["format"] and opts["format"] not in Image.FORMATS:
         raise errors.FormatError("Invalid format: {}".format(opts["format"]))
     elif opts["position"] not in Image.POSITIONS and not opts["pil"]["position"]:
         raise errors.PositionError("Invalid position: {}".format(opts["position"]))
     elif not Image._isint(opts["background"], 16) or len(opts["background"]) not in [3, 4, 6, 8]:
         raise errors.BackgroundError("Invalid background: {}".format(opts["background"]))
     elif opts["optimize"] and not Image._isint(opts["optimize"]):
         raise errors.OptimizeError("Invalid optimize: {}".format(str(opts["optimize"])))
     elif opts["quality"] != "keep" and (not Image._isint(opts["quality"]) or int(opts["quality"]) > 100 or
                                                 int(opts["quality"]) < 0):
         raise errors.QualityError("Invalid quality: {}".format(str(opts["quality"])))
     elif opts["preserve_exif"] and not Image._isint(opts["preserve_exif"]):
         raise errors.PreserveExifError("Invalid preserve_exif: {}".format(str(opts["preserve_exif"])))
     elif opts["progressive"] and not Image._isint(opts["progressive"]):
         raise errors.ProgressiveError("Invalid progressive: {}".format(str(opts["progressive"])))
     elif (not Image._isint(opts["retain"]) or int(opts["retain"]) > 100 or int(opts["retain"]) < 0):
         raise errors.RetainError("Invalid retain: {}".format(str(opts["retain"])))
Example #30
0
 def scaleToAspectRatio(self,ar,padding,**kwargs):
     opts = Image._normalize_options(kwargs)
     tokens=ar.split(":")
     ratio=float(tokens[0])/float(tokens[1])
     width=self.img.size[0]
     height=self.img.size[1]
     pad=0.05
     if padding:
         pad=float(padding)
     if width==height:
         width=width*ratio
     elif height>width:
         width=height*ratio
     else:
         height=height/ratio
     paddingH=int(width*pad)
     paddingV=int(height*pad)
     width=int(width)
     height=int(height)
     logger.debug("New Size : "+str([width,height]))
     self._clip((width,height), opts)
     if self.img.size == (width,height) and not padding:
         return  # No need to fill
     x= ((width+paddingH)-self.img.size[0])/2
     y= ((height+paddingV)-self.img.size[1])/2
     color = color_hex_to_dec_tuple(opts["background"])
     mode = "RGBA" if len(color) == 4 else "RGB"
     logger.debug("New Size with Padding: "+str((width+paddingH, height+paddingV)))
     img = PIL.Image.new(mode=mode, size=(width+paddingH, height+paddingV), color=(255, 255, 255))
     # If the image has an alpha channel, use it as a mask when
     # pasting onto the background.
     channels = self.img.split()
     mask = channels[3] if len(channels) == 4 else None
     img.paste(self.img, (int(x),int(y)), mask=mask)
     self._skip_background = True
     self.img = img
Example #31
0
 def __init__(self, stream, defaults=dict()):
     self.stream = stream
     self.defaults = Image._normalize_options(defaults)
Example #32
0
 def __init__(self, stream, defaults=dict()):
     self.stream = stream
     self.defaults = Image._normalize_options(defaults)