GDで角丸サムネール画像の生成

公開・表示したい画像がいっぱいあるとき、サムネール画像を作るのは非常に手間です。
いちいち一つ一つ画像編集する人は・・・まぁ、いないでしょうね・・・(^^;

以前に、CGIでも使えるようにGDを使用してサムネール画像生成のPerlモジュールを作成していました。

で、今回、そのサムネール画像に角丸を適用したものを生成できるように、機能を付け足すことにしたんですが・・・、
画像に角丸を適用するスマートな方法がわからず、考えたあげく、少々チカラワザ的にインプリメントしてしまいました。

四隅のピクセル値をスキャンして、円弧外のピクセル値は背景色に、円弧内のピクセル値はそのままに・・・という感じです。

ピクセル値の判定には、円の方程式、X2 + Y2 = Radius2 を使用しています。

#
# perl script
#
# $this は、GD::Image 、$radiusは円弧の半径ピクセル
sub applyRoundCorner
{
  my ($this,$radius,$color) = @_;
  my ($x,$y) = (0,0);
  my ($width,$height) = ($this->width-1,$this->height-1);
  $this->alphaBlending(1);
  my ($lhs,$rhs) = (0,$radius**2);

  #上
  for($y = 0;$y <= $radius;$y++)
    {
      #左
      for($x = 0;$x <= $radius;$x++)
        {
          $lhs = ($x - $radius)**2 + ($y - $radius)**2;
          last unless(setPixel($this,$radius,$x,$y,$color,$lhs,$rhs));
        }
      #右
      for($x = $width;$x >= $width - $radius;$x--)
        {
          $lhs = ($x - ($width - $radius))**2 + ($y - $radius)**2;
          last unless(setPixel($this,$radius,$x,$y,$color,$lhs,$rhs));
        }
    }

  #下
  for($y = $height;$y >= $height-$radius;$y--)
    {
      #左
      for($x = 0;$x <= $radius;$x++)
        {
          $lhs = ($x - $radius)**2 + ($y - ($height - $radius))**2;
          last unless(setPixel($this,$radius,$x,$y,$color,$lhs,$rhs));
        }
      #右
      for($x = $width;$x >= $width - $radius;$x--)
        {
          $lhs = ($x - ($width - $radius))**2 + ($y - ($height - $radius))**2;
          last unless(setPixel($this,$radius,$x,$y,$color,$lhs,$rhs));
        }
    }
}

#
# ピクセル(x,y)にカラー値をセットする。
#
sub setPixel
{
  my ($this,$radius,$x,$y,$color,$lhs,$rhs) = @_;
  my $ret = 1;
 
  if($lhs > $rhs)
    {
      $this->setPixel($x,$y,$color);
    }
  else
    {
      $ret = 0;
    }

  return $ret;
}

ただ、サムネール画像にこれをそのまま適用すると、当然ですがアンチエリアス処理がされないので角丸部分がガタガタになってしまいます。
そこで、サムネール画像に角丸を適用するのではなく、メモリ上の元画像に角丸を適用し、GD::ImageのcopyResampledでサムネール画像を生成(縮小)することでアンチエリアス処理の替わりとすることにしました。

他の方法としては、角丸部分をアルファ付きのPNGファイルを用いて、四隅にコピーするという方法があって、そっちの方が簡単かな? とは思うのですが・・・

根本的に改善するには、やはり画像処理のアルゴリズム(主にアンチエリアス処理なんですが・・・)について勉強しなければいけませんねぇ・・・。

他の方が作ったライブラリを探した方がいいかも・・・(^^;;;