WX340K/341K用の.kicoファイルをImager::AnimeFaceで作る。

WX340K/341K用の.kicoファイルをImager::AnimeFaceで作る。

 Imager::AnimeFaceはWX340K用の.kicoファイルを作るのに便利そうだなー、と思っていたのですが。前に書いたように自宅のマシンではmakeできんので放置してたけど、だらっと書いてみた。

WX340K/Kico/AnimeFace.pm

package WX340K::Kico::AnimeFace;
use strict;
use warnings;

use Imager;
use Imager::AnimeFace;

my %KICO = (
  width => 76,
  height => 62,
);
$KICO{ratio} = $KICO{width} / $KICO{height};

my $im = Imager->new();

sub new {
  my $class = shift;
  my $self = bless {
    dst_dir => 'dst',
    expire_width => ($KICO{width} - 20),
    @_,
  }, $class;
}

sub conv {
  my $self = shift;
  my $src_file = shift;
  my $dst_file = shift;
  ($dst_file) = $src_file =~ m/((?:\w+[.])*\w+)[.]\w+\z/xms unless $dst_file;

  my $dst_dir = $self->{dst_dir};

  $im->read( file => $src_file ) or return;
  my $res_list = detect_animeface($im) or return;
  return unless @$res_list;


  my $count = 1;
  foreach my $res (@$res_list) {
    my $face = $res->{face};

    my $face_ratio = $face->{width} / $face->{height};
    if ($face_ratio < $KICO{ratio}) {
      my $new_width = $face->{height} * $KICO{ratio};
      my $diff = int( ($new_width - $face->{width}) / 2 );

      $face->{width} = int($new_width);
      $face->{x} -= $diff;
      $face->{x} = 0 if $face->{x} < 0;
    }
    else {
      my $new_height = $face->{height} / $KICO{ratio};
      my $diff = int( ($new_height - $face->{height}) / 2 );

      $face->{height} = int($new_height);
      $face->{y} -= $diff;
      $face->{y} = 0 if $face->{y} < 0;
    }

    next if $face->{width} < $self->{expire_width};
    if ($face->{width} < $KICO{width}) {
        $face->{x} -= int(($KICO{width} - $face->{width}) / 2);
        $face->{x} = 0 if $face->{x} < 0;
        $face->{width} = $KICO{width};

        $face->{y} -= int(($KICO{height} - $face->{height}) / 2);
        $face->{y} = 0 if $face->{y} < 0;
        $face->{height} = $KICO{height};
    }

    my $kico = $im->crop(
      left => $face->{x},
      top  => $face->{y},
      width  => $face->{width},
      height => $face->{height},
    );
    my $kico_filename = "$dst_file.$count";

    $kico->scale(
      xpixels => $KICO{width},
      ypixels => $KICO{height},
      type  => 'nonprop',
      qtype => 'mixing',
    )
    ->write(
      file => "$dst_dir/$kico_filename.kico", 
      type => 'jpeg',
      jpegquality => 90,
    );

    $count++;
  }
}


1;

 

 使う時はこんな感じで。

#!/usr/bin/perl
use strict;
use warnings;

my $src_dir = shift || 'src';
my $dst_dir = shift || 'dst';

use WX340K::Kico::AnimeFace;
my $kico = WX340K::Kico::AnimeFace->new(
  src_dir => $src_dir,
  dst_dir => $dst_dir,
);

foreach my $filename (<$src_dir/*>) {
  warn "$filename\n";
  $kico->conv($filename);
}

 src/ディレクトリにある画像の顔の部分を切り出して dst/ディレクトリに書き出す感じ。

 icon用だからImagerで変換する時にコントラストをやや強調したほうがいいかも?とか思いつつ。