ます’s Blog - どうでもいい記事100選

どうでもいい記事100選

二値化

Xに代入している値は0や255になっていますが、条件分岐のところで表現したいrr・gg・bb値を代入する事で様々な色に変更できます。

  private Bitmap effectBinarization( Bitmap bitmap ){

    if( bitmap == null ){
      bitmap = BitmapFactory.decodeResource( getResources( ), R.drawable.original ).copy( Bitmap.Config.ARGB_8888, true );
    }

    if( bitmap == null ){
      return bitmap;
    }

    if( bitmap.isMutable( ) != true ){
      bitmap = bitmap.copy( Bitmap.Config.ARGB_8888, true );
    }

    int height   = bitmap.getHeight( );
    int width    = bitmap.getWidth( );
    int[] pixels = new int[( width * height )];
    bitmap.getPixels( pixels, 0, width, 0, 0, width, height );

    for( int YY = 0; YY < width; ++YY ){
      for( int XX = 0; XX < height; ++XX ){

        int bitmapColor = pixels[( YY + XX * width )];

        int rr = Color.red( bitmapColor );
        int gg = Color.green( bitmapColor );
        int bb = Color.blue( bitmapColor );

        int X, Y;
        Y = ( rr + gg + bb ) / 3;

        if( Y < 128 ){
          X = 0;
        } else {
          X = 255;
        }

        rr = X;
        gg = X;
        bb = X;

        pixels[( YY + XX * width )] = Color.rgb( rr, gg, bb );
      }
    }

    bitmap.setPixels( pixels, 0, width, 0, 0, width, height );

    return bitmap;
  }

オリジナル:
f:id:masugata:20110405125239:image:medium
二値化(白と黒):
f:id:masugata:20110331140844:image:medium
二値化(黄と黒):
f:id:masugata:20110331140834:image:medium
二値化(緑と黒):
f:id:masugata:20110331140806:image:medium
二値化(青と黒):
f:id:masugata:20110331140823:image:medium
二値化(紫と黒):
f:id:masugata:20110331140828:image:medium
二値化(ピンクと黒):
f:id:masugata:20110331140839:image:medium
二値化(白と青):
f:id:masugata:20110331151809:image:medium

トイカメラ風

あくまでも「風」です。_| ̄|○
軽く調べてみた感じでは明るさを落としてコントラストを強めに調整。でもってボカシを入れて四隅を黒くする。。。で合ってるのかな?

  // トイカメラ風
  private Bitmap effectToyCamera( Bitmap bitmap ){

    if( bitmap == null ){
      bitmap = BitmapFactory.decodeResource( getResources( ), R.drawable.original ).copy( Bitmap.Config.ARGB_8888, true );
    }

    if( bitmap == null ){
      return bitmap;
    }

    if( bitmap.isMutable( ) != true ){
      bitmap = bitmap.copy( Bitmap.Config.ARGB_8888, true );
    }

    int height   = bitmap.getHeight( );
    int width    = bitmap.getWidth( );
    int[] pixels = new int[( width * height )];
    bitmap.getPixels( pixels, 0, width, 0, 0, width, height );

    for( int YY = 0; YY < width; ++YY ){
      for( int XX = 0; XX < height; ++XX ){

        int bitmapColor = pixels[( YY + XX * width )];

        int rr = Color.red( bitmapColor );
        int gg = Color.green( bitmapColor );
        int bb = Color.blue( bitmapColor );

        // hsv[0] is Hue [0.0f .. 360.0f]
        // hsv[1] is Saturation [0.0f...1.0f]
        // hsv[2] is Value [0.0f...1.0.0f]
        float[] hsv = new float[3];
        Color.RGBToHSV( rr, gg, bb, hsv );

        hsv[1] *= 1.5f;
        hsv[2] -= 0.1f;

        if( 1 < hsv[1] ){
          hsv[1] = 1.0f;
        } else if( hsv[1] < 0 ){
          hsv[1] = 0.0f;
        }

        if( 1 < hsv[2] ){
          hsv[2] = 1.0f;
        } else if ( hsv[2] < 0 ){
          hsv[2] = 0.0f;
        }

        pixels[( YY + XX * width )] = Color.HSVToColor( hsv );
      }
    }

    bitmap.setPixels( pixels, 0, width, 0, 0, width, height );

    bitmap = effectShadeing( bitmap, 170 );
    bitmap = mergeBitmap( bitmap, BitmapFactory.decodeResource( getResources( ), R.drawable.moyamoya ).copy( Bitmap.Config.ARGB_8888, true ) );

    return bitmap;
  }

  // ぼかし
  private Bitmap effectShadeing( Bitmap bitmap, int range ){

    if( bitmap == null ){
      bitmap = BitmapFactory.decodeResource( getResources( ), R.drawable.original ).copy( Bitmap.Config.ARGB_8888, true );
    }

    if( bitmap == null ){
      return bitmap;
    }

    if( bitmap.isMutable( ) != true ){
      bitmap = bitmap.copy( Bitmap.Config.ARGB_8888, true );
    }

    int height   = bitmap.getHeight( );
    int width    = bitmap.getWidth( );
    int[] pixels = new int[( width * height )];
    bitmap.getPixels( pixels, 0, width, 0, 0, width, height );

    int i, j, ii, jj;
    int pixel = 3;

    for( i = 0; i < width; ++i ){
      for( j = 0; j < height; ++j ){

        int r, g, b;
        float sumR, sumG, sumB;
        sumR = 0.0f;
        sumG = 0.0f;
        sumB = 0.0f;

        for( ii = -pixel; ii <= pixel; ii++ ){
          for( jj = -pixel; jj <= pixel; jj++ ){

            if( i + ii < 0 || width <= i + ii || j + jj < 0 || height <= j + jj ){
              continue;
            }

            int bitmapColor = pixels[( ( i + ii ) + ( j + jj ) * width )];

            r = Color.red( bitmapColor );
            g = Color.green( bitmapColor );
            b = Color.blue( bitmapColor );

            sumR += (float)r;
            sumG += (float)g;
            sumB += (float)b;
          }
        }

        int rr, gg, bb;
        rr = (int)( sumR / Math.pow( ( 1 + ( 2 * pixel ) ), 2 ) );
        gg = (int)( sumG / Math.pow( ( 1 + ( 2 * pixel ) ), 2 ) );
        bb = (int)( sumB / Math.pow( ( 1 + ( 2 * pixel ) ), 2 ) );
        
        if( range <= 0 ||
            !( i < ( ( width  / 2 ) + range ) && ( ( width  / 2 ) - range ) < i &&
               j < ( ( height / 2 ) + range ) && ( ( height / 2 ) - range ) < j ) ){
          pixels[( i + j * width )] = Color.rgb( rr, gg, bb );
        }
      }
    }

    bitmap.setPixels( pixels, 0, width, 0, 0, width, height );

    return bitmap;
  }

  // 画像を合成
  private Bitmap mergeBitmap( Bitmap bitmap1, Bitmap bitmap2 ){

    if( bitmap1 == null ){
      return null;
    }

    if( bitmap2 == null ){
      return bitmap1;
    }

    int height1 = bitmap1.getHeight( );
    int width1  = bitmap1.getWidth( );

    int height2 = bitmap2.getHeight( );
    int width2  = bitmap2.getWidth( );

    float scaleWidth  = ( (float)width1 )  / width2;
    float scaleHeight = ( (float)height1 ) / height2;
    Matrix matrix     = new Matrix( );
    matrix.postScale( scaleWidth, scaleHeight );
    Bitmap mergeBitmap = Bitmap.createBitmap( bitmap2, 0, 0, width2, height2, matrix, true );


    Bitmap newBitmap   = Bitmap.createBitmap( width1, height1, Bitmap.Config.ARGB_8888 );
    Canvas canvas      = new Canvas( newBitmap );
    canvas.drawBitmap( bitmap1,     0.0f, 0.0f, null );
    canvas.drawBitmap( mergeBitmap, 0.0f, 0.0f, null );

    return newBitmap;
  }

オリジナル:
f:id:masugata:20110405125239:image:medium
黒いもやもや(詳細で見てください):
f:id:masugata:20110330182455:image:medium
黒いもやもや有 ボカシ一部(真ん中ボカシ無し)(違いは詳細で見てください):
f:id:masugata:20110405111221:image:medium
黒いもやもや有 ボカシ全部(違いは詳細で見てください):
f:id:masugata:20110405111213:image:medium
黒いもやもや有 ボカシ無し(違いは詳細で見てください):
f:id:masugata:20110405111204:image:medium


黒いもやもやを合成しないと以下のような感じになります。
黒いもやもや無 ボカシ一部(真ん中ボカシ無し)(違いは詳細で見てください):
f:id:masugata:20110330173457:image:medium
黒いもやもや無 ボカシ全部(違いは詳細で見てください):
f:id:masugata:20110330173447:image:medium
黒いもやもや無 ボカシ無し(違いは詳細で見てください):
f:id:masugata:20110330173436:image:medium


黒いもやもや感が再現できなきなかったので画像を合成して無理やり対応。_| ̄|○
黒いもやもや画像は透明度を調整しています(真ん中辺りは透明度が多め。端に行く程、透明度が少ない)。
レトロやメロウな感じの懐かしい雰囲気が出せると嬉しいんだけどな。。。


色々と試行錯誤しているけど、HSVの処理が上手くいかない。。。想定外の動きをしている?思った通りに処理してくれない。
自分が全然理解していないダケだったらいいんだけど。。。現状の計算は色々と試行錯誤した上で一番良かった感じの計算値を採用してます。
段々と力任せに無理やり処理している気がしているけど。。。GIMPPhotoshopの使い方が少しだけ上達したので前向きに行こっと。_| ̄|○


他にも色々と加工しているので、小出しに出していくカモ。
ご指摘や参考情報などありましたら、ご連絡ください。<(_ _)>

2枚の画像から差分を抽出

こちらのページImageMagickコマンドラインツールを使って2枚の画像から差分を抽出する方法が紹介されていたけど、こういう事?すげー安直な気もするけど。。。

  // 比較する画像はお互いの縦横サイズが同一である画像を前提
  private Bitmap getDifference( ){

    Bitmap bitmapA = BitmapFactory.decodeResource( getResources( ), R.drawable.r01 ).copy( Bitmap.Config.ARGB_8888, true );
    Bitmap bitmapB = BitmapFactory.decodeResource( getResources( ), R.drawable.r02 ).copy( Bitmap.Config.ARGB_8888, true );

    int heightA   = bitmapA.getHeight( );
    int widthA    = bitmapA.getWidth( );

    int heightB   = bitmapB.getHeight( );
    int widthB    = bitmapB.getWidth( );

    int[] pixelsA = new int[( widthA * heightA )];
    int[] pixelsB = new int[( widthB * heightB )];

    bitmapA.getPixels( pixelsA, 0, widthA, 0, 0, widthA, heightA );
    bitmapB.getPixels( pixelsB, 0, widthB, 0, 0, widthB, heightB );
    
    for( int YY = 0; YY < widthA; ++YY ){
      for( int XX = 0; XX < heightA; ++XX ){

        int bitmapColorA = pixelsA[( YY + XX * widthA )];
        int bitmapColorB = pixelsB[( YY + XX * widthA )];

        int aaA = Color.alpha( bitmapColorA );
        int rrA = Color.red( bitmapColorA );
        int ggA = Color.green( bitmapColorA );
        int bbA = Color.blue( bitmapColorA );

        int aaB = Color.alpha( bitmapColorB );
        int rrB = Color.red( bitmapColorB );
        int ggB = Color.green( bitmapColorB );
        int bbB = Color.blue( bitmapColorB );

        // hsv[0] is Hue [0.0f .. 360.0f]
        // hsv[1] is Saturation [0.0f...1.0f]
        // hsv[2] is Value [0.0f...1.0f]
        // float[] hsvA = new float[3];
        // Color.RGBToHSV( rrA, ggA, bbA, hsvA );

        // float[] hsvB = new float[3];
        // Color.RGBToHSV( rrB, ggB, bbB, hsvB );

        // hsvB[0] = hsvA[0];
        // hsvB[1] = hsvA[1];
        // hsvB[2] = hsvA[2];

        // bitmapColorB = Color.HSVToColor( hsvB )
        // aaB = Color.alpha( bitmapColorB );
        // rrB = Color.red( bitmapColorB );
        // ggB = Color.green( bitmapColorB );
        // bbB = Color.blue( bitmapColorB );

        int aa, rr, gg, bb;

        if( rrA == rrB && ggA == ggB && bbA == bbB ){
          aa = 255;
          rr = 0;
          gg = 0;
          bb = 0;
        } else {
          aa = aaA;
          rr = rrA;
          gg = ggA;
          bb = bbA;
        }

        pixelsA[( YY + XX * widthA )] = Color.argb( aa, rr, gg, bb );
      }
    }

    return Bitmap.createBitmap( pixelsA, widthA, heightA, Bitmap.Config.ARGB_8888 );
  }

オリジナル:
f:id:masugata:20110404140058:image:medium
変更:
f:id:masugata:20110329130445:image:medium
差分抽出:
f:id:masugata:20110329130443:image:medium


それにしてもImageMagickは宝の山な感じがするなぁ。。。サボってないでソースコードを確認しろって事かしら。_| ̄|○

PHP-Cli Built-in web server RFC(続き)

昨日のですが、実際にプログラムを置いて確認してみました。
起動した位置がドキュメント・ルートになるのかな?後、rootにならなくても起動はできるみたい。

% cd /usr/local/src/php-trunk-201103030130
% echo '<?php echo "Hello World\!\!"; echo date( " Y/m/d H:i:s\\n" );' > hello.php
% sapi/cli/php -S localhost:4649
[Fri Mar  4 16:33:19 2011] 127.0.0.1:38942: /hello.php

異なるターミナルから以下を実行して確認。

% telnet localhost 4649
Trying 127.0.0.1...
Connected to localhost.localdomain.
Escape character is '^]'.
GET /hello.php

HTTP/0.9 200 OK
Connection: closed
X-Powered-By: PHP/5.3.99-dev
Content-type: text/html; charset=UTF-8

Hello World!! 2011/03/04 16:34:19
Connection closed by foreign host.
%

PHP-Cli Built-in web server RFC

moriyoshiさんがトンでもないををやろうとしているようです。すげぇ!

パッチはtrunkを対象にしているようだったのでtrunkで確認。
久々に試して遊んでみようと思ってビルドしてみたら。。。Undefined symbol で遊ぶ事ができませんでした。お前はもう遊ぶな!って事かしら。_| ̄|○

% cd /usr/local/src
% gzip -dc ./gist835698-b07dd229da2ebd9fdc03297a1a1dfd2082853d0b.tar.gz | tar xf -
% gzip -dc ./php-trunk-201103030130.tar.gz | tar xf -
% cd ./php-trunk-201103030130
% patch -p0 < ../gist835698-b07dd229da2ebd9fdc03297a1a1dfd2082853d0b/php-embedded-server-20110220.patch.diff
patching file sapi/cli/config.w32
patching file sapi/cli/php_http_parser.c
patching file sapi/cli/config.m4
patching file sapi/cli/php_cli_server.c
patching file sapi/cli/php_http_parser.h
patching file sapi/cli/php_cli_server.h
patching file sapi/cli/php_cli.c
patching file main/network.c
patching file main/php_main.h
patching file main/php_network.h
% ./configure --without-iconv --disable-all
% make

[Solaris(sparc)]
Undefined                       first referenced
 symbol                             in file
cli_server_sapi_module              sapi/cli/php_cli.o
do_cli_server                       sapi/cli/php_cli.o
ld: fatal: Symbol referencing errors. No output written to sapi/cli/php

[Linux(x86)]
sapi/cli/php_cli.o: In function `main':
/usr/local/src/php-trunk-201103030130/sapi/cli/php_cli.c:1347: undefined reference to `do_cli_server'
/usr/local/src/php-trunk-201103030130/sapi/cli/php_cli.c:1297: undefined reference to `cli_server_sapi_module'
collect2: ld returned 1 exit status

% uname -a
SunOS ***** 5.10 Generic_127111-05 sun4v sparc SUNW,Sun-Fire-T200 Solaris
% gcc -v
Reading specs from /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/specs
Configured with: /gates/sfw10/builds/sfw10-gate/usr/src/cmd/gcc/gcc-3.4.3/configure --prefix=/usr/sfw --with-as=/usr/sfw/bin/gas --with-gnu-as --with-ld=/usr/ccs/bin/ld --without-gnu-ld --enable-languages=c,c++ --enable-shared
Thread model: posix
gcc version 3.4.3 (csl-sol210-3_4-branch+sol_rpath)

% uname -a
Linux ***** 2.6.18-6-686 #1 SMP Fri Feb 19 23:40:03 UTC 2010 i686 GNU/Linux
% gcc -v
Reading specs from /usr/lib/gcc/i486-linux-gnu/3.4.6/specs
Configured with: ../src/configure -v --enable-languages=c,c++,f77,pascal --prefix=/usr --libexecdir=/usr/lib --with-gxx-include-dir=/usr/include/c++/3.4 --enable-shared --with-system-zlib --enable-nls --without-included-gettext --program-suffix=-3.4 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --with-tune=i686 i486-linux-gnu
Thread model: posix
gcc version 3.4.6 (Debian 3.4.6-5)

gccが化石だから。。。か?後でMac OS Xで確認してみよっと。


で、Mac OS Xで確認しても同じエラーだったのですが「./buildconf --forceしろ!」って神のお告げがあったので、その通りにしたら全ての環境でビルドが通りました!わーい。これで遊べる。
って、よくよく考えてみるとm4ファイルを変更しているのだから「./buildconf --force」は必要だったね。。。_| ̄|○

% cd /usr/local/src
% rm -rf ./php-trunk-201103030130
% gzip -dc ./gist835698-b07dd229da2ebd9fdc03297a1a1dfd2082853d0b.tar.gz | tar xf -
% gzip -dc ./php-trunk-201103030130.tar.gz | tar xf -
% cd ./php-trunk-201103030130
% patch -p0 < ../gist835698-b07dd229da2ebd9fdc03297a1a1dfd2082853d0b/php-embedded-server-20110220.patch.diff
patching file sapi/cli/config.w32
patching file sapi/cli/php_http_parser.c
patching file sapi/cli/config.m4
patching file sapi/cli/php_cli_server.c
patching file sapi/cli/php_http_parser.h
patching file sapi/cli/php_cli_server.h
patching file sapi/cli/php_cli.c
patching file main/network.c
patching file main/php_main.h
patching file main/php_network.h
% ./buildconf --force
% ./configure --without-iconv --with-libxml-dir=/usr --enable-mbstring
% make
% su
# sapi/cli/php -S localhost:4649
Server is listening on localhost:4649... Press CTRL-C to quit.
[Thu Mar  3 11:58:55 2011] 127.0.0.1:59253: /
[Thu Mar  3 11:58:55 2011] 127.0.0.1:59253: / - No such file or directory
[Thu Mar  3 11:58:55 2011] 127.0.0.1:59253: / - Sending error page (404)


% uname -a
SunOS ***** 5.10 Generic_127111-05 sun4v sparc SUNW,Sun-Fire-T200 Solaris
% gcc -v
Reading specs from /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/specs
Configured with: /gates/sfw10/builds/sfw10-gate/usr/src/cmd/gcc/gcc-3.4.3/configure --prefix=/usr/sfw --with-as=/usr/sfw/bin/gas --with-gnu-as --with-ld=/usr/ccs/bin/ld --without-gnu-ld --enable-languages=c,c++ --enable-shared
Thread model: posix
gcc version 3.4.3 (csl-sol210-3_4-branch+sol_rpath)

% uname -a
Linux ***** 2.6.18-6-686 #1 SMP Fri Feb 19 23:40:03 UTC 2010 i686 GNU/Linux
% gcc -v
Reading specs from /usr/lib/gcc/i486-linux-gnu/3.4.6/specs
Configured with: ../src/configure -v --enable-languages=c,c++,f77,pascal --prefix=/usr --libexecdir=/usr/lib --with-gxx-include-dir=/usr/include/c++/3.4 --enable-shared --with-system-zlib --enable-nls --without-included-gettext --program-suffix=-3.4 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --with-tune=i686 i486-linux-gnu
Thread model: posix
gcc version 3.4.6 (Debian 3.4.6-5)

% uname -a
Darwin ***** 10.6.0 Darwin Kernel Version 10.6.0: Wed Nov 10 18:13:17 PST 2010; root:xnu-1504.9.26~3/RELEASE_I386 i386
% gcc -v
Using built-in specs.
Target: i686-apple-darwin10
Configured with: /var/tmp/gcc/gcc-5664~105/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5664)

異なるターミナルから以下を実行して確認。

% telnet localhost 4649
Trying 127.0.0.1...
Connected to localhost.localdomain.
Escape character is '^]'.
GET /

HTTP/0.9 404 Not Found
Connection: closed
Content-Type: text/html; charset=UTF=8
Content-Length: 1145

<html><head><title>404 Not Found</title><style type="text/css">
body {background-color: #ffffff; color: #000000;}
body, td, th, h1, h2 {font-family: sans-serif;}
pre {margin: 0px; font-family: monospace;}
a:link {color: #000099; text-decoration: none; background-color: #ffffff;}
a:hover {text-decoration: underline;}
table {border-collapse: collapse;}
.center {text-align: center;}
.center table { margin-left: auto; margin-right: auto; text-align: left;}
.center th { text-align: center !important; }
td, th { border: 1px solid #000000; font-size: 75%; vertical-align: baseline;}
h1 {font-size: 150%;}
h2 {font-size: 125%;}
.p {text-align: left;}
.e {background-color: #ccccff; font-weight: bold; color: #000000;}
.h {background-color: #9999cc; font-weight: bold; color: #000000;}
.v {background-color: #cccccc; color: #000000;}
.vr {background-color: #cccccc; text-align: right; color: #000000;}
img {float: right; border: 0px;}
hr {width: 600px; background-color: #cccccc; border: 0px; height: 1px; color: #000000;}
</style>
</head><body><h1 class="h">Not Found</h1><p>The requested resource / was not found on this server.</p></body></html>Connection closed by foreign host.
%

バレンタインチョコ欲しい!

バレンタインチョコ欲しい!
欲しいプレゼントは…

機動戦士Zガンダム メモリアルボックス Part.II [Blu-ray]

機動戦士Zガンダム メモリアルボックス Part.II [Blu-ray]


本当はGoogle I/O 2011 のチケットが欲しいんだけど、無理そうなのでZガンダム見て癒されたい。○| ̄|_

俺とPHP

moriyoshiさんが思い出を語っているので自分も語りたくなりました。

PHPを使い始めたのは2000年。とあるWeb案件をやる事になったのがきっかけです。
当時インターネットは大きなフロンティアという雰囲気もあって、自分もWeb案件は初めてでしたが「遂にきた!」と興奮していた記憶があります。
その頃は社内でもPerlを使ってWeb案件をやるのが大部分であったり、隣の席ではASPを使って黒をベースにピンクの文字で書かれたロゴが印象的なWeb案件(音楽関係の会社)を華やかにやっていたりと、PHPを取り組む人達(といっても自分を含めて3人)はやれる事がなく扱いに困っていて、最近PHPが話題になっているので評価もかねて新しい事に取り組んでみようか。。。みたいな感じでした。少なくとも戦略的に取り組んではいなかったと思います。
当時は自分も21歳になったばかりで、野心ギラギラで「社内に風穴を空けてやろう!社内勢力を塗り替えてやる!」と何もできないけど勢いと野望だけはあるみたいな感じで取り組んでいました。


一番最初に取り組んだWeb案件ではPHPを使うかXMLを使うか迷っていて、企画の方が「PHPでやらないんだったら、お断りします」と言っていたのが印象深いです。
今もその案件は運用しているようなので感慨深いというか(PHPのバージョンは最新版になっておりますが)ちょっと恐怖を感じます。
当時、使っていたバージョンはPHP3.0.15.-i18n-ja。mbstringが本体に取り込まれたのは4.0.6(リリースは2001年)から。当時はjstringとも呼ばれていましたね。懐かしい。


当時のPHPの印象としては、日本語マニュアルが非常に充実していて困る事が少なく、メーリング・リストも優しい方が多くてWeb案件を初めてやるような人でも優しく包んでくれるような環境だったと思います。そんな環境だったので、自分も積極的にメーリング・リストでフォローするよう心がけていました。
Blogも今みたいに盛り上がってはおらず、メーリング・リストや著名な方のHPに情報が殆ど集約されているような時代でした。そういう意味では困った時の情報収集は今よりも楽だったのかもしれません(後、検索結果も Google がブイブイ言わせていた時期で、SPAM も少なく良質な記事がググれば簡単に出てきたので)。
また、色々な拡張モジュールがバンドルされていたので、手当たり次第ビルドしながら色んな関数を動かしては興奮して、動かしては興奮して「こんな事ができる!あんな事もできる!」と、のめり込んでいったのを覚えています。imap拡張モジュールを使ってメールサーバにあるメールを読めたのは本当に感動したのを覚えています。
次第にPHPに大きな可能性を感じるように「いける(社内で対抗勢力として充分に戦える)!」と思うようになりました。今、振り返ってみると、PHPに可能性を感じた。。。というよりかはWebに大きな可能性を感じていたのかもしれません。
ただ、社内での印象は(特にサーバ管理者部門からは)悪かったように思えます。
バグが多い、脆弱性が多い、(当時はDSOではなくてstaticにリンクする形式を取っていたので)Apacheモジュールとしてインストールするには入れ替えが激しく面倒だし、ビルドするにも時間がかかる、とにかくサイズが大きい。。。みたいな感じでサーバ管理者泣かせであったのは間違いないようです。いつも、やり玉に上げられているような感じでした。


PHPにも苦手な領域はありますが、あえてそういう領域でPHPを使ったりしていました。
当時は棲み分けについて議論した記憶がありますが「言語が凄いんじゃない。プログラマが凄いんだ!」と思っていた自分はそういう風に分類するのが凄く嫌いでした。あえて苦手な領域でPHPを使って課題を解決することで自分の考えを証明しようとしてました。
今考えると完全に「若さ故の〜」だったと思います。この頃から熱くなると周りが見えなくなっていたのは変わっていないようです。
この時期だっけかな?ある人から「PHPが好きなのは分かるけどさ」と言われた時に「PHPが好きな訳ではありません。仕事で使っているだけです」と答えています。PHPを好きかどうかは別にして、自身の野望と目的達成の為にPHPを使っていた事は間違いありません。


逆風にも負けず地道に取り組み続け、順調に拡大は続いていきます(この頃やっていたのはYがトレードの楽器関係の会社)。
時には残業時間が200時間を超していた時もあったけど、若さのおかげか体力勝負で何とか乗り切ってました(家から歩いて5分のところに会社があったので、朝の5時に帰って、ちょっと寝て、9時には出社みたいな状態)。
今だと考えられませんね。9.11事件を会社のTVで深夜に皆で見ていたのが思い出深いです。その前日に自分は入籍したので、入籍したから突っ込まれたのか?と焦ってました。


その後も順調に拡大が続いていき(この頃やっていたのはYがトレードの家電会社)、ASPをやってた人達もPHPに合流する等、勢力も増してきて社内でもPHPが無視できない存在になってきました。
同時に反対勢力の反発も大きくなってきました。気に食わないPHPで好き勝手やられている状況です。相手の立場になって考えてみるとアレなのですが、当時は「色々とご迷惑をおかけしました(が、反省はしない)。」みたいな雰囲気で、とにかく懲りなかった記憶があります。今考えると非常識ですね。ただ、非常識なのは今も変わっていないのかもしれません。


反対勢力との溝が大きくなり対立が日々激しくなっていく状況で、PHPに大変な出来事がおきてしまいました。この時はさすがにもう駄目だ。。。と思いました。
反対勢力が主催して緊急会議が開かれましたが、実際は吊るし上げ状態でした。
「この問題どうするんだよ?」とか「だからPHPを使うべきではないと前から散々言ってきたのに」とかスゲー罵られました。鬼の首を取ったどー!状態です。
ただ、自然に解決するだろうと思っていたので「大丈夫です。解決するので問題ありません」の一点張りで、じっと耐えてました。元上司が「ライセンスを購入するのはどうすればいいんだ?」と真面目に発言していたのが面白かったです。そういう発想もあったか。
この問題は無事に解決されたのですが、吊るし上げ状態に納得がいっていなかった?ので記事を投稿しました(Anonymous Cowardになっていますが、投稿したのは自分です)。
今と違って当時は ./ もニュースサイトとしては人気があったのですが(投稿したせいなのかは分かりませんが)後日、該当サイトへのPOST通信がF/Wのポリシーで禁止されるようになりました。どうもすみませんでした。(w


反対勢力とは書いていますが、実際には最初のPHP立ち上げ時から、ものすごくお世話になっているサーバ管理者部門の方です(技術的にも尖っている尊敬できる人)が、この事件を境に関係が薄くなっていきました。
ちょっと関係がギクシャクしていた事もあったのですが、いつも迷惑をかけている状況だったので「これじゃいけない!」と自分の中で思うようになり、自分自身の成長、そして自立する為にも離れて活動するようになりました。


相変わらず順調に拡大していき、社内でもPHPが認知されるようになり、年間で1億くらい生産できる状況になりました。当初の目標は達成できたかな、と思います。
PHPを使う人が多くなってきたので段々と統率を取るのが難しくなってきたのと、PHPのバグの多さに悩まされる日々が続いたので、コードの品質やスキルレベルを均一に保つ為、社内ライブラリを用意しました(最終的には800くらい用意しました)。
便利なライブラリを沢山用意してコードを書かずに使わせるように徹底すれば、誰がコードを書いても同じようなコードになる訳だし、関数の挙動が変わったり脆弱性が発見された場合、ライブラリを修正して配布すればてのプログラムが修正されます。
外部フレームワークによる開発も当時はフロンティア状態で(まだまだ)確立されているとは言いがたい状況だったのと社内の環境が特殊であった為、全て自分で揃えようと、この時に決心しました。


この頃から本格的にスナップショット(cvsやコミット・ログ)を意識するようにして、影響がありそうな修正を早く見つけて問題が出る前に社内ライブラリを追加したりする等していました。バグ報告をしたり動作の確認を事前に行う等、自分にできそうな事は積極的にやっていきました。
当時は今みたいにPHP内部の実装を理解して修正するような積極的な日本人が少なくて、慢性的な人手不足が続いていました。自分もバグ報告はできるけどバグ修正できない日本人の一人だったので、報告する度に心苦しい思いをしていました。
段々と「迷惑ばっかりかけて、これじゃ駄目だ」と自分の中で思うようになり、PHPソースコードを見るようにしていきました。
19歳の時に(1年くらいだけど)C言語を使って仕事をしていたので何とかなるかも。。。と思っていたのですが、実際は全然駄目でした。
仕事をしていたといっても「初めてのC」書籍程度の知識が無くて、NEWS上で動く単なるテキスト解析(ファイルから一行ずつ読み込んで加工して別のファイルに出力する)バッチ処理しかやったことがありません。また、C言語を使って仕事をしなくなってから5年くらい経っていたので殆ど忘れていました。


余談になりますが、この時に初めてmalloc & free の存在を知りました。最初は何かの関数か?と思っていたので、ずーっと探していたのですが、内容を知った時に教育してくれた先輩を恨みました。
先輩の話では「今と違って昔のOSは動的に確保したメモリを解放し忘れたらメモリを掴みっぱなしなんだよ。一人が使うマシンで動かす訳じゃないから、そんなリスキーな事はできないだろ?」みたいな事を言ってました。今考えると怪しいな。。。なので、関数の存在を知るまではC言語では静的にメモリを確保するものだと思っていました( #define BUF_SIZE 10000; char hoge[BUF_SIZE]; memset( hoge, 0, BUF_SIZE); みたいな)。もしかしたら、バッチ処理なのでプロセスは長い間生きていることが多くて、メモリ・リークが多いとOS全体が大変な事になってしまうので、そういうリスクを未然に防ぐ為に、あえて教えなかったのかもしれません。


話を戻して、PHPソースコードは全然理解できなかったのですが、懲りずにmbstring.cとmbstring.hを見続ける日々が続きました。
さすがに毎日眺めているとコードの内容を丸暗記できるようになってきて、ある日を境に共通点が沢山ある事に気がつきました。何気なく青マンモス本を見てみると、PHPソースコードのお作法に関するページがある事に気がつき、とても興奮したのを覚えています。この頃から買った本は殆ど見ていない(索引からの逆引きとしてでしか使っていない)ようでした。灯台下暗し。。。
次第にmbstring以外のソースコードにも目を向けるようになりました。分からない部分も沢山あったけど、当時はOO指向が主流ではなかったので、共通点も多くてスムーズに理解することができました。実際に改造してみたり、独自の関数を追加したりして楽しんでいました。


moriyoshi さんのモチベーションが下がったのもそれくらいの時期だったのかなあ。
主メンテナに何があったのかは分からないけどmbstringのメンテナンス状態が芳しくない状況になってきたので思いきってCVSアカウントを取りました()。
脆弱性対応とか独自PHP拡張を書く為のスキル向上とか、(英語が全然できないくせに)本家における日本人の弱い立場を少しでも解消したいとか、今までお世話になった分を少しでも恩返ししたいとか、onigurumaのアップデートに追随したいとか、@php.netドメインを取りたかったとか、とにかく一石十鳥みたいな感じで色々目的はあったような気もしましたが、とにかく「主メンテナが活性化するまでの繋ぎ」として頑張ってみようと思っていました。主メンテナが活発に活動するようになったら迷惑がかからないよう、さりげなくフェードアウトしようと考えていました。
元々そんなにスキルは無かったので要望が出ても応えられる自信も無かったし、主メンテナが活性化するまでの繋ぎだし、メンテナンスしながらスキル向上していけばいいや、と軽い気持ちでいました。そんな軽い気持ちでやってたのかよ。。。と改めて振り返ってみると絶句です。おもちゃではないんだし。。。
今考えると、phpdocのkarmaを貰わなかったのは完全に失敗したなと思っています。関数を追加してもドキュメントに追加できないし。。。


遅くまで仕事していたので主に作業は家に帰ってからでした。最初はcvsの使い方も分からず苦労しまくりです。
家に帰るのがいつも1時を過ぎていたので、作業して就寝ともなると3時を超えたりしていました。メンテナの皆様は、こうやって睡眠時間を削りながら作業しているのか。。。と思うと、今まで自分がしてきた発言がどれだけ負担をかけているか、と思うようになり切なくなりました。
最初はどうでもいい修正から始まり、徐々に関数を追加していきました。慣れてくると段々面白くなってきて、コミット・ログやソースコードに自分のアカウント名が記載されているのを見て興奮していました。
それまではPHPのバージョンがリリースされるのが(脆弱性の確認や開発環境のアップデート等)少し辛かったのですが、自分もメンテナンスしている(参加している)という事もあって、新しいバージョンがリリースされるのを楽しみにしていました。


メンテナンスするようになってから1年くらいかな?ある関数を追加した事で意見の相違や考え方の相違による喧嘩をしてしまいました。
今考えると自分も調子に乗ってたな(精神状態がお子ちゃまだったかな)、と反省しています。
改めて「そもそも自分は何の為にメンテナンスをしているのだろうか?」と考えるようになりました。色々と考えた結果「自分がメンテナンスする事で誰かが満足できない状況が発生するようではメンテナとしての資格は無い。メンテナ失格。自粛すべき」と思うようになりました。
その後はhirokawaさんやmoriyoshiさんがフォローをしてくれて、一応、落ち着きました。心残りとしては mb_explodeやmb_str_replaceを実装できなかった事ですが、そんな事はどうでもいい事です。


メンテナンス作業をやめてからは(大きな目標が無くなってしまった為)心にぽっかり大きな穴があいた状態が続きました。
この頃から次の目標を立てられず迷走している状態が続きました。主メンテナから外れた後も自分のBlog内であれば迷惑かからないだろう。。。と思って、脆弱性対応のバックポート用のパッチを書いたり、gdbを使って改造したりと細々とやっていましたが、モチベーションは上がってきません。行き詰まりを感じてしまいました。振り返ってみると、Blogのエントリは本当に自分がやったのかなぁ?と感じています。そんな事できるスキルなんて無かったような気がします。


社内の政治にも段々と巻き込まれるようになって会社にくるのが辛くなりました。
転職でもしてみようかと思って、実際に色々な企業の面接に行ってたりしていました。次の就職先が決定しそうになった時に自分の中で「本当に転職してもいいのか?」と迷いが生じました。色々と考えた結果「単に逃げているだけだ」と思うようになり、転職するのはやめました。


そこからしばらくして管理職になりました。
継続してPHPを担当するのかな。。。と思っていたら全然違いました。Javaを担当する事になりました。社内のPHP開発体制を確立したように、社内のJava開発体制を確立しほしい、との事でした。
Java開発体制を確立しておけばエンタープライズ系で更に大きな金が動くと経営層は恐らく判断したのでしょう。そういう意味ではPHPと違って戦略的に取り組もうとしていたのだと思います。


実際に周りの人も自分がPHPを担当すると思っていた人が多くて色んな人が困惑していました。
とりあえずPHPに関する業務は全て移管しました。管理職者になった時、一番最初の挨拶で「新しくできた部署を一年で潰さないように頑張りたいと思います」と言ったのを覚えていますが、モチベーションが上がるか不安でした。
ただ、担当を外された割には困った時だけ呼び出されて「何とかしろ」とかいう始末。都合の良い人状態。
昔からそういう傾向は沢山あったのですが、その時はPHPをメインで担当していたので何とかモチベーションは保てていましたが、流石に今回はモチベーションは維持できませんでした。再び会社をやめようかな。。。と考えるようになりました。後頭部に円形脱毛症ができたりもしました。


今までは意図的にJavaを使うのを避けていたので表面的な知識しか無かった事もあったのですが、それ以前に、異なる言語で同じ領域を社内で再び取り組む事に何の意味があるのだろうか?と疑問に感じていました。
また、社内のJava開発体制に関しては過去にも浮かんでは消えて、浮かんでは消えての状態が延々と続いていたので、これを浮上させるのは相当難しいだろうな。。。と思っていました。
運用やプログラムの更新方法や思想も従来とは異なるし、マルチスレッドという言語の特性や難しさもある。おまけに過去に何度も失敗している経験もある。苦い経験をしている人が多い為、社内でもJavaの印象は良くありませんでした。
この時に集められた面子(自分の部下)は社内でWeb案件をした事が殆どないような温室育ちの人達が多く、色々な意味でゆるい人達ばかりでした。年配の方は自分で解決しようとせず、若手はスキルが乏しく自分で時間配分を考える事ができず自発的に行動できなかったりと「こいつら本気で仕事する気があるのか?」と苛つきながら、とにかく最初は仕事の上では1日が24時間ではなくて1日8時間(勤務時間)である事を認識させる事に苦労していた記憶があります。
自社開発案件しかやった事が無く「納期は交渉すれば変更される」と思っている人が多く、かけもちで仕事をした事が無い人が殆どでスピード感も全然感じられず、自分が育ってきた環境とは真逆の環境で育ってきた人達でした。とにかく意識を変える事に注力してきた気がします。そんなに人生は甘くないぞ!この頃「こんなに怒られたのは生まれて初めてです」と言われた事が印象深いです。


不安要素は沢山あった訳ですが、それでも任されたからには何とか頑張らないといけません。
どうにかして入り込める余地を考えつつ、バッチ処理だったらスムーズに入り込みやすいかな。。。と思って、バッチ処理に関してはJavaで開発するよう、色んな部署にお願いしたりしていました。そこから徐々に浸食していこうと考えていました。
ただ、バッチ処理だけで多くの生産が見込める程、甘くはありません。なので、既存言語で取り組んでいるWeb案件のヘルプ要員として細々と取り組みながらチャンスを伺うような毎日を過ごしていました。ただ、運が悪い事にリーマンショックの件も重なって、チャンスは全く訪れませんでした。この時ばかりは「運は味方してくれなかったか。。。」と思いましたが、今考えると、取り組んではいたものの自分の気持ちが入っておらず、本気で取り組んでいなかった気がします。指示ばかりで実際に自分で手を動すような事は何もしていなかったので、やっつけでやっていたような気がします。


相変わらず厳しい状況は続きましたが、その頃の業界ではiPhone開発やAndroid開発等のスマートフォン・アプリ開発が本格的に盛り上がろうとしていた時期でした。
元々アプリを作成するのは興味があったので、この波に乗ってみようかな。。。と考えるようになりました。特にAndroid開発は言語がJavaなので今の面子を活かす事ができ、自分も興味がある分野なので一石二鳥。全体のモチベーションも下がって雰囲気は良くない(頑張っても成果が出ない。。。と嘆いている)状況だったので、全員で新しい事に取り組む事で雰囲気を良くしようと考えていました。
ただ、ここで想定外の出来事が起きてしまいました。大規模な自社開発案件が決定し、Javaで開発する面子が全員(かつ長期間)招集される事になりました。いざ皆で頑張って取り組んでいこう!と思っていた矢先の出来事で、嬉しいかな、悲しいかな。。。といった感じです(定期的な生産が確保できるようになったが、新しい事をやろうとする人が自分だけになった)。
決まってしまったものは仕方がないので気持ちを切り替えて頑張ろうと思っていました。長期間といっても終わりは必ずやってきます。帰ってきた時に再び開発案件が無くてお互い居心地が悪くなるような状況はコリゴリです。招集された面子が帰ってくる事を見越して、帰ってきても開発案件に困る事が無いように、開発案件の種を蒔いておいて下地を作っておこうと決心しました。


丁度その頃はXperia(SO-01B)が販売されたくらいの時期で、この時はAndroid開発もまだまだなあ。。。という印象を感じており、先にiPhone開発を行おうと決心しました(iPhone3GSが販売されるくらいの時期)。
iPhone開発を行うのはIntel CPUが搭載されたMacが必要との事で、この時、初めてMacを触る事になりました。最初はOSの操作もおぼつかないくらい大変でしたが、コピー&ペーストとアンドゥのやり方を覚えてからは作業効率が一気に上がりました。ただ、Macを入手するのにも色々と一悶着あって、結構うんざりしていたのを覚えています。
Macを入手してからは色んなサイトを参考しつつ、試行錯誤しながら取り組んでいきました。周りには誰も助けれくれる人がいなかったので、一人寂しくやっていたのを覚えています。途中で関西の方も合流して一緒に取り組んでこんなのを作る事ができました。その頃はこんなのも平行してやってはいましたが、個人的にはコレが社内で流行る事は無いと思っています。単なる客寄せパンダだと今でも思っています。


ある時、社長が色々な人の意見を聞く取り組みを行っていました。
自分も話をする機会があったので、この時に口が滑って色々な事を言ってしまいました。今考えると自分の不満をガツンと言っただけなので、一緒に参加していた人には申し訳なかったかな、と思います。
これが影響したのかは分かりませんが、社内の組織が大きく変化して、自分にも新しい風が吹くようになり、今まで担当していた部署を離れる事になりました。
同時に自分が担当していた部署も他の部署に吸収合併される形で消滅しました。一年は持ったけど二年で消滅する事になってしまったのは残念です。力が及びませんでした。。。が、恐らく、社内におけるJavaの位置付けは今後も(Web案件に関しては)浮かんでは消えて、浮かんでは消えて、を繰り返すような気がしています。勝手な予想なので外れてくれると嬉しいかな。。。とは思いますが、自分が再びJavaを担当する事になったとしても、Web案件ではなくてAndroid開発案件として使うんだと思います。
補足しておきますが、厳しい状況は続いていましたが製造利益・営業利益共に黒で終わっています(年間平均でいうと1億くらいの生産)。なので、会社に迷惑はかけてはいないと思っています。単に期待外れだった、という感じです。タイミングが合っていれば、また違った結果になっていたのかな。。。。とは思いますが、結果が全て。


新しい部署では(社内で取り組めていない取り組むべき)新しいことをやるのがミッションになっています。
業界ではiPhone/iPad開発やAndroid開発が非常に盛り上がっているので、まずは、この波を社内全体に持ってこようと考えています。今までは小さく活動していましたが、これからは周りをドンドン巻き込んで大きく活動していかなければなりません。この波だけではなく、他の波も社内全体に持ってこようと考えています。
大変な事は多いのですが、自由にやらせてもらっているので充実した日々を過ごせています。自由にやらせてもらっているので、元に生活に戻れるか不安ですが。。。
また、PHPの時に感じた可能性を再び感じています。去年はiPhone/iPad開発を取り組み、こんなのを作る事ができました。今年はAndroid開発をメインに取り組むつもりです。たまに都合の良い人状態でコキ使われることがあって凹んだりもしていますが、基本的にはモチベーションが上がっているのを実感しています。


PHPを取り組んでから今に至るまで10年くらいですが、それまでには色んな出来事がありました。
PHPを通じて色んな経験をすることができました。苦い事も。甘い事も。楽しい事も。辛い事も。まるで人生みたい。
改めて考えてみると「好きじゃない」と言っていた割には割と本気でPHPと向き合っていたような気がします。
また、社内におけるPHPの位置付けも「俺のPHP」から「皆のPHP」になった気がします。子供が成人になった日を迎えるような親の気分に似た感覚があります。
自分は自分なりに自分のやり方で、新しい目標を全員で盛り上げていくべく取り組んでいきますが、再び交わる事があると嬉しいな。。。とも思います。


やっぱり10年の思い出だから相当長くなってしまったけど、過去を振り返って「昔は良かった。。。」みたいな事は言いたくないし、良い事も悪い事も含めて過去は過去。すがってはいけない。


この文章を一つの区切りにして、輝かしい新しい未来に向かって自分の可能性を信じて一歩ずつ前に進んでいこうと思います。