2009-10-22 4 views
20

파이썬을 사용하여 그림의 크기를 조정하려고합니다. 내 카메라로 파일은 모두 가로 방향으로 작성되었습니다.PIL을 사용하여 회전 EXIF ​​정보의 크기를 조정하고 파일에 적용하는 방법?

exif 정보는 이미지 뷰어에게 다른 방식으로 회전하도록 요청하는 태그를 처리합니다. 브라우저의 대부분이이 정보를 이해하지 못하므로이 EXIF ​​정보를 사용하고 다른 모든 EXIF ​​정보를 유지하면서 이미지를 회전하고 싶습니다.

파이썬을 사용하여 어떻게 할 수 있는지 알고 있습니까?

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를 사용할 수 있습니다

는 EXIF.py 소스 코드를 읽고, 그 뭔가를 발견?

+0

자세한 정보는 http://www.abc-view.com/articles/article5.html이 값과 관련하여 특정 프로세스에서 함수를 사용해야한다고 생각합니까? – Natim

+2

좋은 질문입니다! PIL로 JPEG를 무손실로 회전시킬 수 있습니까 (예 :'jpegtran')? 무손실 변환 없이는이 작업을 고려하지 않습니다. – u0b34a0f6ae

답변

15

마침내 pyexiv2을 사용했지만 GNU 이외의 다른 플랫폼에 설치하는 것은 약간 까다 롭습니다.

#!/usr/bin/python 
# -*- coding: utf-8 -*- 
# Copyright (C) 2008-2009 Rémy HUBSCHER <[email protected]> - 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 

개선 될 수있는 점이 있다면 (파이썬 2.5에 대한 내용을 제외하고) 알려주십시오.

+1

파일 경로를 얻기 위해 glob 모듈을 사용했다면 listJPEG 함수가 조금 더 짧을 것이라고 생각합니다. _mkdir()을 사용하지 않는 표준 라이브러리에 os.makedirs가 있고, 크기가 조정 된 JPEG를 쓰는 코드 블록이 있습니다. 메타 데이터 복사 기능을 중복 코드를 피하기 위해 리팩토링해야합니다. 어쩌면 파일 형식 등을 조정하기위한 추가 명령 줄 매개 변수가 필요합니다. – fbuchinger

+0

좋습니다.고마워요 :) – Natim

+0

저는 파티에 좀 늦었습니다.하지만 StackOverflow 답변은 cc-wiki에서 라이센스를 받았으며이 답변은 GPL로 응답하는 내용과 충돌합니다. –

2

먼저 카메라에 회전 센서가 있는지 확인해야합니다. 센서가없는 대부분의 카메라 모델은 모든 사진에 대해 방향 태그를 1 (수평)로 설정하기 만합니다.

그렇다면 귀하의 경우에는 pyexiv2와 pyjpegtran을 사용하는 것이 좋습니다. PIL은 pyjpegtran의 도메인 인 무손실 순환을 지원하지 않습니다. pyexiv2는 한 이미지에서 다른 이미지로 메타 데이터를 복사 할 수있는 라이브러리입니다 (메소드 이름이 copyMetadata라고 생각합니다).

사진을 브라우저에 표시하기 전에 사진의 크기를 조정하지 않으시겠습니까? 8 메가 픽셀 JPEG는 브라우저 창에 비해 너무 커서 끝없는로드 시간이 발생합니다.

+0

내가 말했듯이 그림을 크기를 조정하고 회전하여 유용한 EXIF ​​정보를 유지하려고합니다. – Natim

6

PIL은 EXIF ​​메타 데이터를 읽을 수 있지만 이미지 파일을 변경하고 이미지 파일에 다시 쓸 수는 없습니다.

더 나은 선택은 pyexiv2 라이브러리입니다. 이 라이브러리를 사용하면 사진의 방향을 뒤집을 수 있습니다. 다음은 그 예입니다 :

import sys 
import pyexiv2 

image = pyexiv2.Image(sys.argv[1]) 
image.readMetadata() 

image['Exif.Image.Orientation'] = 6 
image.writeMetadata() 

이것은 "Rotated 90 CW"에 해당하는 방향을 6으로 설정합니다.

+0

실제로 카메라가 이미 Exif.Image.Orientation 태그를 설정 했으므로 EXIF ​​정보를 이해할 수 없더라도 브라우저가 이미지를 표시 할 수 있도록 오른쪽 방향으로 이미지를 쓰려고합니다. 어쨌든, pyexiv2는 필자가 필요로하는 라이브러리입니다. 당신이 내 코드에서 볼 수 있듯이. – Natim

관련 문제