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)
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)
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)
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}")
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)
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)
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)
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)
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))
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))
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)
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)