Markdown-Pod

 view release on metacpan or  search on metacpan

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

    #!perl
    use Win32::Clipboard;
    my $bitmap = Win32::Clipboard::GetBitmap;

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

클립보드에 저장된 비트맵을 불러오는 것이므로 클립보드에 있는 것이
이미지인지 텍스트인지 확인할 필요도 없을 것 같습니다.
C<$bitmap> 스칼라 변수에 비트맵 이미지가 고스란히 저장되기 때문에
C<.bmp> 파일에 써주기만 하면 파일 저장도 끝납니다.
파일명을 일일이 사용자에게 물어보는 것도 번거로운 일이니까
현재 날짜과 시간을 사용해서 자동으로 저장하도록 하겠습니다.
C<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;
        },
        ...
    );

I<그림 2.> 화면 갈무리 결과 L<(원본)|2011-12-07-2.png>
=for html <img src="2011-12-07-2.png" alt="화면 갈무리 결과" width="700" />


=head2 용량 줄이기

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

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

이 문제를 해결하는 가장 간단한 방법은 BMP를 PNG로 변환해주는 가벼운 유틸리티를
구해서 BMP 파일을 생성한 다음 바로 실행시켜 변환시키는 것입니다.
L<PNG 라이브러리 공식 홈페이지|http://www.libpng.org/pub/png/pngcode.html>에는 변환툴로서 가벼운
L<bmp2png|http://cetus.sakura.ne.jp/softlab/b2p-home/>를 소개하고 있습니다.
bmp2png는 단 하나의 실행파일로 구성되어 있으며 윈도우즈 명령줄에서
인자로 BMP 파일을 넘기면 확장자만 바꿔서 PNG 파일을 생성해줍니다.
bmp2png를 다운로드 받아서 압축을 푼 다음에 C<BMP2PNG.EXE> 파일을 스크립트가
있는 경로에 두거나 또는 C<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;
        },
        ...
    );

I<그림 2.> PNG로 변환한 캡처 화면 L<(원본)|2011-12-07-3.png>
=for html <img src="2011-12-07-3.png" alt="PNG로 변환한 캡처 화면" width="700" />


=head2 보기 싫은 콘솔 창을 없애자

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

스크립트에는 다음 코드를 추가합니다.



( run in 2.296 seconds using v1.01-cache-2.11-cpan-99c4e6809bf )