記事一覧はこちら

SI Captchaのイメージ改造

バージョンは2.7.5。

キャプチャの難易度を高いにしてもすり抜けるので色々いじくってみました。 いじくった場所はランダムに入る線の数と色。出来た結果はこんな感じ。

$img->perturbation = 0.7; // 文字のぐにゃ度。1.0にすると画像領域からはみ出るからやりすぎ注意
$img->num_lines = 50;//線の数。増やして損なし?
$img->text_transparency_percentage=00;//文字の透明度。0でいいや
$img->use_transparent_text=true;//文字を透明にするか。0ならfalseでもいいや
$img->draw_lines_over_text=true;//文字を線の上に表示するか、線を文字の上に表示するか。

線の色の処理。デフォルトでは最初に色を決めてその色をn本描いているけど、一本一本違う色にする。 線の透明度がゼロで線の本数を増やすと本当に文字が読めなくなっていたけど、色に透明度を指定出来るようにして本数が増えても読めるようにする。 色をHSLにして輝度を調節する。カラフルな方がいいかなと。

    //RBGtoHSL、HuetoRGB、HSLtoRGBはphp公式の http://www.php.net/manual/ja/ref.image.php#79996 より
    function RBGtoHSL( $R, $G, $B ){
        $var_R = ( $R / 255 );
        $var_G = ( $G / 255 );
        $var_B = ( $B / 255 );
        $var_Min = min( $var_R, $var_G, $var_B );
        $var_Max = max( $var_R, $var_G, $var_B );
        $del_Max = $var_Max - $var_Min;
        $L = ( $var_Max + $var_Min ) / 2;
        if ( $del_Max == 0 )    {
           $H = 0;
           $S = 0;
        }    else    {
            if ( $L < 0.5 )        {
                $S = $del_Max / ( $var_Max + $var_Min );
            }        else        {
                $S = $del_Max / ( 2 - $var_Max - $var_Min );
            }
            $del_R = ( ( ( $var_Max - $var_R ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
            $del_G = ( ( ( $var_Max - $var_G ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
            $del_B = ( ( ( $var_Max - $var_B ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
            if ( $var_R == $var_Max ){
                $H = $del_B - $del_G;
            } else if ( $var_G == $var_Max ){
                $H = ( 1 / 3 ) + $del_R - $del_B;
            }else if ( $var_B == $var_Max ){
                $H = ( 2 / 3 ) + $del_G - $del_R;
            }
            if ( $H < 0 ){
                $H += 1;
            }
            if ( $H > 1 ){
                $H -= 1;
            }
        }
        return array( $H, $S, $L );
    }
    function HuetoRGB( $v1, $v2, $vH )  {
        if ( $vH < 0 )       {
            $vH += 1;
        }
        if ( $vH > 1 )       {
            $vH -= 1;
        }
        if ( ( 6 * $vH ) < 1 )       {
            return ( $v1 + ( $v2 - $v1 ) * 6 * $vH );
        }
        if ( ( 2 * $vH ) < 1 )       {
            return ( $v2 );
        }
        if ( ( 3 * $vH ) < 2 )       {
            return ( $v1 + ( $v2 - $v1 ) * ( ( 2 / 3 ) - $vH ) * 6 );
        }
        return ( $v1 );
    }
    function HSLtoRGB( $H, $S, $L ){
        if ( $S == 0 )    {
            $R = $L * 255;
            $G = $L * 255;
            $B = $L * 255;
        }    else    {
            if ( $L < 0.5 )        {
                $var_2 = $L * ( 1 + $S );
            }        else        {
                $var_2 = ( $L + $S ) - ( $S * $L );
            }
            $var_1 = 2 * $L - $var_2;
            $R = 255 * $this->HuetoRGB( $var_1, $var_2, $H + ( 1 / 3 ) );
            $G = 255 * $this->HuetoRGB( $var_1, $var_2, $H );
            $B = 255 * $this->HuetoRGB( $var_1, $var_2, $H - ( 1 / 3 ) );
        }
        return array( $R, $G, $B );
    }
    /**
     * Draw random curvy lines over the image<br />
     * Modified code from HKCaptcha
     *
     * @since 2.0
     * @access private
     *
     */
    function drawLines(){
        for ($line = 0; $line < $this->num_lines; ++$line) {
            //元々の $this->line_color は一色しか入ってないから、テキスト用の色配列を使う
            shuffle($this->multi_text_color);
            $nowColor=$this->multi_text_color[0];
            $nowColor=$this->RBGtoHSL($nowColor[0],$nowColor[1],$nowColor[2]);
            $nowColor[2]=0.5;
            $nowColor=$this->HSLtoRGB($nowColor[0],$nowColor[1],$nowColor[2]);
            $linecolor = imagecolorallocatealpha($this->im,$nowColor[0],$nowColor[1],$nowColor[2],126);
            //追加ここまで
            $x = $this->image_width * (1 + $line) / ($this->num_lines + 1);
            $x += (0.5 - $this->frand()) * $this->image_width / $this->num_lines;
            $y = rand($this->image_height * 0.1, $this->image_height * 0.9);

            $theta = ($this->frand()-0.5) * M_PI * 0.7;
            $w = $this->image_width;
            $len = rand($w * 0.4, $w * 0.7);
            $lwid = rand(0, 15);//おまけで線を太めにする。

            $k = $this->frand() * 0.6 + 0.2;
            $k = $k * $k * 0.5;
            $phi = $this->frand() * 6.28;
            $step = 0.5;
            $dx = $step * cos($theta);
            $dy = $step * sin($theta);
            $n = $len / $step;
            $amp = 1.5 * $this->frand() / ($k + 5.0 / $len);
            $x0 = $x - 0.5 * $len * cos($theta);
            $y0 = $y - 0.5 * $len * sin($theta);

            $ldx = round(-$dy * $lwid);
            $ldy = round($dx * $lwid);

            for ($i = 0; $i < $n; ++$i) {
                $x = $x0 + $i * $dx + $amp * $dy * sin($k * $i * $step + $phi);
                $y = $y0 + $i * $dy - $amp * $dx * sin($k * $i * $step + $phi);
                imagefilledrectangle($this->im, $x, $y, $x + $lwid, $y + $lwid, $linecolor);
            }
        }
    }

drawLinesの下にdrawWordという面白そうな関数があるのが気になる。 これでも止まらなかったら日本語追加、答え合わせ部分に手を加えて1+1等の計算をさせる とか色々ネタがあります。