Markdown-Pod

 view release on metacpan or  search on metacpan

t/mkd/2011-12-07.mkd  view on Meta::CPAN

    use Win32::Clipboard;
    my $bitmap = Win32::Clipboard::GetBitmap;

정말 끝내주지 않나요? :-D

클립보드에 저장된 비트맵을 불러오는 것이므로 클립보드에 있는 것이
이미지인지 텍스트인지 확인할 필요도 없을 것 같습니다.
`$bitmap` 스칼라 변수에 비트맵 이미지가 고스란히 저장되기 때문에
`.bmp` 파일에 써주기만 하면 파일 저장도 끝납니다.
파일명을 일일이 사용자에게 물어보는 것도 번거로운 일이니까
현재 날짜과 시간을 사용해서 자동으로 저장하도록 하겠습니다.
`onClick` 이벤트에 대한 함수 레퍼런스는 이렇게 바뀝니다.

    #!perl
    ...
    
    use Win32::GUI ();
    use Win32::GuiTest qw(SendKeys);
    use Win32::Clipboard;
    use DateTime;
    use File::Slurp
    
    ...
    
    $main->AddNotifyIcon(
        -name    => "NI",
        -icon    => $icon,
        -tip     => "Click to Screenshot!",
        -balloon => 0,
        -onClick => sub {
            # 스크린샷을 찍습니다.
            SendKeys( "+{PRTSCR}" );
    
            # 스크린샷을 저장합니다.
            my $dt       = DateTime->now( time_zone => 'Asia/Seoul' );
            my $filename = sprintf('%s %s.bmp', $dt->ymd, $dt->hms);
            my $bitmap   = Win32::Clipboard::GetBitmap;
    
            write_file( $filename, {binmode => ':raw'}, $bitmap ) ;
    
            return 0;
        },
        ...
    );

*그림 2.* 화면 갈무리 결과 [(원본)][img-02-original]
![화면 갈무리 결과][img-02]


용량 줄이기
------------

일단 프로그램 작성은 끝났습니다.
다만 실행해보면 갈무리되는 파일의 크기가 무척 크다는 것을 알 수 있습니다.
비트맵 형식은 압축을 하지 않기 때문에 일반적인 HD 해상도의 파일은 약 3MB,
그리고 그 이상의 해상도의 화면을 사용한다면 5MB는 가볍게 훌쩍 넘깁니다.
본격적으로 대량 캡쳐를 하려고 생각했는데, 이러면 좀 곤란하겠죠.
BMP 대신 PNG 파일 포맷을 사용해서 용량 문제를 해결하도록 하겠습니다.

BMP를 PNG로 변환하는 방법은 다양합니다.
CPAN의 [GD 모듈][cpan-gd], [Image::Magick][cpan-image-magick],
[Imager][cpan-imager]는 물론이고 `Win32::GUI` 모듈에 딸려 나오는
[Win32::GUI::DIBitmap][cpan-win32-gui-dbbitmap] 모듈을 사용하는 등
여러가지 방법이 있습니다.
다만 각각의 모듈은 모두 윈도우즈에 소소한 문제들이 있습니다.
`GD` 모듈의 경우 BMP 포맷을 지원하지 않으며,
`Image::Magick`는 따로 바이너리 라이브러리를 설치한 후 CPAN 모듈을
설치해야 하므로 초보자의 경우 접근이 어렵습니다.
또한 `Imager`는 BMP를 지원하지면 결정적으로 윈도우즈에서
캡쳐할때 생성되는 BMP 형식(만)을 지원하지 않습니다.
마지막으로 `Win32::GUI::DIBitmap` 모듈의 경우 ActivePerl의 경우 문제없이
사용이 가능하나 딸기펄 사용자의 경우 컴파일러 호환 문제로 설치되지 않아
사용할 수가 없습니다.

이 문제를 해결하는 가장 간단한 방법은 BMP를 PNG로 변환해주는 가벼운 유틸리티를
구해서 BMP 파일을 생성한 다음 바로 실행시켜 변환시키는 것입니다.
[PNG 라이브러리 공식 홈페이지][home-png]에는 변환툴로서 가벼운
[bmp2png][home-bmp2png]를 소개하고 있습니다.
bmp2png는 단 하나의 실행파일로 구성되어 있으며 윈도우즈 명령줄에서
인자로 BMP 파일을 넘기면 확장자만 바꿔서 PNG 파일을 생성해줍니다.
bmp2png를 다운로드 받아서 압축을 푼 다음에 `BMP2PNG.EXE` 파일을 스크립트가
있는 경로에 두거나 또는 `PATH` 환경변수로 관리되고 있는 디렉터리에 두세요.

새롭게 갱신한 코드 조각은 다음과 같을 것입니다.

    #!perl
    $main->AddNotifyIcon(
        ...
        -onClick => sub {
            # 스크린샷을 찍습니다.
            SendKeys( "+{PRTSCR}" );
    
            # 스크린샷을 저장합니다.
            my $dt       = DateTime->now( time_zone => 'Asia/Seoul' );
            my $bitmap   = Win32::Clipboard::GetBitmap;
            my $filename = sprintf(
                '%4d%02d%02d-%02d%02d%02d.bmp',
                $dt->year, $dt->month,  $dt->day,
                $dt->hour, $dt->minute, $dt->second,
            );
            write_file($filename, { binmode => ':raw' }, $bitmap);
    
            # BMP 형식을 PNG로 변환합니다.
            system('BMP2PNG.EXE', $filename);
            unlink($filename);
    
            return 0;
        },
        ...
    );

*그림 2.* PNG로 변환한 캡처 화면 [(원본)][img-03-original]
![PNG로 변환한 캡처 화면][img-03]


보기 싫은 콘솔 창을 없애자
---------------------------

윈도우즈 환경에서 Perl 스크립트를 실행하면 기본적으로
항상 나타나는 까만 콘솔 창은 아무래도 좀 부담스럽습니다.
이제 이 콘솔 창을 없애 봅시다.
[CPAN의 PAR::Packer 모듈][cpan-par-packer]을 사용하면
실행 바이너리를 만드는 시점에 옵션을 이용해 콘솔 창을 보이지 않게 할 수 있습니다.
`PAR::Packer`를 이용해서 바이너리로 만들지 않더라도
콘솔 창을 없애려면 [CPAN의 Win32::HideConsole 모듈][cpan-win32-hideconsole]을
이용([CPAN의 Win32::Console 모듈][cpan-win32-console]도 한번 확인해보세요) 합니다.

t/mkd/2011-12-07.mkd  view on Meta::CPAN

    $main->Hide;
    
    # GUI 메인 루프에 진입합니다.
    Win32::GUI::Dialog;



정리하며
---------

글쓴이 소개란을 읽으셨을지 모르겠지만, 전 전산/컴퓨터와는 전혀 관계 없는 법학 전공자거든요. (^^)
MS 윈도우 환경에서 약간의 Perl 지식만 있다면 Perl을 이용해 자신이 필요한 기능을
자신이 직접 설계해서 사용할 수 있다는 사실은 정말 매력적입니다.
모듈을 사용한 것은 온전한 제 지식이 아니라구요?
뭐 그럼 어떤가요? 어쨌든 만들고 싶었던 것을 만들어냈잖아요!
이미 다른 사람들이 만들어 놓은 수많은 CPAN 모듈들을 활용하면,
혼자 힘으로는 역부족이라고 생각했던 부분은 해낼 수 있게,
가능한 부분은 더욱 빠른 시간내에 구현할 수 있게 도와줍니다.
어떤가요? 매력적이지 않나요?
이미 Perl을 훌륭하게 사용하고 계신 많은 분들이 있지만,
저처럼 전산 전공이 아닌, 일반적 지식만을 갖춘 *잠재적 Perl 이용자*께 이 글을 바칩니다.
화이팅! ;-)


생각해볼 거리
--------------

지금 프로그램은 파일을 저장하는 경로가 정해져있습니다.
실행하는 시점에 인자로 넘긴다던가, 또는 설정파일을 참고하도록 수정할 수도 있겠지요.
또한 트레이 아이콘에서 오른쪽 버튼을 눌렀을때 바로 종료가 되는 것이 아니라
팝업 메뉴를 띄운 후 설정을 변경하거나 종료하는 옵션을 추가할 수도 있을 것입니다.
나머지는 여러분의 상상력에 맡기겠습니다.

마지막으로 이 프로그램에 단축키 기능을 추가한다면 어떨까요?
이를테면 윈도우 환경 어디서나 CTRL-F12 를 클릭하면 이 기능이 동작하도록 하는 것입니다.
윈도우용 Perl은 [Win32::API][cpan-win32-api] 모듈을 이용해 윈도우 기본 API를 직접 사용할 수 있기 때문에,
`user32.dll`의 `RegisterHotKey/UnregisterHotKey`를 임포트해 적당한 키 조합을 등록하고
키보드 입력을 전역으로 모니터링(후킹)하면, 단축키를 이용한 스크린샷의 조작이 가능합니다.
단축키 방식을 도입할 경우 지금까지 사용한 전체 화면 스크린캡쳐 외에도,
`Alt + PrtSc`를 사용해 현재 활성화 된 창만을 갈무리 할 수 있습니다.
지금처럼 아이콘을 클릭하는 방식이라면 아이콘을 클릭하는 순간 활성창이
작업표시줄로 바뀌기 때문에, 항상 작업 표시줄만 갈무리 될 것입니다.
기사에서 사용한 모든 화면은 단축키까지 구현한 완전한 스크립트를 이용해서 갈무리한 것입니다.
`PAR::Packer`로 빌드한 [실행 바이너리와 전체 소스][capture-source]도
꼭 다운로드 받아서 확인해보세요. ;-)



[img-01]:                   2011-12-07-1.png width=700
[img-02]:                   2011-12-07-2.png width=700
[img-03]:                   2011-12-07-3.png width=700

[img-01-original]:          2011-12-07-1.png
[img-02-original]:          2011-12-07-2.png
[img-03-original]:          2011-12-07-3.png

[activeperl]:               http://www.activestate.com/activeperl
[blog-owl0908]:             http://www.dormouse.pe.kr
[capture-source]:           http://www.nightowl.pe.kr/software/prtscrsave
[cpan-gd]:                  https://metacpan.org/module/GD
[cpan-image-magick]:        https://metacpan.org/module/Image::Magick
[cpan-imager]:              https://metacpan.org/module/Imager
[cpan-par-packer]:          https://metacpan.org/module/Par::Packer
[cpan-win32-api]:           https://metacpan.org/module/Win32::API
[cpan-win32-clipboard]:     https://metacpan.org/module/Win32::Clipboard
[cpan-win32-console]:       https://metacpan.org/module/Win32::Console
[cpan-datetime]:            https://metacpan.org/module/DateTime
[cpan-file-slurp]:          https://metacpan.org/module/File::Slurp
[cpan-win32-gui-dibitmap]:  https://metacpan.org/module/Win32::GUI::DIBitmap
[cpan-win32-gui]:           https://metacpan.org/module/Win32::GUI
[cpan-win32-guitest]:       https://metacpan.org/module/Win32::GuiTest
[cpan-win32-hideconsole]:   https://metacpan.org/module/Win32::HideConsole
[home-bmp2png]:             http://cetus.sakura.ne.jp/softlab/b2p-home/
[home-png]:                 http://www.libpng.org/pub/png/pngcode.html
[strawberry-perl-514]:      http://strawberryperl.com/beta/index.html
[strawberry-perl]:          http://strawberryperl.com



( run in 2.006 seconds using v1.01-cache-2.11-cpan-0d23b851a93 )