ジュリア集合のアンチエイリアシングについて

いろいろ試した結果、重みを付けずに平均をとることにした。

昨日の結果を見てたんだけど、Chromeで昨日のページを眺めてて、
縮小された画像が良い感じだったので、それに近くなるように変更してみた。

結果的に、こんな感じ。(一部抜粋)

use v5.14;
use strict;
use warnings;

use Imager;
use List::Util qw/max sum/;
use Time::HiRes qw/time/;
use Getopt::Long qw/:config posix_default no_ignore_case bundling auto_help/;

use Inline C => Config => LIBS => '-lm' => OPTIMIZE => '-O';
use Inline C => q{
    #include <stdio.h>
    #include <math.h>

    static IV fLoopLimit = 1000;
    static NV fP0_r = 0.0; // 実部(x方向)
    static NV fP0_i = 0.0; // 虚部(y方向)
    static NV fP1_r = 0.5;
    static NV fP1_i = 0.5;

    void set_loop_limit(IV limit)
    {
        fLoopLimit = limit;
    }

    void set_render_area(NV p0_r, NV p0_i, NV p1_r, NV p1_i)
    {
        fP0_r = p0_r;
        fP0_i = p0_i;
        fP1_r = p1_r;
        fP1_i = p1_i;
    }

    IV calculate(NV z_r, NV z_i, NV a_r, NV a_i)
    {
        IV i = 0;
        for (; i<fLoopLimit; i++) {
            const NV z2_r = (z_r * z_r) - (z_i * z_i) + a_r;
            const NV z2_i = (2.0 * z_r * z_i) + a_i;

            if ( 4.0 < ((z2_r * z2_r) + (z2_i * z2_i)) ) {
                break;
            }

            z_r = z2_r, z_i = z2_i;
        }

        return i;
    }

    SV * generate(IV w, IV h, NV a_r, NV a_i)
    {
        const NV d_r = ( fP1_r - fP0_r ) / w;
        const NV d_i = ( fP1_i - fP0_i ) / h;
        const NV dd_r = d_r / 3.0;
        const NV dd_i = d_i / 3.0;
        const NV dd2_r = dd_r / sqrt(2.0);
        const NV dd2_i = dd_i / sqrt(2.0);

        IV *dst = NULL;
        Newx( dst, (w * h), IV );

        printf( "progress: %4d/%4d", 0, h );
        fflush( stdout );

        for (IV iy=0; iy<h; iy++) {
            IV *p = dst + (w * iy);
            for (IV ix=0; ix<h; ix++) {
                const NV z_r = (ix * d_r) + fP0_r;
                const NV z_i = (iy * d_i) + fP0_i;

                IV wk = calculate( z_r, z_i, a_r, a_i );
                wk += calculate( z_r + dd_r, z_i, a_r, a_i );
                wk += calculate( z_r - dd_r, z_i, a_r, a_i );
                wk += calculate( z_r, z_i + dd_i, a_r, a_i );
                wk += calculate( z_r, z_i - dd_i, a_r, a_i );                
                wk += calculate( z_r + dd2_r, z_i + dd2_i, a_r, a_i );
                wk += calculate( z_r + dd2_r, z_i - dd2_i, a_r, a_i );
                wk += calculate( z_r - dd2_r, z_i + dd2_i, a_r, a_i );
                wk += calculate( z_r - dd2_r, z_i - dd2_i, a_r, a_i );

                p[ix] = wk;
            }

            printf( "\rprogress: %4d/%4d", iy + 1, h );
            fflush( stdout );
        }

        printf( " -> calclated!\n" );

        SV *ret = newAV();
        av_fill( ret, (w * h) - 1 );
        SV **base = AvARRAY( ret );
        for (IV iy=0; iy<h; iy++) {
            const IV *p = dst + (w * iy);
            for (IV ix=0; ix<w; ix++) {
                (*base++) = newSViv( p[ix] );
            }
        }

        Safefree( dst );
        return newRV_noinc( (SV *)ret );
    }
};

# 以下、前回と同じ

Inline::Cに書いたgenerate()で重み付けするのをやめただけ。

1画素を決定するのに、周囲8箇所を加えて計9回計算するくらいなら、
幅・高さを倍にしてリサンプリングした方が良いのでは?って思ってて、
次は、その辺を試そうと思う。
ほんとは、パレットのバリエーションを増やすべく、
この辺についていろいろやる予定だったんだけど・・・。

というわけで、本日の1枚。

$ perl aaa.pl --param="0.34,-0.422" --dst="test"
20160823-1

おしまい。

Leave a Comment