사진 원본을 읽어서 썸네일 이미지를 만드는 간단한 이미지 변환기를 만들 일이 생겼는데...


Bitmap.FromFile() 함수에서 사진 파일을 읽는데 오류가 발생했다.


A generic error occurred in GDI+.

HResult: 0x80004005



혹시나 해서 Image.FromStream() 등 여러가지 방법으로 바꿔봐도 똑같은 에러가 났다.


그냥 PC상에서 여러 이미지 뷰어 프로그램으로 시도해봐도 똑같은 에러가 나고 읽어지지 않았다.


원본 파일이 깨진 것이다.


그런데, 특정 프로그램(XnShell)에서는 미리보기 그림이 정상 표시되는 것이 이상했다.


깨졌지만 깨진 것이 아니다?


이리저리 검색해봐도 파일을 저장할 때 오류가 발생하는 케이스가 대부분이고

그 경우에 시간을 잠깐 둔다든가 Close를 호출하지 않는다든가 등등 우회하는 방법 등등만 잔뜩 나와 있지 

파일을 읽을 때 발생하는 오류를 처리하는 방법은 없었다.


혹시나 하고, GIMP라는 프로그램을 받아서 한번 읽어봤다.

이미지 포맷 처리를 가장 관대하게(?) 하는 프로그램이라나 뭐라나...



왠 걸... 꽝이다.

뭔가 헤더가 어쩌고, 마커가 어쩌고 설명이 있는데, 깨진 게 맞단다.


이참에 JPEG 포맷을 한번 들여다 봤다.


>> 참조: http://cometkorea.tistory.com/56


뭔가 내용이 많이 복잡하긴 한데, 내가 알고 싶은 내용은 일단 명확하게 일관성은 있어 보인다.


JPEG 파일 헤더는 원래 FF D8 (이미지 시작 헤더)가 가장 앞에 오고

FF E0 (APP0 마커) 섹션을 그 다음부터 붙이기 시작해서, 헤더 정보를 확장하기에 따라 

FF E1 (APP1 마커) ~ FF EF (APP15 마커) 섹션까지 추가로 들어갈 수 있도록 되어 있는데 

그 중 특정 마커 섹션에 잘못된 데이터가 들어있으면 오류가 발생할 수 있다고 한다.

(예를 들면 크기 정보가 0 이라든가...)


>> 참조: https://stackoverflow.com/questions/1143882/error-while-loading-jpeg-a-generic-error-occurred-in-gdi



그래서 오류가 발생하는 파일을 한번 열어봤다.




설명대로, FF D8 FF E0 으로 시작한다. 이건 항상 그렇다고 하니 공통 헤더 정도로 알아놔도 되겠다.

또, 둘째 줄 중간에 FF E1 도 보이는 것을 보니 뭔가 확장을 하긴 했구나... 정도는 알겠다.


좀 더 들여다 봤다. 뭐가 문제인건지...



엇, 이상한 게 보인다.


FF D8 FF E0 이 중간에 다시 나오는 걸까?

분명히 FF D8은 파일 맨 처음에 나오는 이미지 시작 헤더 정보라고 했는데 말이다.


아... 알겠다.

그러니까 어떤 프로그램에서 이 FF D8 헤더가 이미 있음에도 불구하고 

앞에다 새로운 FF D8 헤더로 시작하는 추가 헤더를 붙여 버린 것이다. 


쯧쯧... 그러니 깨진 걸로 나오지.


이걸 고치는 방법은 간단했다.

처음부터 중간에 보이는 저 FF D8 FF E0 앞까지를 지워버리면 끝.


내 경우는 다행히 특정 APP 섹션에 잘못된 데이터가 들어있는 것이 아니라

헤더가 통째로 중복되었던 것이다.


C# 콘솔 프로그램으로 간략하게 FF D8 FF E0 바이트 패턴을 찾아서 그 앞까지는 무시하고 

뒤의 나머지 데이터만 이용해서 새 메모리 스트림(MemoryStream)을 만든 다음 

이미지로 로딩해보니 아주 잘 되었다.


이후부터는 일사천리. 이미지 썸네일을 만들고 새 파일을 쓰는 코드까지 뚝딱.

(코드 샘플은 생략... 방법을 몰라 그렇지 방법만 알면 나머지는 인터넷 뒤져보면 다 나온다.)


다른 JPEG 파일들도 만약 깨졌으면 이런 방법으로 손상을 치료할 수 있을 듯 해서

기록으로 남겨둔다.





Posted by 떼르미
,


자바스크립트를 허용해주세요!
Please Enable JavaScript![ Enable JavaScript ]