Example #1
0
    def resize_image(self, src, dst, max_size):
        """Make a copy of the image in the requested size."""
        if not Image:
            utils.copy_file(src, dst)
            return
        im = Image.open(src)
        w, h = im.size
        if w > max_size or h > max_size:
            size = max_size, max_size
            try:
                exif = im._getexif()
            except Exception:
                exif = None
            if exif is not None:
                for tag, value in exif.items():
                    decoded = ExifTags.TAGS.get(tag, tag)

                    if decoded == 'Orientation':
                        if value == 3:
                            im = im.rotate(180)
                        elif value == 6:
                            im = im.rotate(270)
                        elif value == 8:
                            im = im.rotate(90)

                        break

            im.thumbnail(size, Image.ANTIALIAS)
            im.save(dst)

        else:
            utils.copy_file(src, dst)
Example #2
0
    def resize_image(self, src, dst, max_size, bigger_panoramas=True, preserve_exif_data=False, exif_whitelist={}):
        """Make a copy of the image in the requested size."""
        if not Image or os.path.splitext(src)[1] in ['.svg', '.svgz']:
            self.resize_svg(src, dst, max_size, bigger_panoramas)
            return
        im = Image.open(src)

        if hasattr(im, 'n_frames') and im.n_frames > 1:
            # Animated gif, leave as-is
            utils.copy_file(src, dst)
            return

        size = w, h = im.size
        if w > max_size or h > max_size:
            size = max_size, max_size

            # Panoramas get larger thumbnails because they look *awful*
            if bigger_panoramas and w > 2 * h:
                size = min(w, max_size * 4), min(w, max_size * 4)

        try:
            exif = piexif.load(im.info["exif"])
        except KeyError:
            exif = None
        # Inside this if, we can manipulate exif as much as
        # we want/need and it will be preserved if required
        if exif is not None:
            # Rotate according to EXIF
            value = exif['0th'].get(piexif.ImageIFD.Orientation, 1)
            if value in (3, 4):
                im = im.transpose(Image.ROTATE_180)
            elif value in (5, 6):
                im = im.transpose(Image.ROTATE_270)
            elif value in (7, 8):
                im = im.transpose(Image.ROTATE_90)
            if value in (2, 4, 5, 7):
                im = im.transpose(Image.FLIP_LEFT_RIGHT)
            exif['0th'][piexif.ImageIFD.Orientation] = 1

        try:
            im.thumbnail(size, Image.ANTIALIAS)
            if exif is not None and preserve_exif_data:
                # Put right size in EXIF data
                w, h = im.size
                if '0th' in exif:
                    exif["0th"][piexif.ImageIFD.ImageWidth] = w
                    exif["0th"][piexif.ImageIFD.ImageLength] = h
                if 'Exif' in exif:
                    exif["Exif"][piexif.ExifIFD.PixelXDimension] = w
                    exif["Exif"][piexif.ExifIFD.PixelYDimension] = h
                # Filter EXIF data as required
                exif = self.filter_exif(exif, exif_whitelist)
                im.save(dst, exif=piexif.dump(exif))
            else:
                im.save(dst)
        except Exception as e:
            self.logger.warn("Can't process {0}, using original "
                             "image! ({1})".format(src, e))
            utils.copy_file(src, dst)
Example #3
0
    def resize_image(self,
                     src,
                     dst,
                     max_size,
                     bigger_panoramas=True,
                     preserve_exif_data=False,
                     exif_whitelist={}):
        """Make a copy of the image in the requested size."""
        if not Image or os.path.splitext(src)[1] in ['.svg', '.svgz']:
            self.resize_svg(src, dst, max_size, bigger_panoramas)
            return
        im = Image.open(src)
        size = w, h = im.size
        if w > max_size or h > max_size:
            size = max_size, max_size

            # Panoramas get larger thumbnails because they look *awful*
            if bigger_panoramas and w > 2 * h:
                size = min(w, max_size * 4), min(w, max_size * 4)

        try:
            exif = piexif.load(im.info["exif"])
        except KeyError:
            exif = None
        # Inside this if, we can manipulate exif as much as
        # we want/need and it will be preserved if required
        if exif is not None:
            # Rotate according to EXIF
            value = exif['0th'].get(piexif.ImageIFD.Orientation, 1)
            if value in (3, 4):
                im = im.transpose(Image.ROTATE_180)
            elif value in (5, 6):
                im = im.transpose(Image.ROTATE_270)
            elif value in (7, 8):
                im = im.transpose(Image.ROTATE_90)
            if value in (2, 4, 5, 7):
                im = im.transpose(Image.FLIP_LEFT_RIGHT)
            exif['0th'][piexif.ImageIFD.Orientation] = 1

        try:
            im.thumbnail(size, Image.ANTIALIAS)
            if exif is not None and preserve_exif_data:
                # Put right size in EXIF data
                w, h = im.size
                if '0th' in exif:
                    exif["0th"][piexif.ImageIFD.ImageWidth] = w
                    exif["0th"][piexif.ImageIFD.ImageLength] = h
                if 'Exif' in exif:
                    exif["Exif"][piexif.ExifIFD.PixelXDimension] = w
                    exif["Exif"][piexif.ExifIFD.PixelYDimension] = h
                # Filter EXIF data as required
                exif = self.filter_exif(exif, exif_whitelist)
                im.save(dst, exif=piexif.dump(exif))
            else:
                im.save(dst)
        except Exception as e:
            self.logger.warn("Can't process {0}, using original "
                             "image! ({1})".format(src, e))
            utils.copy_file(src, dst)
Example #4
0
    def import_content(self):
        """Import content and supplemental files"""

        output_root = "posts" if self.is_post else "pages"
        self.write_to(output_root)
        # TODO: write cover image to `images/{dirname(preferred_path)}`
        if self.bundle_files:
            image_folder = os.path.join("images/", self.nikola_stub_folder())
            makedirs(image_folder)

            for bundle_file in self.bundle_files:
                copy_file(bundle_file, image_folder)
                log.info(f"Copied {bundle_file}")
Example #5
0
    def resize_image(self,
                     src,
                     dst,
                     max_size,
                     bigger_panoramas=True,
                     preserve_exif_data=False):
        """Make a copy of the image in the requested size."""
        if not Image or os.path.splitext(src)[1] in ['.svg', '.svgz']:
            self.resize_svg(src, dst, max_size, bigger_panoramas)
            return
        im = Image.open(src)
        w, h = im.size
        if w > max_size or h > max_size:
            size = max_size, max_size

            # Panoramas get larger thumbnails because they look *awful*
            if bigger_panoramas and w > 2 * h:
                size = min(w, max_size * 4), min(w, max_size * 4)

            try:
                exif = im._getexif()
            except Exception:
                exif = None
            _exif = im.info.get('exif')
            if exif is not None:
                for tag, value in list(exif.items()):
                    decoded = ExifTags.TAGS.get(tag, tag)

                    if decoded == 'Orientation':
                        if value == 3:
                            im = im.rotate(180)
                        elif value == 6:
                            im = im.rotate(270)
                        elif value == 8:
                            im = im.rotate(90)
                        break
            try:
                im.thumbnail(size, Image.ANTIALIAS)
                if _exif is not None and preserve_exif_data:
                    im.save(dst, exif=_exif)
                else:
                    im.save(dst)
            except Exception as e:
                self.logger.warn("Can't thumbnail {0}, using original "
                                 "image as thumbnail ({1})".format(src, e))
                utils.copy_file(src, dst)
        else:  # Image is small
            utils.copy_file(src, dst)
Example #6
0
    def resize_svg(self, src, dst_paths, max_sizes, bigger_panoramas):
        """Make a copy of an svg at the requested sizes."""
        # Resize svg based on viewport hacking.
        # note that this can also lead to enlarged svgs
        if src.endswith('.svgz'):
            with gzip.GzipFile(src, 'rb') as op:
                xml = op.read()
        else:
            with open(src, 'rb') as op:
                xml = op.read()

        for dst, max_size in zip(dst_paths, max_sizes):
            try:
                tree = lxml.etree.XML(xml)
                width = tree.attrib['width']
                height = tree.attrib['height']
                w = int(re.search("[0-9]+", width).group(0))
                h = int(re.search("[0-9]+", height).group(0))
                # calculate new size preserving aspect ratio.
                ratio = float(w) / h
                # Panoramas get larger thumbnails because they look *awful*
                if bigger_panoramas and w > 2 * h:
                    max_size = max_size * 4
                if w > h:
                    w = max_size
                    h = max_size / ratio
                else:
                    w = max_size * ratio
                    h = max_size
                w = int(w)
                h = int(h)
                tree.attrib.pop("width")
                tree.attrib.pop("height")
                tree.attrib['viewport'] = "0 0 %ipx %ipx" % (w, h)
                if dst.endswith('.svgz'):
                    op = gzip.GzipFile(dst, 'wb')
                else:
                    op = open(dst, 'wb')
                op.write(lxml.etree.tostring(tree))
                op.close()
            except (KeyError, AttributeError) as e:
                self.logger.warning(
                    "No width/height in %s. Original exception: %s" % (src, e))
                utils.copy_file(src, dst)
Example #7
0
    def resize_image(self, src, dst, max_size, bigger_panoramas=True, preserve_exif_data=False):
        """Make a copy of the image in the requested size."""
        if not Image or os.path.splitext(src)[1] in ['.svg', '.svgz']:
            self.resize_svg(src, dst, max_size, bigger_panoramas)
            return
        im = Image.open(src)
        w, h = im.size
        if w > max_size or h > max_size:
            size = max_size, max_size

            # Panoramas get larger thumbnails because they look *awful*
            if bigger_panoramas and w > 2 * h:
                size = min(w, max_size * 4), min(w, max_size * 4)

            try:
                exif = im._getexif()
            except Exception:
                exif = None
            _exif = im.info.get('exif')
            if exif is not None:
                for tag, value in list(exif.items()):
                    decoded = ExifTags.TAGS.get(tag, tag)

                    if decoded == 'Orientation':
                        if value == 3:
                            im = im.rotate(180)
                        elif value == 6:
                            im = im.rotate(270)
                        elif value == 8:
                            im = im.rotate(90)
                        break
            try:
                im.thumbnail(size, Image.ANTIALIAS)
                if _exif is not None and preserve_exif_data:
                    im.save(dst, exif=_exif)
                else:
                    im.save(dst)
            except Exception as e:
                self.logger.warn("Can't thumbnail {0}, using original "
                                 "image as thumbnail ({1})".format(src, e))
                utils.copy_file(src, dst)
        else:  # Image is small
            utils.copy_file(src, dst)
Example #8
0
    def resize_image(self, src, dst, max_size):
        """Make a copy of the image in the requested size."""
        if not Image:
            utils.copy_file(src, dst)
            return
        im = Image.open(src)
        w, h = im.size
        if w > max_size or h > max_size:
            size = max_size, max_size

            # Panoramas get larger thumbnails because they look *awful*
            if w > 2 * h:
                size = min(w, max_size * 4), min(w, max_size * 4)

            try:
                exif = im._getexif()
            except Exception:
                exif = None
            if exif is not None:
                for tag, value in list(exif.items()):
                    decoded = ExifTags.TAGS.get(tag, tag)

                    if decoded == 'Orientation':
                        if value == 3:
                            im = im.rotate(180)
                        elif value == 6:
                            im = im.rotate(270)
                        elif value == 8:
                            im = im.rotate(90)

                        break

            try:
                im.thumbnail(size, Image.ANTIALIAS)
            except Exception:
                utils.show_msg("WARNING: can't thumbnail {0}".format(src))
                pass
            else:
                im.save(dst)

        else:
            utils.copy_file(src, dst)
Example #9
0
    def resize_image(self, src, dst, max_size):
        """Make a copy of the image in the requested size."""
        if not Image:
            utils.copy_file(src, dst)
            return
        im = Image.open(src)
        w, h = im.size
        if w > max_size or h > max_size:
            size = max_size, max_size

            # Panoramas get larger thumbnails because they look *awful*
            if w > 2 * h:
                size = min(w, max_size * 4), min(w, max_size * 4)

            try:
                exif = im._getexif()
            except Exception:
                exif = None
            if exif is not None:
                for tag, value in list(exif.items()):
                    decoded = ExifTags.TAGS.get(tag, tag)

                    if decoded == 'Orientation':
                        if value == 3:
                            im = im.rotate(180)
                        elif value == 6:
                            im = im.rotate(270)
                        elif value == 8:
                            im = im.rotate(90)

                        break

            try:
                im.thumbnail(size, Image.ANTIALIAS)
            except Exception:
                utils.show_msg("WARNING: can't thumbnail {0}".format(src))
                pass
            else:
                im.save(dst)

        else:
            utils.copy_file(src, dst)
Example #10
0
 def resize_svg(self, src, dst, max_size, bigger_panoramas):
     """Make a copy of an svg at the requested size."""
     try:
         # Resize svg based on viewport hacking.
         # note that this can also lead to enlarged svgs
         if src.endswith('.svgz'):
             with gzip.GzipFile(src, 'rb') as op:
                 xml = op.read()
         else:
             with open(src, 'rb') as op:
                 xml = op.read()
         tree = lxml.etree.XML(xml)
         width = tree.attrib['width']
         height = tree.attrib['height']
         w = int(re.search("[0-9]+", width).group(0))
         h = int(re.search("[0-9]+", height).group(0))
         # calculate new size preserving aspect ratio.
         ratio = float(w) / h
         # Panoramas get larger thumbnails because they look *awful*
         if bigger_panoramas and w > 2 * h:
             max_size = max_size * 4
         if w > h:
             w = max_size
             h = max_size / ratio
         else:
             w = max_size * ratio
             h = max_size
         w = int(w)
         h = int(h)
         tree.attrib.pop("width")
         tree.attrib.pop("height")
         tree.attrib['viewport'] = "0 0 %ipx %ipx" % (w, h)
         if dst.endswith('.svgz'):
             op = gzip.GzipFile(dst, 'wb')
         else:
             op = open(dst, 'wb')
         op.write(lxml.etree.tostring(tree))
         op.close()
     except (KeyError, AttributeError) as e:
         self.logger.warn("No width/height in %s. Original exception: %s" % (src, e))
         utils.copy_file(src, dst)
Example #11
0
    def import_item(self, pic, date, text):
        """Create a post file."""

        post_date = datetime.datetime.strptime(date, "%m/%d/%Y")
        title = "Twitpic: %s" % post_date.strftime("%d/%m/%Y")
        slug = utils.slugify(title)
        self.tags = ["Twitpic"] + self.extra_tags
        content = self.expand(text)
        base, ext = pic.split('.')
        content += """

.. figure:: %s.thumbnail.%s
  :target: %s
""" % (base, ext, pic)

        self.write_metadata(
            os.path.join(self.output_folder, slug + '.meta'),
            title, slug, post_date.strftime(r'%Y/%m/%d %H:%m:%S'), '', self.tags)
        self.write_content(
            os.path.join(self.output_folder, slug + '.rst'),
            content,
            False)
        utils.copy_file(os.path.join(self.path, pic), os.path.join("images", self.output_folder, slug, pic))
Example #12
0
    def import_item(self, pic, date, text):
        """Create a post file."""

        post_date = datetime.datetime.strptime(date, "%m/%d/%Y")
        title = "Twitpic: %s" % post_date.strftime("%d/%m/%Y")
        slug = utils.slugify(title)
        self.tags = ["Twitpic"] + self.extra_tags
        content = self.expand(text)
        base, ext = pic.split('.')
        content += """

.. figure:: %s.thumbnail.%s
  :target: %s
""" % (base, ext, pic)

        self.write_metadata(os.path.join(self.output_folder,
                                         slug + '.meta'), title, slug,
                            post_date.strftime(r'%Y/%m/%d %H:%m:%S'), '',
                            self.tags)
        self.write_content(os.path.join(self.output_folder, slug + '.rst'),
                           content, False)
        utils.copy_file(os.path.join(self.path, pic),
                        os.path.join("images", self.output_folder, slug, pic))
Example #13
0
    def resize_image(self, src, dst, max_size):
        """Make a copy of the image in the requested size."""
        if not Image:
            utils.copy_file(src, dst)
            return
        im = Image.open(src)
        w, h = im.size
        if w > max_size or h > max_size:
            size = max_size, max_size

            # Panoramas get larger thumbnails because they look *awful*
            if w > 2 * h:
                size = min(w, max_size * 4), min(w, max_size * 4)

            try:
                exif = im._getexif()
            except Exception:
                exif = None
            if exif is not None:
                for tag, value in list(exif.items()):
                    decoded = ExifTags.TAGS.get(tag, tag)

                    if decoded == "Orientation":
                        if value == 3:
                            im = im.rotate(180)
                        elif value == 6:
                            im = im.rotate(270)
                        elif value == 8:
                            im = im.rotate(90)
                        break
            try:
                im.thumbnail(size, Image.ANTIALIAS)
                im.save(dst)
            except Exception as e:
                self.logger.warn("Can't thumbnail {0}, using original " "image as thumbnail ({1})".format(src, e))
                utils.copy_file(src, dst)
        else:  # Image is small
            utils.copy_file(src, dst)
Example #14
0
    def resize_image(self,
                     src,
                     dst=None,
                     max_size=None,
                     bigger_panoramas=True,
                     preserve_exif_data=False,
                     exif_whitelist={},
                     preserve_icc_profiles=False,
                     dst_paths=None,
                     max_sizes=None):
        """Make a copy of the image in the requested size(s).

        max_sizes should be a list of sizes, and the image would be resized to fit in a
        square of each size (preserving aspect ratio).

        dst_paths is a list of the destination paths, and should be the same length as max_sizes.

        Backwards compatibility:

        * If max_sizes is None, it's set to [max_size]
        * If dst_paths is None, it's set to [dst]
        * Either max_size or max_sizes should be set
        * Either dst or dst_paths should be set
        """
        if dst_paths is None:
            dst_paths = [dst]
        if max_sizes is None:
            max_sizes = [max_size]
        if len(max_sizes) != len(dst_paths):
            raise ValueError(
                'resize_image called with incompatible arguments: {} / {}'.
                format(dst_paths, max_sizes))
        extension = os.path.splitext(src)[1].lower()
        if extension in {'.svg', '.svgz'}:
            self.resize_svg(src, dst_paths, max_sizes, bigger_panoramas)
            return

        _im = Image.open(src)

        # The jpg exclusion is Issue #3332
        is_animated = hasattr(
            _im, 'n_frames') and _im.n_frames > 1 and extension not in {
                '.jpg', '.jpeg'
            }

        exif = None
        if "exif" in _im.info:
            exif = piexif.load(_im.info["exif"])
            # Rotate according to EXIF
            if "0th" in exif:
                value = exif['0th'].get(piexif.ImageIFD.Orientation, 1)
                if value in (3, 4):
                    _im = _im.transpose(Image.ROTATE_180)
                elif value in (5, 6):
                    _im = _im.transpose(Image.ROTATE_270)
                elif value in (7, 8):
                    _im = _im.transpose(Image.ROTATE_90)
                if value in (2, 4, 5, 7):
                    _im = _im.transpose(Image.FLIP_LEFT_RIGHT)
                exif['0th'][piexif.ImageIFD.Orientation] = 1
            exif = self.filter_exif(exif, exif_whitelist)

        icc_profile = _im.info.get(
            'icc_profile') if preserve_icc_profiles else None

        for dst, max_size in zip(dst_paths, max_sizes):
            if is_animated:  # Animated gif, leave as-is
                utils.copy_file(src, dst)
                continue

            im = _im.copy()

            size = w, h = im.size
            if w > max_size or h > max_size:
                size = max_size, max_size
                # Panoramas get larger thumbnails because they look *awful*
                if bigger_panoramas and w > 2 * h:
                    size = min(w, max_size * 4), min(w, max_size * 4)
            try:
                im.thumbnail(size, Image.ANTIALIAS)
                save_args = {}
                if icc_profile:
                    save_args['icc_profile'] = icc_profile

                if exif is not None and preserve_exif_data:
                    # Put right size in EXIF data
                    w, h = im.size
                    if '0th' in exif:
                        exif["0th"][piexif.ImageIFD.ImageWidth] = w
                        exif["0th"][piexif.ImageIFD.ImageLength] = h
                    if 'Exif' in exif:
                        exif["Exif"][piexif.ExifIFD.PixelXDimension] = w
                        exif["Exif"][piexif.ExifIFD.PixelYDimension] = h
                    # Filter EXIF data as required
                    save_args['exif'] = piexif.dump(exif)

                im.save(dst, **save_args)
            except Exception as e:
                self.logger.warning("Can't process {0}, using original "
                                    "image! ({1})".format(src, e))
                utils.copy_file(src, dst)