当前位置: 首页 > 面试题库 >

如何使用PIL调整大小和将旋转EXIF信息应用于文件?

吴哲
2023-03-14
问题内容

我正在尝试使用Python调整图片大小。用我的相机,所有文件都是横向写的。

exif信息处理一个标签,要求图像查看器以某种方式旋转。由于大多数浏览器都不了解此信息,因此我想使用此EXIF信息来旋转图像,并保留所有其他EXIF信息。

您知道如何使用Python做到这一点吗?

阅读EXIF.py源代码,我发现了类似的内容:

0x0112: ('Orientation',
         {1: 'Horizontal (normal)',
          2: 'Mirrored horizontal',
          3: 'Rotated 180',
          4: 'Mirrored vertical',
          5: 'Mirrored horizontal then rotated 90 CCW',
          6: 'Rotated 90 CW',
          7: 'Mirrored horizontal then rotated 90 CW',
          8: 'Rotated 90 CCW'})

如何使用此信息和PIL进行应用?


问题答案:

我最终使用了pyexiv2,但是要在除GNU之外的其他平台上安装也有些棘手。

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (C) 2008-2009 Rémy HUBSCHER <natim@users.sf.net> - http://www.trunat.fr/portfolio/python.html

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

# Using :
#   - Python Imaging Library PIL    http://www.pythonware.com/products/pil/index.htm
#   - pyexiv2                       http://tilloy.net/dev/pyexiv2/

###
# What is doing this script ?
#
#  1. Take a directory of picture from a Reflex Camera (Nikon D90 for example)
#  2. Use the EXIF Orientation information to turn the image
#  3. Remove the thumbnail from the EXIF Information
#  4. Create 2 image one maxi map in 600x600, one mini map in 200x200
#  5. Add a comment with the name of the Author and his Website
#  6. Copy the EXIF information to the maxi and mini image
#  7. Name the image files with a meanful name (Date of picture)

import os, sys
try:
    import Image
except:
    print "To use this program, you need to install Python Imaging Library - http://www.pythonware.com/products/pil/"
    sys.exit(1)

try:
    import pyexiv2
except:
    print "To use this program, you need to install pyexiv2 - http://tilloy.net/dev/pyexiv2/"
    sys.exit(1)

############# Configuration ##############
size_mini = 200, 200
size_maxi = 1024, 1024

# Information about the Photograph should be in ASCII
COPYRIGHT="Remy Hubscher - http://www.trunat.fr/"
ARTIST="Remy Hubscher"
##########################################

def listJPEG(directory):
    "Retourn a list of the JPEG files in the directory"
    fileList = [os.path.normcase(f) for f in os.listdir(directory)]
    fileList = [f for f in fileList if os.path.splitext(f)[1]  in ('.jpg', '.JPG')]
    fileList.sort()
    return fileList

def _mkdir(newdir):
    """
    works the way a good mkdir should :)
      - already exists, silently complete
      - regular file in the way, raise an exception
      - parent directory(ies) does not exist, make them as well
    """
    if os.path.isdir(newdir):
        pass
    elif os.path.isfile(newdir):
        raise OSError("a file with the same name as the desired " \
                      "dir, '%s', already exists." % newdir)
    else:
        head, tail = os.path.split(newdir)
        if head and not os.path.isdir(head):
            _mkdir(head)
        if tail:
            os.mkdir(newdir)

if len(sys.argv) < 3:
    print "USAGE : python %s indir outdir [comment]" % sys.argv[0]
    exit

indir  = sys.argv[1]
outdir = sys.argv[2]

if len(sys.argv) == 4:
    comment = sys.argv[1]
else:
    comment = COPYRIGHT

agrandie = os.path.join(outdir, 'agrandie')
miniature = os.path.join(outdir, 'miniature')

print agrandie, miniature

_mkdir(agrandie)
_mkdir(miniature)

for infile in listJPEG(indir):
    mini  = os.path.join(miniature, infile)
    grand = os.path.join(agrandie, infile)
    file_path = os.path.join(indir, infile)

    image = pyexiv2.Image(file_path)
    image.readMetadata()

    # We clean the file and add some information
    image.deleteThumbnail()

    image['Exif.Image.Artist'] = ARTIST
    image['Exif.Image.Copyright'] = COPYRIGHT

    image.setComment(comment)

    # I prefer not to modify the input file
    # image.writeMetadata()

    # We look for a meanful name
    if 'Exif.Image.DateTime' in image.exifKeys():
        filename = image['Exif.Image.DateTime'].strftime('%Y-%m-%d_%H-%M-%S.jpg')
        mini  = os.path.join(miniature, filename)
        grand = os.path.join(agrandie, filename)
    else:
        # If no exif information, leave the old name
        mini  = os.path.join(miniature, infile)
        grand = os.path.join(agrandie, infile)

    # We create the thumbnail
    #try:
    im = Image.open(file_path)
    im.thumbnail(size_maxi, Image.ANTIALIAS)

    # We rotate regarding to the EXIF orientation information
    if 'Exif.Image.Orientation' in image.exifKeys():
        orientation = image['Exif.Image.Orientation']
        if orientation == 1:
            # Nothing
            mirror = im.copy()
        elif orientation == 2:
            # Vertical Mirror
            mirror = im.transpose(Image.FLIP_LEFT_RIGHT)
        elif orientation == 3:
            # Rotation 180°
            mirror = im.transpose(Image.ROTATE_180)
        elif orientation == 4:
            # Horizontal Mirror
            mirror = im.transpose(Image.FLIP_TOP_BOTTOM)
        elif orientation == 5:
            # Horizontal Mirror + Rotation 90° CCW
            mirror = im.transpose(Image.FLIP_TOP_BOTTOM).transpose(Image.ROTATE_90)
        elif orientation == 6:
            # Rotation 270°
            mirror = im.transpose(Image.ROTATE_270)
        elif orientation == 7:
            # Horizontal Mirror + Rotation 270°
            mirror = im.transpose(Image.FLIP_TOP_BOTTOM).transpose(Image.ROTATE_270)
        elif orientation == 8:
            # Rotation 90°
            mirror = im.transpose(Image.ROTATE_90)

        # No more Orientation information
        image['Exif.Image.Orientation'] = 1
    else:
        # No EXIF information, the user has to do it
        mirror = im.copy()

    mirror.save(grand, "JPEG", quality=85)
    img_grand = pyexiv2.Image(grand)
    img_grand.readMetadata()
    image.copyMetadataTo(img_grand)
    img_grand.writeMetadata()
    print grand

    mirror.thumbnail(size_mini, Image.ANTIALIAS)
    mirror.save(mini, "JPEG", quality=85)
    img_mini = pyexiv2.Image(mini)
    img_mini.readMetadata()
    image.copyMetadataTo(img_mini)
    img_mini.writeMetadata()
    print mini

    print

如果您发现可以改进的地方(除了仍然适用于Python 2.5,请告诉我)。



 类似资料:
  • 这可能会导致问题,特别是如果有问题的设备依赖于“方向”标签来正确地垂直显示图像。 不同的Android设备以不同的方式处理相机/图像旋转--我信任的旧Nexus One似乎总是在捕获后立即旋转图像,因此文件的原生内容在查看时总是“直立”。 然而,其他设备(尤其是我测试的三星手机)不会旋转图像文件的内容--相反,它们设置了Exif“方向”标签。每当稍后显示图像时,相关的图像代码应该检测到方向“标签”

  • 问题内容: 当我尝试使用PIL调整图像大小(缩略图)时,exif数据丢失。 我该怎么做才能将exif数据保留在缩略图中?当我搜索相同的内容时,获得了一些链接,但似乎没有任何作用。 原始图像具有exif数据,但图像im(512_a.JPEG)没有。 问题答案: import pyexiv2 from PIL import Image 现在我使用(Patch Image Inspector)打开图像,

  • 本文档概述了您可以用来调整图像的裁剪、旋转和画布大小的各种方法。 使用裁剪命令裁剪图像 使用选区工具来选择要保留的图像部分。 选取“图像”>“裁剪”。 使用裁切命令裁剪图像 “裁切”命令通过移去不需要的图像数据来裁剪图像,其所用的方式与“裁剪”命令所用的方式不同。可以通过裁切周围的透明像素或指定颜色的背景像素来裁剪图像。 选取“图像”>“裁切”。 在“裁切”对话框中选择选项: “透明像素”修整掉图

  • 我正在开发一个应用程序,它具有通过拖动右下角按钮来调整和旋转imageview的功能。 我看到一个应用程序,它有一个功能,如果我们拖动右下角的按钮对角,imageview大小已经调整,或者如果我们拖动按钮向左或向右的方向,imageview已经按照方向旋转。我希望在我的应用程序中实现此功能 我正在努力实现单指旋转以及调整imageview的大小。 我可以通过拖动它的右下角按钮成功地实现调整图像视图

  • 我有一个UIViewController,当设备旋转时,它只旋转其中的一些子视图。这在iOS7下运行良好,但在iOS8下会中断。UIView的边界似乎是由iOS8下的变换调整的。这是出乎意料的。 这里有一些代码: 我们在UIViewController上创建了一个类别来处理此行为。以下是相关代码: 以下是笔尖的外观: nib中名为pinned的UIView是pinnedControls的IBOut

  • 问题内容: 有什么明显的方法可以实现我所缺少的吗?我只是想制作缩略图。 问题答案: 定义最大尺寸。然后,通过计算调整大小比例。 适当大小。 当然,还有一个库方法可以做到这一点:。 以下是PIL文档中的一个(经过编辑的)示例。