Jpeg의 exif 정보 분석에 대해서
디지털 카메라로 찍은 파일에서, exif 정보를 뽑기 위해서 관련 자료를 보고 하나씩 찾아가던 중에 Rational(유리수) 값을 어떻게 뽑아내는지 궁금해서 글을 올립니다.
http://www.linuxstudy.pe.kr/~ntames8/photo/test/exifdump.py
위 파일로 디카로 찍은 Jpeg파일의 Exif 정보를 추출할 수 있지만, 저는 제가 원하는 값들만 추출하고 싶은 상황으로 위 파일을 참조만 하려고 합니다.
파일 중간에
EXIF_TAGS = { 0x100: "ImageWidth", 0x101: "ImageLength", 0x102: "BitsPerSample", 0x103: "Compression", .............중략........... 0x9102: "CompressedBitsPerPixel", 0x9201: "ShutterSpeedValue", 0x9202: "ApertureValue", 0x9203: "BrightnessValue", 0x9204: "ExposureBiasValue", .............중략........... 0xA002: "ExifImageWidth", 0xA003: "ExifImageLength", 0xA005: "InteroperabilityOffset", .............중략........... 0xA301: "SceneType", }
와 같이 헤더를 정의하는 곳이 있습니다. 실제 Jpeg 파일 상에도 이와 같은 헤더 코드 부분을 찾을 수 있었습니다.
0000000: ffd8 ffe1 25fd 4578 6966 0000 4949 2a00 ....%.Exif..II*. 0000010: 0800 0000 0700 0f01 0200 1600 0000 6200 ..............b. 0000020: 0000 1001 0200 1c00 0000 7800 0000 1a01 ..........x..... 0000030: 0500 0100 0000 9400 0000 1b01 0500 0100 ................ 0000040: 0000 9c00 0000 2801 0300 0100 0000 0200 ......(......... 0000050: 0000 1302 0300 0100 0000 0200 0000 6987 ..............i. 0000060: 0400 0100 0000 a400 0000 f201 0000 5361 ..............Sa 0000070: 6d73 756e 6720 2020 2020 2020 2020 2020 msung 0000080: 2020 2000 4469 6769 6d61 7820 3230 3020 .Digimax 200 0000090: 2020 2020 2020 2020 2020 2020 2020 2000 . 00000a0: 4800 0000 0100 0000 4800 0000 0100 0000 H.......H....... 00000b0: 0f00 0090 0700 0400 0000 3032 3130 0390 ..........0210.. 00000c0: 0200 1400 0000 5e01 0000 0490 0200 1400 ......^......... 00000d0: 0000 7201 0000 0191 0700 0400 0000 0102 ..r............. 00000e0: 0300 00a0 0700 0400 0000 3031 3030 01a0 ..........0100.. 00000f0: 0300 0100 0000 0100 0000 02a0 0400 0100 ................ 0000100: 0000 2003 0000 03a0 0400 0100 0000 5802 .. ...........X. 0000110: 0000 0992 0300 0100 0000 0000 0000 0291 ................ 0000120: 0500 0100 0000 8601 0000 0292 0500 0100 ................ 0000130: 0000 8e01 0000 9a82 0500 0100 0000 9601 ................ 0000140: 0000 0ba2 0500 0100 0000 9e01 0000 8692 ................ 0000150: 0700 2e00 0000 a601 0000 05a0 0400 0100 ................ 0000160: 0000 d401 0000 0000 0000 3230 3034 3a30 ..........2004:0 0000170: 393a 3239 2030 333a 3134 3a33 3400 3230 9:29 03:14:34.20 0000180: 3031 3a30 353a 3330 2031 353a 3330 3a33 01:05:30 15:30:3 0000190: 3000 0200 0000 0100 0000 0500 0000 0100 0............... 00001a0: 0000 1d00 0000 1027 0000 0400 0000 0100 .......'........ 00001b0: 0000 4153 4349 4900 0000 2020 2020 2020 ..ASCII... 00001c0: 2020 2020 2020 2020 2020 2020 2020 2020 00001d0: 2020 2020 2020 2020 2020 2020 2020 2020 00001e0: 0200 0100 0200 0400 0000 5239 3800 0200 ..........R98... .......................................생략.............................
위 코드 화면과 같이 xxd 유틸리티를 이용해서 Jpeg 파일을 열어보았습니다.
보시다시피, 0xA002 헤더부분은 ExifImageWidth 값입니다.
00000f0: 0300 0100 0000 0100 0000 02a0 0400 0100 ................ 0000100: 0000 2003 0000 03a0 0400 0100 0000 5802 .. ...........X.
Jpeg의 Offset 0x00FA에 0x02a0가 보이실 겁니다. 이 부분은 Intel Order식으로 해석하자면, 0xa002가 되므로 Width부분이 확실합니다.
0400 0100 0000 2003 0000 까지가 여기에 해당되는 값이 되는 것인데,
맨 앞 2Word는 각각 0x0004와 0x0001로 제 생각에는 Exif을 보는 유틸리티 파일에서
def print_IFD(fields, dict=EXIF_TAGS): for (tag,type,values) in fields: try: stag = dict[tag] except: stag = '0x%04X' % tag stype = ['B', # BYTE 'A', # ASCII 'S', # SHORT 'L', # LONG 'R', # RATIONAL 'SB', # SBYTE 'U', # UNDEFINED 'SS', # SSHORT 'SL', # SLONG 'SR', # SRATIONAL ] [type-1] ..........생략...........
와 같이 4번째 'L'을 뜻하는 것 같습니다. 실제 실행해본 결과 값으로
ExifImageWidth(L)=[800]
ExifImageLength(L)=[600]
Flash(S)=[0]
CompressedBitsPerPixel(R)=[2/1]
ApertureValue(R)=[5/1]
ExposureTime(R)=[29/10000]
FlashEnergy(R)=[4/1]
와 같이 나왔습니다. 괄호가 값 형태를 의미하는 것이겠죠? 그래서 L이라는 겁니다.
그다음 0x0001은 인식하는 갯수를 의미하는 것 같습니다. 2로 되어 있다면 값으로 [xxx,yyy] 식으로 나오게 됩니다. 1이므로 [xxx]와 같이 나오는 것이죠(테스트의 결과로 확신하는 것입니다).
2003값은 0x0320으로 10진수로 800이 되는 겁니다.
여기까지는 제가 해석한 부분이고 이제 질문을 드리겠습니다.
바로 위 인용부분에서 보이다시피, CompressedBitsPerPixel(R)과 같은 Rational 값입니다. 어떻게 저렇게 2/1이란 값이 나오게 되었는지 모르겠습니다. 부연 설명 더 들어갑니다.
0000110: 0000 0992 0300 0100 0000 0000 0000 0291 ................ 0000120: 0500 0100 0000 8601 0000 0292 0500 0100 ................ 0000130: 0000 8e01 0000 9a82 0500 0100 0000 9601 ................ 0000140: 0000 0ba2 0500 0100 0000 9e01 0000 8692 ................
CompressedBitsPerPixel은 0x9102(offset 0x000011E) 부분으로 시작하게 됩니다. 0500 0100 0000 8601 0000 까지인데, 앞의 4Bytes는 이 값이 5번째 'R'이고, 1개의 값이라는 것을 알려줍니다. 뒤값 0000 8601 0000 이 어떻게 [2/1]이 나오게 되는지가 궁금합니다.
마찬가지로 Rational 으로 표현되는 값들을 더 쓰자면, 0x9202는 ApertureValue(조리개) 값으로 0500 0100 0000 8301 0000까지 입니다. 역시 'R'에 1개의 값입니다. 이것은 [5/1]입니다.
추가로 제가 임의로 위의 CompressedBitsPerPixel의 값을 변경해보았었습니다. 0000 8501 0000로 해보니까 값으로 [512/256]이 나왔었습니다.
제 수학적인 지식으로는 풀기 어려워서 이곳에 문의를 드립니다. 조금이라도 이쪽으로 관심이 있으거나, 약간의 지식이 있으신 분 조금의 도움이라도 주시면 감사하겠습니다.;; 참고로 내일 군대 복귀날입니다..ㅜ.ㅜ;; 그 전까지는..
http://blog.empas.com/changyong2/781655 에서 개인적으로 많은 참조를 하고 있었습니다.
제가 기록하고 있는 위키도 참고적으로 알려드립니다.
http://linuxstudy.pe.kr/~ntames8/wiki/wiki.php/exif
겨우 알아냈습니다.
0x8601 에 0x9601로 값을 고쳐보니,
ExposureTime(R)=[29/10000]와 같이 CompressedBitsPerPixel(R)=[29/10000]이 나오는 것입니다.
한참 헤맨 끝에 이 것이 offset이라는 것을 알았습니다.
Exif의 offset(0xc)에 0x9102 TAG가 가지고 있는 값 0x8601은 0x0186이므로 더하게 되면 0x000c + 0x0186 = 0x0192
0000190: 3000 0200 0000 0100 0000 0500 0000 0100 0...............
처음 0200 0000 은 2, 0100 0000 은 1 해서 이렇게 2/1이 나온겁니다.
제가 :lol: 참 바보스럽네요. 읽어주신 분들께 감사드립니다.
이거 덕분에 내일 잘 복귀할 수 있을 듯 ㅡㅡ;;
----
http://linu.sarang.net, http://wbhacker.tistory.com
java library
http://www.drewnoakes.com/code/exif/
혹시 필요할 때를 위해서 링크 걸어놉니다.
----
I paint objects as I think them, not as I see them.
atie's minipage
댓글 달기