본문 바로가기
APM

ImageMagick을 사용한 뒤집기, 크기, 회전

by 누피짱 2008. 5. 28.
큰 용량을 필요로 하는 작업을 한번에 처리하는 데는 명령행 툴만한 것이 없다. 이미지 조작도 예외는 아니다. 웹 개발자와 관리자들은 명령행이든 스크립트에서든지, 많은 파일들을 쉽게 다룰 수 있다는 것에 감사해 할 것이다. 프로그래머 Michael Still이 ImageMagick 수트를 소개한다.

이 글에서 명령행 툴을 사용하여 이미지를 조작하는 방법을 설명할 것이다. 디지털 카메라를 처음 구입했을 때부터 그리고 지금 수천 개의 스냅 사진들의 라이브러리를 관리하게 되면서부터 이 작업을 꽤 자주하고 있다. 수 많은 이미지들을 일괄 처리해야 하는 웹 개발자와 관리자들에게 명령행 툴은 더욱더 매력적이다. 왜냐하면 개발자는 이것을 스크립트와 통합할 수 있기 때문이다. 하지만 개발자가 아니더라도 이 툴은 시간을 줄일 수 있는 좋은 방법이다.

이 글에서 다룰 명령행 툴은 우수한 성능의 ImageMagick 수트의 일부이다. Red Hat Linux에 포함 되어 있고, 온라인에서 무료로 사용할 수 있다. (참고자료). ImageMagick은 C, C++, Perl, Python, Java 및 기타 여러 언어들을 통해 액세스 될 수 있다. 이것이 리눅스 프로그래머들이 감사해 하는 부분이다.

ImageMagick 작동 방법

ImageMagick은 libtiff와 libpng (참고자료)를 포함하여 다양한 이미징 바이너리에 대한 래퍼로서 구현된다. ImageMagick 용어로 하면 이것은 delegate이다. 바로 이것이 ImageMagick이 커스텀 애플리케이션만큼 빠르지 않은 이유이기도 하다. 그러한 라이브러리들이 이미지 데이터를 표현하는 다양한 방식을 다룰 수 있도록 일반적인 방법으로 작성되어야 했기 때문이다.

이 글에서 다루는 내용을 수행하는 많은 방법들이 있다는 것을 명심하라. 이 글에서는 내가 사용하는 방식을 다루는 것뿐이다. 다른 툴이 잘못되었다는 것이 아니라 지금 내가 사용하고 있는 툴에 내가 만족을 느끼고 있다는 의미이다.

여기에서는 예제들을 사용하여 특정 문제들을 설명하고자 한다. 하지만 개념 그 자체는 다른 문제들에도 적용할 수 있다.

섬네일(thumbnails) 생성하기

내 그림들로 했던 첫 번째 일은 간단한 섬네일(thumbnails) 을 만드는 것이었다. 또한 웹 사이트 버전에 맞게 이미지 크기도 줄여야 했다. 1920 대 1440 픽셀은 일반적으로 보기에 부담스럽다.

ImageMagick 수트의 일부인 변환 툴(convert tool)을 사용했다. 변환(Convert)은 매우 쉬웠다. 이미지 크기 조절 외에도 반 앨리어싱, 이미지 세트 균등 분배, 흐리게 하기, 이미지 포맷들 간 변환, 자르기, despeckle, 디더(dither), 보더 그리기, 뒤집기, 붙이기, 재 샘플링, 리사이징 등이 가능하다. 다양한 명령행 옵션에 대한 자세한 정보는 man 페이지를 참조하라. 많은 시각 효과들은 이 글 후반부에서 다루겠다.

장미 이미지의 섬네일(thumbnail)을 만드는 경우를 살펴보자.



그림 1. 장미 그림
A picture of a rose

convert로 이미지 크기를 재조정 하려면 -sample 명령행 옵션을 사용한다. 예를 들어, 섬네일을 80 x 40 픽셀로 만든다고 해보자. 명령행은 다음과 같다.

# convert -sample 80x40 input.jpg output.jpg

이 명령행은 아래와 같은 섬네일(thumbnail)을 만든다.



그림 2. 첫 번째 섬네일(thumbnail) 시도
A thumbnail of a rose

ImageMagick은 리사이징(resizing) 될 때 양쪽 이미지에서 만들어진 비율을 자동으로 따른다. 새로운 이미지의 비율은 이전 이미지의 비율과 같아진다. 위 예제에서 크기를 조정한 이미지는 80대 40이 아닌 53대 40이다. 결과 이미지의 크기를 지정하는 또 다른 방법은 백분율을 사용하는 것이다. 인풋 이미지 크기를 잘 모르거나 새로운 이미지가 정확한 크기가 되지 않아도 무관할 경우에 사용할 수 있다. 다음은 백분율 사용 예제이다.

# convert -sample 25%x25% input.jpg output.jpg

아래와 같은 섬네일(thumbnail)이 생겼다.



그림 3. 두 번째 섬네일(thumbnail) 시도
A thumbnail of a rose

이 명령어를 사용하여 팩토리 내의 이미지용 섬네일(thumbnail)도 만들 수 있다. 이 글은 쉘 스크립팅에 대한 글이 아니기 때문에, 현재 디렉토리에서 각 JPEG의 섬네일(thumbnail)을 만드는 방법을 설명하겠다.



Listing 1. 현재 디렉토리에서 모든 JPEG의 섬네일(thumbnail) 만들기
for img in `ls *.jpg` do convert -sample 25%x25% $img thumb-$img done

이 코드는 실제 이미지의 25% 정도 되는 섬네일(thumbnail)을 만든다. 파일 이름에는 기존 JPEG 파일 이름 앞에 thumb- 가 붙는다.




위로


이미지 파일 정보 수집하기

또 다른 작업으로는 이미지 파일의 치수를 결정하는 일이다. 이전 예제에서 어느 정도 크기로 섬네일(thumbnail)을 만들지 알아야 한다.

이미징 라이브러리에는 여기에 걸맞는 툴이 포함되어 있다. 예를 들어, libtiff (TIFF 라이브러리), (참고자료)에는 tiffinfo가 포함된다. 이것은 TIFF 파일에 대한 정보를 디스플레이 한다.

# tiffinfo sample.tif


Listing 2. tiffinfo의 아웃풋 샘플
TIFF Directory at offset 0x146 Image Width: 352 Image Length: 288 Bits/Sample: 8 Compression Scheme: Deflate Photometric Interpretation: RGB color Samples/Pixel: 3 Planar Configuration: single image plane

이것은 tiffinfo를 사용하는 방법을 설명한 완벽한 예제는 아니지만, 이미지 크기, 픽셀 범위(샘플 당 비트 수와 픽셀 당 샘플 수의 결합), 사용된 압축 스키마 같은 유용한 정보를 나타낸다.

이와 비슷하게, PNG 파일에 대해 비슷한 정보를 리턴하는 pnginfo 명령어가 있다.

# pnginfo sample.png


Listing 3. 의 아웃풋 샘플
sample.png... Image Width: 640 Image Length: 480 Bitdepth (Bits/Sample): 8 Channels (Samples/Pixel): 3 Pixel depth (Pixel Depth): 24 Colour Type (Photometric Interpretation): RGB Image filter: Single row per byte filter Interlacing: No interlacing Compression Scheme: Deflate method 8, 32k window Resolution: 0, 0 (unit unknown) FillOrder: msb-to-lsb Byte Order: Network (Big Endian) Number of text strings: 0 of 0

BMP, GIF, JPEG 같은 포맷용 툴은 잘 모르겠다. 하지만 ImageMagick의 도움을 한번 더 구해보자. 이번에는 identify라는 툴을 사용한다.

# identify -verbose sample.png


Listing 4. identify의 아웃풋 샘플
Image: sample.png Format: PNG (Portable Network Graphics) Geometry: 640x480 Class: DirectClass Type: true color Depth: 8 bits-per-pixel component Colors: 142360 Filesize: 555.6k Interlace: None Background Color: grey100 Border Color: #DFDFDF Matte Color: grey74 Dispose: Undefined Iterations: 0 Compression: Zip signature: 361fe70ae623ef6f1fca44e0d29d157c2d701039fcf0f8625862925d881e13a4 Tainted: False User Time: 0.190u Elapsed Time: 0:01

identify는 이미지 크기(픽셀), 이미지의 색상, 이미지 포맷 같은 유용한 파일 정보를 디스플레이 한다.

pnginfo

PNG를 사용하기 시작했을 때 얼마 동안은 tiffinfo를 사용했다. 그 당시에는 PNG 파일에 같은 tiffinfo것이 없었다. 바로 이런 이유로 pnginfo를 만들게 되었다. (pnginfo 다운로드 (참고자료)).

identify에는 명령행 -format 플래그가 있어서 출력하고 싶은 정보만 지정할 수 있다. 이미지 크기만 알고 싶다면 다음과 같이 한다.

# identify -format "%wx%h" sample.png

결과는 다음과 같다.

640x480

여기에서, %w는 이미지 넓이를, %h는 이미지의 길이를 의미한다. 자세한 정보는 identify man 페이지를 참조하라.




위로


이미지 회전

이미지 회전 역시 이미지 조작에 필요하다. 디지털 카메라로 찍었던 많은 사진들이 90o(90도) 회전이 가능하다. 내 카메라는 회전이 되지 않아 카메라에서 이미지를 다운로드 하면, 이를 수행하도록 스크립트를 만든다.

아래 그림은 Tasmania의 Port Arthur를 여행하다가 찍은 사진이다.



그림 4. Port Arthur 원본
A sideways picture of Port Arthur

이 그림을 돌리려면 convert 명령어가 필요하다.

# convert -rotate 90 input.jpg output.jpg

결과 이미지는 아래와 같다.



그림 5. Port Arthur
A picture of Port Arthur

-rotate 옵션의 인자는 오른쪽으로 이미지를 회전할 때의 각도이다. 왼쪽으로 돌리려면 음수를 사용하라.




위로


이미지 포맷 변경하기

convert 명령어는 이미지 파일의 포맷도 변환할 수 있다. JPEG 이미지를 PNG로 변환하는 것 외에, 회색으로 색상 변환하기, 디더(dither) 같은 이미지 포맷들 간 변환이 포함되어 있다.

convert는 명령행에서 정해진 파일 확장자를 통해, 인풋과 아웃풋이 어떤 이미지 포맷인지를 알고 있다. 따라서 JPEG를 PNG로 변환하려면 다음과 같은 명령행을 사용한다.

# convert input.jpg output.png

ImageMagick은 이 글을 쓰고 있는 지금 현재 89개의 이미지 포맷을 지원한다. 자세한 내용은 ImageMagick 웹 사이트(참고자료)를 참조하라.




위로


이미지에 텍스트 주석 추가하기

이미지에 글을 첨부해야 할 때가 있다. 표준 비즈니스 카드 이미지에 사원들의 상세를 입력해야 하는 경우도 이에 해당한다. 또는 웹 사이트로 온라인 과정을 통과한 사용자를 위한 인증서를 만들 경우도 있다.

다음 이미지로 시작해보자.



그림 6. Floriade 2002
Floriade 2002

다음 명령행을 사용하여 몇 가지 정보를 이미지에 넣을 수 있다.

# convert -font helvetica -fill white -pointsize 36 \
-draw 'text 10,50 "Floriade 2002, Canberra, Australia"' \
floriade.jpg comment.jpg

아래 그림을 보자.



그림 7. Floriade 2002: 주석 추가
Floriade 2002 after annotation

지금까지 이 글에서 설명한 convert 명령행 중 가장 복잡하다.

-font helvetica는 주석 폰트를 Helvetica로 설정한다. 폰트 파일로 가는 경로도 지정할 수 있다. 이 예제는 이미지에 주석을 달았기 때문에 허락 없이 다른 웹 사이트에서 사용될 수 없다. 다른 위치에 다른 폰트를 사용할 수도 있다.

# convert -font fonts/1900805.ttf -fill white -pointsize 36 \
-draw 'text 10,475 "stillhq.com"' \
floriade.jpg stillhq.jpg

결과는 다음과 같다.



그림 8. 뱃지 이미지
Floriade after badging

-fill white는 표준 검정색이 아닌 흰 색으로 글자의 안을 채운다.

-pointsize 36는 글자의 크기를 포인트로 지정한다. 1인치에 72 포인트이다.

-draw 'text 10,50 "..."'는 그리기 명령어이다. 이 경우 10, 50 위치로 이동하고, 더블 쿼트에 텍스트를 그린다. 한 단어 이상이 그려진다면 그리기 명령어 내에 더블 쿼트가 필요하고, 더블 쿼트 안에는 더블 쿼트를 넣을 수 없기 때문에 싱글 쿼트를 사용했다.




위로


예술적인 변환

convert는 매우 예술적인 변환도 구현할 수 있다. 보다 재미있는 시각적 구현에 대해 설명하겠다. 이 분야에 관심이 있다면 ImageMagick man 페이지와 웹 사이트를 참조하기 바란다. 다음은 예제로 사용할 인풋 이미지이다.



그림 9. Uluru의 일몰
Uluru

Ayer's Rock으로 알려진 이 Uluru 사진은 해질 무렵에 찍었다.

목탄 효과(charcoal)

목탄화 효과는 목탄화가가 그린 그림처럼 보이게 하는 것이다.

# convert -charcoal 2 input.jpg output.jpg

아래 그림을 보자.



그림 10. Uluru의 일몰: 목탄 효과
Uluru after a charcoal effect

-charcoal 옵션에 대한 인자의 크기를 늘리면, 이미지에 목탄 효과도 증가하고, 이미지 생성도 느려진다. 다음은 또 다른 목탄효과 예제이다.

# convert -charcoal 10 input.jpg output.jpg

위 명령어는 아래와 같은 결과를 만든다.



그림 11. Uluru의 일몰: 다른 목탄 효과
Uluru after more charcoal effect

과도하게 목탄효과를 낼 수도 있다.

# convert -charcoal 200 input.jpg output.jpg

결과는 다음과 같다.



그림 12. Uluru의 일몰: 과도한 목탄 효과
Uluru after even more charcoal effect
세 가지 값 지정하기

각각 빨간색, 녹색, 파란색 샘플에 값을 지정하려면, red/ green/ blue인자를 사용한다. 예를 들어, 10/ 20/ 30은 빨간색은 10을, 녹색은 20을, 파란색은 30을 갖고 있다는 뜻이다. 이 구조에서 백분율도 사용할 수 있다.

색상 입히기(colorize)

색상 입히기(Colorizing)입히기는 각 픽셀의 색상을 지정된 색상과 섞는 과정이다. 이 효과에 대한 인자는 섞을 색상이 된다. 이것은 (각각 빨간색, 녹색, 파란색에 사용될) 하나의 백분율로 지정되거나, 아니면 세 개의 백분율로 지정된다. 세 가지 실제 값들 중 한 개를 제공할 수도 있다.

# convert -colorize 255 input.jpg output.jpg

다음은 색상 입히기가 적용된 사진이다.



그림 13. Uluru의 일몰: 색상 입히기 적용
Uluru after a colorizing effect

임플로드(Implode)

임플로드 효과는 이미지의 중심이 가상의 블랙홀 안으로 빨려 들어가고 있는 것을 묘사한 것이다. 인자는 내부 파열(implosion) 효과의 양이 되겠다.

# convert -implode 4 input.jpg output.jpg

결과는 다음과 같다.



그림 14. Uluru의 일몰: 임플로드
Uluru after an implosion effect
solarize 인자

ImageMagick 문서에는 solarize에 대한 인자가 언제나 백분율로 되어있다고 언급하고 있다. 이것은 정확한 사실은 아니다. 인자의 끝에 백분율 표시가 되어 있다면 백분율로 간주된다. 하지만 백분율 표시가 없으면 숫자 그 자체 값으로 간주된다.

노출(solarize)

노출은 사진 작업 중에 네거티브(negative)가 빛에 노출될 때 발생하는 효과이다. 여기에서 인풋 인자는 이 효과가 적용되는 강도이다. 절대값으로 지정되거나 픽셀의 최대 값에 대한 백분율로 지정된다. 픽셀이 임계값 이상이면 무효가 된다.

# convert -solarize 42 input.jpg output.jpg

노출 효과가 적용된 그림을 보자.



그림 15. Uluru의 일몰: 노출 효과
Uluru after a solarization effect

스프레드(Spread)

Spread는 이미지 내에서 무작위로 픽셀들을 이동시킨다. 인자는 픽셀 주위의 영역 크기이다. 따라서 아웃풋과 인풋이 얼마나 닮도록 할 것인지를 지정하는 것이다.

# convert -spread 5 input.jpg output.jpg

바뀐 Uluru 사진을 보자.



그림 16. Uluru의 일몰: 스프레드 효과 적용
Uluru after a spreading effect



위로


ImageMagick 호출 시 사용되는 다중 명령어

주석 예제를 통해 연쇄 명령어 예제를 이미 보았다. 이 글에서 언급한 모든 ImageMagick 명령어들을 엮을 수 있다. 예를 들어, 이미지의 섬네일(thumbnail)을 만든 다음 여기에 스프레드를 적용해보자. 일단 스프레드가 발생하면 목탄 효과도 적용한다.

# convert -sample 25%x25% -spread 4 \ -charcoal 4 input.jpg output.jpg

결과물은 다음과 같다.



그림 17. Uluru의 일몰: 연쇄 효과 적용
Uluru after a chain of effects



위로


이미지 조작 팁

이미지를 변경하기 전에 이미지 조작에 대해 기억해야 할 것이 몇 가지 있다. 우선, 장기간 사용하게 될 이미지 포맷이 무엇인지를 생각해야 한다. 그러면 이미지 포맷을 변경할 때 convert를 사용할 수 있기 때문에 매우 편리하다.

JPEG 압축은 사진 같은 큰 용량의 이미지에 알맞다. 하지만 이것은 일반적으로 손실이 많다. (다시 말해서, 이미지 데이터가 압축 프로세스 중에 소실된다.) 이러한 이유로 텍스트 압축에는 잘 쓰지 않는다. 기억해야 할 또 한 가지는, 손실은 누적된다는 사실이다.

PNG는 칼라 이미지에 일반적으로 맞다. 손실이 축적되어 이미지 품질에 영향을 주고 싶지 않으면 PNG를 사용한다.

"Graphics programming with libtiff, Part 2" 를 참조하면 자세한 내용을 볼 수 있다. (참고자료).

이 글에서 설명한 이미지 조작 대부분이 일방적이다. 예를 들어, 이미지를 줄이면 그 이미지 데이터는 날라간다. 나중에 이미지를 다시 확대하면 결과는 엉망이 된다. 예를 들어, 사진을 찍어 섬네일(thumbnail)을 만들고, 그런 다음 이미지를 다시 확대해보자. 간단히 전후 이미지만 보여주겠다.



그림 18. 폭포
A waterfall

여기에서 확대와 축소를 함께 사용해 보겠다.

# convert -sample 10% -sample 1000% input.jpg output.jpg

결과는 다음과 같다.



그림 19. 폭포: 깨진 그림
A blocky waterfall

위 그림이 폭포인지 분간이 가지 않는다.




위로


결론

이 글에서 ImageMagick 툴을 살펴보았다. 이 글에서 설명한 툴이 모든 문제에 대한 답을 줄 수는 없다. 커스텀 코드를 작성할 필요도 있다. 하지만 일반적인 명령행 이미지 조작 툴은 많은 도움이 된다.




위로


참고자료




위로


필자소개

Michael Still

Michael Still: 소프트웨어 엔지니어, Tower Software 

댓글