mwultong Blog ... 프로그래밍 / 계산기

컴퓨터 엑셀 워드 포토샵 구글어스 WINDOWS JAVASCRIPT JAVA C++

 
Thursday, May 17, 2007

Perl 펄] 디카 메타 정보를, JPG, RAW (NEF) 파일명으로 변경 유틸리티; Exif to Filename


디카로 찍은 사진의 메타 정보(조리개 값, 셔터 속도 등등)를 파일명으로 자동 변경하는 펄 프로그램 소스입니다. 디카에서 PC로 뽑은 사진은

DSC_0001.JPG
DSC_0002.JPG
DSC_0003.JPG
...

이런 무의미한 파일명으로 되어 있어 알아보기 힘듭니다. 그리고 파일명이 유니크하지도 않기에, 사진을 겹쳐쓰게 될 위험이 있습니다.

JPG 등의 사진 파일 속에 들어 있는 실제 촬영 정보 (촬영날짜/조리개/셔터 속도 등)를 읽어서, 다음과 같은 파일명으로 바꾸어 주면 편리할 것입니다.

NIKON-D40X 20070515-205344-90 ISO200 51mm F4.5 S1-60 (18-55mm f-3.5-5.6).jpg

카메라마다 Exif 정보 형태가 많이 다르기 때문에, 아래의 프로그램이 모든 카메라의 사진에서 잘 작동하지는 않습니다. 가령 니콘 DSLR에는 초단위 이하의 촬영 시각이 나오는데, 캐논은 없는 것 같았습니다.

따라서 자신의 디카에 맞게 소스를 적절히 수정해야 합니다. 컴팩트 카메라(똑딱이)에는 "DateTimeOriginal" 이라는 태그가 없어서 "DateTime" 이라는 태그를 사용해야 할 것입니다. 그러나 니콘 DSLR의 사진에서는 대부분 잘 작동했습니다. 제가 개인적으로 쓰려고 만든 프로그램이기에 범용성이 떨어지고 소스도 지저분합니다-_-;


사용법


* 시스템에 펄이 설치되어 있어야 합니다. 윈도우에서는 액티브펄을 설치하면 적당합니다.

* 아래의 펄 소스는 독자적으로 실행되지 않고, 다음의 펄 모듈을 설치해 주어야 합니다: ▶▶ Perl 펄] Image::ExifTool::Exif 모듈 다운로드 설치법

위의 모듈을 설치하면 "TagNames.pod" 라는 텍스트 파일이 있는데, 이 파일 안에, Exif 태그 목록이 있습니다. 자신의 카메라에서 지원하는 태그를 골라서 소스를 수정하면 됩니다. (물론 펄 프로그래밍을 할 줄 아시는 분만 가능합니다.)

* 펄 소스를 하드에 저장한 후, 도스창이나 터미널에서
exif2fn.pl
이라고 치면, 현재 디렉토리의 모든 사진 파일들의 이름이 변경됩니다. 다만 메타 정보가 없는 파일은 무시됩니다.

Y 키를 누르면 변경
N 키를 누르면 다음 파일로 건너뛰기
A 키를 누르면, 묻지 않고, 모든 파일 한꺼번에 변경
Q 키를 누르면 종료

(대문자가 아닌 소문자 키를 눌러도 됩니다.)


메타 정보 (Exif;조리개값, 셔터속도 등)를 파일명으로 변경


파일명: exif2fn.pl
(※ 스크롤 박스 사용법: 박스 안을 마우스로 클릭한 후, 키보드의 좌우 화살표키를 누르면 양옆으로 움직일 수 있습니다. 박스에서 다시 나오려면, 박스 바깥의 아무곳이나 클릭하면 됩니다.)
#!/usr/bin/perl
use strict; use warnings;

# v0.5d

use Image::ExifTool;
use File::Basename;
use Term::ReadKey; # getAkey

  my $exifTool = new Image::ExifTool;


  # 현재 디렉토리의 모든 파일명들을 배열로 저장
  opendir(DIR, ".") or die "$!\n";
  my @items = readdir(DIR);  # @items 라는 배열에, 파일 목록 넣기
  closedir DIR;


  # 기타 변수 선언
  my $all = 0;
  my $choice;




# 본격 작업 시작
# 현재 디렉토리의 사진 파일들을 모두
# Exif 문자열로 리네임

LOOP: foreach (@items) { # 각 파일을 대상으로 하나씩 작업
  my $filename = $_;
  next unless (-f $filename); # 디렉토리면 건너뛰기
  my ($fileNameOnly, $dir, $ext) = fileparse($filename, '\.[^.]*');
  next if ($ext !~ /^\.jpg$|^\.jpeg$|^\.nef$|^\.tif$|^\.tiff$/i); # JPG / RAW 등의 확장자만 대상으로

  my $exif_str = getExif($filename); # 사진 파일의 Exif 정보 읽기
  if (defined $exif_str) { # Exif 정보 있는 파일만 처리
    print "\"$filename\" 를 아래의 파일명으로 바꿀까요? [ y(es)/n(o)/a(ll)/q(uit) ]", "\n"; # 각 파일명 출력
    my $filename_new = $exif_str . lc($ext);
    print $filename_new, "\n";

    for (;;) { # 사용자 허락받은 후 파일명 변경
      if ($all == 1) { $choice = "a"; }
      else { $choice = getAkey(); } # 키보드 입력 받기

      if ($choice =~ /^a/) { $all = 1; }

      if ($choice =~ /^y/ || $all == 1) { # Yes면 변경
        if (-f $filename_new) { warn "같은 파일명이 이미 존재함!\n"; }
        else { rename($filename, $filename_new) or warn "변경 실패!\n"; }
        last;
      }
      elsif ($choice =~ /^n/) { last; } # No 면 다음 파일로 건너뛰기
      elsif ($choice =~ /^q/) { last LOOP; } # LOOP를 완전히 빠져나가라는 의미
    }
    print "\n";
  }

}



# 파일의 Exif 정보를 읽어서, 한줄의 문자열로 요약하여 반환 함수
sub getExif {
  my $info = $exifTool->ImageInfo($_[0]);
  my ($temp, @temp, $s);


  # 카메라 모델명
  $temp = $$info{"Model"};
  return undef if not defined $temp; # 모델명 없으면 에러 반환
  $temp =~ s/[\s]/-/g;
  $s = $temp;


  # 날짜/시간 처리
  @temp = split(/[:\s]/, $$info{"DateTimeOriginal"});
  $s .= " " . $temp[0] . $temp[1] . $temp[2] . "-" . $temp[3] . $temp[4] . $temp[5];


  # 초 단위 이하 처리
  $temp = $$info{"SubSecTimeOriginal"};
  if (defined $temp) {
    $s .= "-" . $temp;
  } else {
    $s .= "-XX";
  }



  # 감도
  # (니콘은 1600보다 높으면, "Hi 3200" 이라고 나오는데, 여기서 숫자만 추출)
  @temp = $$info{"ISO"} =~ /[\d.*]/g;
  $s .= " ISO" . join("", @temp);


  # 초점 거리 (35미리 포맷으로 환산한 초점거리)
  $temp = $$info{"FocalLengthIn35mmFormat"};
  if (defined $temp) {
    $s .= " " . $temp;
  } else {
    $s .= " XX";
  }
  $s .= "mm";


  # 조리개
  $temp  = $$info{"FNumber"};
  $s .= " F" . $temp;


  # 셔터 속도
  $temp = $$info{"ExposureTime"};
  $s .= " S" . $temp;


  # 카메라 수평/수직 방향
  if ($$info{"Orientation"} !~ "Horizontal") {
    $s .= " [V]";
  }


  # 렌즈 스펙
  $temp = $$info{"Lens"};
  if (defined $temp) {
    $s .= " (" . $temp . ")";
  }


  # 모든 슬래시를 하이픈으로 변환. 파일명에는 슬래시(/) 기호 허용 안됨
  $s =~ s/[\/]/-/g;


  return $s;
}


# 키보드에서 영문 딱 1글자만 입력받는 함수 (Enter키 칠 필요 없음)
sub getAkey {
  ReadMode 'cbreak';
  my $key = ReadKey(0);
  print $key; # echo 가 안되어서 억지로 출력
  ReadMode 'normal';

  return lc($key); # 소문자로 변환한 후 반환
}


업데이트: 버그 몇 가지를 수정했는데, 버그가 더 있을 수 있으니, 사진 파일의 사본을 대상으로 충분히 테스트한 후 사용하시기 바랍니다.


실행 결과 화면:
D:\Z\000>exif2fn.pl
"DSC_0077.JPG" 를 아래의 파일명으로 바꿀까요? [ y(es)/n(o)/a(ll)/q(uit) ]
NIKON-D40X 20070512-232324-00 ISO400 82mm F7.1 S1-30 (18-55mm f-3.5-5.6).jpg
y
"DSC_0082.JPG" 를 아래의 파일명으로 바꿀까요? [ y(es)/n(o)/a(ll)/q(uit) ]
NIKON-D40X 20070512-232405-80 ISO500 82mm F5.6 S1-30 (18-55mm f-3.5-5.6).jpg
a
"DSC_0083.JPG" 를 아래의 파일명으로 바꿀까요? [ y(es)/n(o)/a(ll)/q(uit) ]
NIKON-D40X 20070513-214319-30 ISO3200 27mm F3.5 S1-13 (18-55mm f-3.5-5.6).jpg

"DSC_0084.JPG" 를 아래의 파일명으로 바꿀까요? [ y(es)/n(o)/a(ll)/q(uit) ]
NIKON-D40X 20070513-214348-60 ISO1600 27mm F3.5 S1-10 (18-55mm f-3.5-5.6).jpg

"DSC_0085.JPG" 를 아래의 파일명으로 바꿀까요? [ y(es)/n(o)/a(ll)/q(uit) ]
NIKON-D40X 20070513-214505-00 ISO1600 27mm F3.5 S1-10 (18-55mm f-3.5-5.6).jpg

"DSC_0086.JPG" 를 아래의 파일명으로 바꿀까요? [ y(es)/n(o)/a(ll)/q(uit) ]
NIKON-D40X 20070513-214551-60 ISO1600 27mm F3.5 S1-60 (18-55mm f-3.5-5.6).jpg


D:\Z\000>



이제 숫자로 된 파일명이, 다음과 같이 의미 있는 이름으로 변경되어 있을 것입니다:
NIKON-D40X 20070510-003838-40 ISO100 82mm F5.6 S1-60 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070510-114020-50 ISO100 57mm F5.6 S1-15 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070512-231207-50 ISO800 82mm F10.0 S1-30 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070512-231254-10 ISO800 82mm F9.0 S1-30 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070512-232322-90 ISO400 82mm F6.3 S1-30 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070512-232324-00 ISO400 82mm F7.1 S1-30 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070512-232405-80 ISO500 82mm F5.6 S1-30 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070513-214319-30 ISO3200 27mm F3.5 S1-13 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070513-214348-60 ISO1600 27mm F3.5 S1-10 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070513-214505-00 ISO1600 27mm F3.5 S1-10 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070513-215132-70 ISO3200 27mm F3.5 S2 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070513-215212-30 ISO3200 27mm F3.5 S0.5 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070514-194914-60 ISO3200 27mm F3.5 S1-4 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070514-195059-20 ISO3200 36mm F4.0 S1-4 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070514-195214-10 ISO125 27mm F3.5 S2 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070514-195515-10 ISO900 27mm F3.5 S1-4 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070514-195557-80 ISO3200 27mm F3.5 S1-4 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070514-200112-00 ISO3200 27mm F3.5 S1-4 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070514-200234-90 ISO3200 27mm F3.5 S1-4 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070515-205344-90 ISO200 51mm F4.5 S1-60 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070515-205412-20 ISO200 57mm F5.0 S1-60 (18-55mm f-3.5-5.6).jpg
NIKON-D40X 20070515-205441-70 ISO200 57mm F5.0 S1-60 (18-55mm f-3.5-5.6).jpg
...



파일명 각 요소들의 설명은 다음과 같습니다:
* NIKON-D40X : 카메라 모델명
* 20070510-001827-40 : 년월일-시분초(24시간제)-초 이하 단위
* ISO200 : ISO 감도
* 27mm : 촬영시의 렌즈의 초점거리를 35mm 판으로 환산한 것
* F3.5 : 조리개
* S1-60 : 셔터 속도 (60분의 1초)
* [V] : 이 마크가 있을 경우에는 사진을 "세로 구도"로 찍었다는 뜻
* (18-55mm f-3.5-5.6) : 렌즈 스펙


셔터 속도 "1/1000" 즉 천분의 1초는 "S1-1000" 이렇게 표현됩니다. 파일명에는 슬래시(/)가 들어갈 수 없기에...

야경 등을 촬영하려고 노출을 20초 주었다면, "S20" 이렇게 나옵니다.

1.3초 노출했다면 "S1.3" 이렇게 나옵니다.


현재 이 프로그램에서는 ".jpg" 와, ".tif", 니콘 RAW 파일인 ".nef" 확장자만 인식하는데, 다른 메이커의 카메라는 그 메이커 고유의 Raw 파일 확장자를 소스에 추가하면 간단히 인식됩니다.


주의 사항: 파일명이 이렇게 길고 공백이 들어간 파일을, 인터넷에 올리거나 CD-ROM/DVD에 구우면 에러가 납니다. 인터넷에 올릴 때는 날짜 정도만 간단히 넣고 공백은 밑줄(_)로 변경해야 합니다.

너무 긴 파일명의 파일을 CD-ROM에 구우면, 설령 잘 구워지더라도, 다시 읽을 수 없게 되는 일이 있습니다.

CD-ROM에 사진들을 구울 때에는, 사진 파일들을 Zip 등으로 압축해서 굽는 것이 좋습니다. 그러면 파일명의 제약도 사라지고, CD-ROM 에 더 많은 사진을 넣을 수 있습니다. JPG 의 Exif 부분은 압축되어 있지 않기에 더 압축이 됩니다.



지정한 특정 사진 파일의 메타 정보 자세히 출력하기: ▶▶ Perl 펄] EXIF 정보 읽기, 디카 촬영 정보 출력 소스; Exif Info Dump




tag: perl
Perl | 펄
tag: camera
카메라 | 디카 DSLR | 사진용품 사용기

0 Comments:

<< Home RSS 2.0 feed

구글 Google 에서 제공하는 무료 블로그 서비스인 블로거 Blogger 의 인터넷 주소는 www.blogger.com 입니다. Blogger 에 블로그를 만들면, blogspot.com 이라는 주소에 블로그가 생성됩니다.
블로그를 직접 방문하지 않고도 최신 게시물을 구독하려면 RSS 2.0 feed 주소를 리더기에 등록하시면 됩니다.
Previous Posts
Monthly Archives
Top