トランザクションでロールバックされない処理

BEGIN
— 任意の処理 ..(A)
ROLLBACK

とすれば、(A)で何をしてもロールバックしてくれるものだと思っていたらそれは勘違いのようです。
 
たとえばシーケンスなど

create sequence seq;
 
BEGIN;
SELECT nextval(‘seq’); — (B)
SELECT nextval(‘seq’); — (C)
ROLLBACK;
SELECT nextval(‘seq’); — (D)

としても (B) == (D) にはならず、BEGIN, ROLLBACK で囲まなかった場合と同じになります。
 
PGSQL-JP ML によると
http://www.drive.ne.jp/iMA/showmail.pl?pgsql-jp=3098

 

素人的な考えだと、transaction 内での処理なんだから、値を戻して
くれてもよさそうなものなのに、と思うのですが。。

#Oracle でも sequence は戻らないと聞いたので、出来ないのが普通
#なのかなあ?

 
他にも戻らないものとしては、
create table
create index
create sequence
があります(他にもあるかも)。商用DBでも多分同じです。

公式 PGSQL ML の引用

It’s normal behaviour.
 
Sequences are locked only for duration of nextval call, not for
transaction! So, one sequence may be used simultaneously
by many transactions. No way to rollback sequence changes.
 
意訳: シーケンスのロックは nextval 呼び出しについてのロックであり、トランザクションのためのロックではありません。一つのシーケンスが同時に複数のトランザクションで利用されうるため、シーケンスの変更をロールバックする方法は存在しません。

ということですが、単純に、一つのテーブルで serial (bigserial)として利用していて、他で nextval が呼ばれないことをシステム的に保証していれば、テーブルロックを使い、ROLLBACK 時にシーケンスを元に戻してやれば、一応実現は可能かなと思います。

GD でマスク処理

ふと、ImageLayerEffect() という関数を見付けたのですが、情報がなかったため、使い方を書いておきます。
 
User Contributed Notes より..

bool imagelayereffect ( resource image, int effect )
 
この関数は全ての描画関数の処理に影響を与えるという点で、既存の関数 ImageAlphaBlending() と似ています。(以下に示す)エフェクトモードを切替えることで既存の関数の機能を拡張できます。
 
effect には以下のうちいずれか一つを指定します。
 
IMG_EFFECT_REPLACE
ピクセル置換を利用します(ImageAlphaBlending(FALSE) と同等)
 
IMG_EFFECT_NORMAL
通常のピクセルブレンディングを利用します(ImageAlphaBlending(TRUE) と同等)
 
IMG_EFFECT_OVERLAY
 オーバーレイルーチンを利用します。オーバーレイは、黒い下地のピクセルは黒のまま、白い下地のピクセルは白のままですが、グレーの下地のピクセルに対しては上に乗るピクセルの色をとります。

 
当然気になるのは、IMG_EFFECT_OVERLAY です。
説明にある下地のピクセル(background pixels)というのは、たとえば imagecopy() を使う時の、コピー先の画像のそれぞれのピクセル、上に乗るピクセル(foreground pixels)というのはコピー元の画像のそれそれのピクセルにあたります。
 
下地がグレー(0x7F7F7F)の時は上に乗る色、
RGB のそれぞれが 0 に近付くほど、上に乗る色のそれぞれの色を暗くし、0になると元の色によらず 0 になります。つまり全てが0になると真黒(0x000000)になります。
同様に FF に近付くほど、元の色が明るくなり全てが FF になると真っ白(0xFFFFFF)になるようです。
 
例: 画像の任意の部分を黒に塗りつぶす

$im = imagecreatefromjpeg(“sample.jpg”); // 任意の元画像
// 画像サイズ
$w = imagesx($im);
$h = imagesy($im);
// 非透過
$c_visible = 0x007F7F7F;
// 背景(黒)
$c_bg = 0x00000000;
// 中央に円のあるマスクを作成
$im_mask = imagecreatetruecolor($w,$h);
imageFilledRectangle($im_mask, 0,0, $w,$h, $c_bg);
imageFilledEllipse ($im_mask, $w/2,$h/2, $w,$h, $c_visible);
 
// コピー先のエフェクトモードを変更(デフォルトは IMG_EFFECT_NORMAL)
imagelayereffect($im_mask, IMG_EFFECT_OVERLAY);
 
// 元画像にマスクを適用(結果はマスクに上書き)
imagecopy($im_mask, $im, 0,0, 0,0, $w,$h);
imagedestroy($im);
 
// マスク結果を出力
imagepng($im_mask);
imagedestroy($im_mask);

 
非透過とある部分を、 たとえば 0x00FF007F にすると、非透過部分のそれぞれのピクセルに対し、R 要素を FF, G 要素を 0, B 要素をそのままで出力します。
 
また、α値も組合せることが可能です。
 
例:画像の任意の部分を透過する

$im = imagecreatefromjpeg(“sample.jpg”); // 任意の元画像
// 画像サイズ
$w = imagesx($im);
$h = imagesy($im);
// 非透過
$c_visible = 0x007F7F7F;
// 背景(透過)
$c_bg = 0x7F7F7F7F;
// 中央に円のあるマスクを作成
$im_mask = imagecreatetruecolor($w,$h);
imagelayereffect($im_mask, IMG_EFFECT_REPLACE); // 透過色塗りのため上書きモードに変更。
imageFilledRectangle($im_mask, 0,0, $w,$h, $c_bg);
imageFilledEllipse ($im_mask, $w/2,$h/2, $w,$h, $c_visible);
imagelayereffect($im_mask, IMG_EFFECT_NORMAL); // 透過色を透過するため通常モードに戻す。
 
// コピー先のエフェクトモードを変更(デフォルトは IMG_EFFECT_NORMAL)
imagelayereffect($im_mask, IMG_EFFECT_OVERLAY);
 
// 元画像にマスクを適用(結果はマスクに上書き)
imagecopy($im_mask, $im, 0,0, 0,0, $w,$h);
// 透過色を保存する設定
imagesavealpha($im_mask, true);
 
imagepng($im_mask);
imagedestroy($im);

IE で PNG-24 が透過されない

IE6 でアルファチャンネルで透過している PNG を単純に<img>で表示させるとαチャンネルが無視されるという仕様のようです。
この対策を調べたところ、filter を使った解決方法がありました。
 
ieでPNGを表示させる
 
ここを参考に IE の時のみ

<img src=”blank.gif” style=”filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=’<画像のURL>’,sizingmethod=image);”>

のように、空画像へのフィルタとして実体画像を指定することで表示できました。

AS3 を試す

http://www.dango-itimi.com/blog/archives/2006/000897.html
にあるように、Flash9 AS3 ではクライアントでの画像生成(BMP,JPG,PNG)など、バイト列を直接操作できます。来春リリースだそうです。
 
Flash9 AS3 previewから開発環境がダウンロードできます(利用には Flash8 のライセンスが必要)
 
また、Flash9 Player は既にリリース済みです。
参考:
PNGEncoder
JPEGEncoder
ActionScript3.0 Tutorial
AS3.0 の記述の基本

スクリプトを実行している perl の実行パスを調べる変数

print $0;

だと, スクリプト名になってしまうので

print $^X; # $ + 制御文字 0x18

とします。
 
例:
foo.pl

#!/usr/bin/perl
 
print “script name: $0\n”;
print “perl: $^X\n”;

実行コマンド:

./foo.pl

結果:

script name: ./foo.pl
perl: /usr/bin/perl

imagerotate の小数から整数への変換仕様

imagerotate の結果を計算で出したいなと思い次のコードで検証してみました。

<?php
// 対象の画像のサイズ。
$sw = 1000;
$sh = 2000;
// 実測用に画像生成
$im = imagecreatetruecolor($sw,$sh);
for($deg = -360; $deg <= 360; $deg +=15){
   $rad = deg2rad($deg); // 三角関数はラジアンを取るので角度をラジアンに変換
   // 回転後のサイズ計算(四捨五入)
   $w = round(abs($sw * cos($rad)) + abs($sh * sin($rad)));
   $h = round(abs($sw * sin($rad)) + abs($sh * cos($rad)));
   // 実際に回転させた時のサイズ
   $im_t =imagerotate($im, $deg, -1);
   $rw = imagesx($im_t);
   $rh = imagesy($im_t);
   imagedestroy($im_t);
   // 比較
   if($w != $rw || $h != $rh){
     echo “$deg: calc($w, $h) != real($rw, $rh) “.”\n”;
   }
}
?>

結果:

-330: calc(1866, 2232) != real(1867, 2233)
-315: calc(2121, 2121) != real(2122, 2122)
-300: calc(2232, 1866) != real(2233, 1867)
-240: calc(2232, 1866) != real(2233, 1867)
-225: calc(2121, 2121) != real(2122, 2122)
-210: calc(1866, 2232) != real(1867, 2233)
-150: calc(1866, 2232) != real(1867, 2233)
-135: calc(2121, 2121) != real(2122, 2122)
-120: calc(2232, 1866) != real(2233, 1867)
-60: calc(2232, 1866) != real(2233, 1867)
-45: calc(2121, 2121) != real(2122, 2122)
-30: calc(1866, 2232) != real(1867, 2233)
30: calc(1866, 2232) != real(1867, 2233)
45: calc(2121, 2121) != real(2122, 2122)
60: calc(2232, 1866) != real(2233, 1867)
120: calc(2232, 1866) != real(2233, 1867)
135: calc(2121, 2121) != real(2122, 2122)
150: calc(1866, 2232) != real(1867, 2233)
210: calc(1866, 2232) != real(1867, 2233)
225: calc(2121, 2121) != real(2122, 2122)
240: calc(2232, 1866) != real(2233, 1867)
300: calc(2232, 1866) != real(2233, 1867)
315: calc(2121, 2121) != real(2122, 2122)
330: calc(1866, 2232) != real(1867, 2233)

この結果から判断して、
imagerotate では内部的に ceil で繰り上げにしているようなので
単純に round -> ceil にかえてみたところ、
結果は次のようになりました。

-360: calc(1001, 2001) != real(1000, 2000)
-270: calc(2001, 1001) != real(2000, 1000)
-180: calc(1001, 2001) != real(1000, 2000)
-90: calc(2000, 1001) != real(2000, 1000)

PHP の float の特性(*1)が悪さをしているのか、切り上げ処理で GD の結果と食い違いができてしまったようです。
ということで次のようにすれば完全に一致しました。

<?php
// 回転後のサイズ計算(imagerotate 互換の切り上げ)
$fw = abs($sw * cos($rad)) + abs($sh * sin($rad));
$w = ceil(“$fw”); // 一度文字列にする
$fh = abs($sw * sin($rad)) + abs($sh * cos($rad));
$h = ceil(“$fh”); // 同上

 
 *1: PHP の float は有効桁数を超えると表示上その部分が見えなくなります。

$f = 1 + 1E-13;
echo “$f\n”; // 1 が表示される
if($f > 1){
    echo “$f > 1\n”; // 1 > 1 が表示される。
}
echo sprintf(“%.15f”, $f).”\n”; // 1.000000000000100 が表示される

LoadVars – 外部テキスト読み込みクラス

Loadvars(livedocs)
 
例1:

var user = new LoadVars();
user.onLoad = function(success){
  if(success){
    trace(“名前: ” + this.name);
    trace(“年齢: ” + this.age);
    trace(“職業: ” + this.job);
    play(); // 読み終ったら次のフレームに。
  }else{
    trace(“失敗”);
    return;
  }
}
user.load(“user.txt”); // 中身は name=John&age=24&job=Fireman とする
stop();

例2(任意書式のテキストデータを読む):
CSV データ等を読む場合は LoadVars.onData() を使います。

var mesLoader = new LoadVars();
_global.message = ”;
mesLoader.onData = function(src){
   if(src == undefined){
      trace(“失敗”);
      return;
   }
   _global.message = src;
   play();
}
mesLoader.load(“message.txt”); // 中身は Hello, world! など任意。
stop();

参考:
LoadVarsでテキストファイルを読み込む

Ethereal,Tethereal が FreeBSD の ports から消えてた

ローカルの ports で探してみて、net/ethereal にあったはずの Ethereal が見付からなくてアレッ!?と思って公式の cvsweb をあたって見たところ
次のように書いてました。
 
http://www.jp.freebsd.org/cgi/cvsweb.cgi/ports/net/ethereal/Attic/Makefile?hideattic=0

FILE REMOVED
 
Add wireshark and tshark after repocopies from ethereal and tethereal
respectively. Wireshark is a rename of ethereal after the principal
developer moved companies and lost the Ethereal copyright.
 
Messenger, don’t shoot!
 
Now the ethereal binary is called wireshark, the tethereal binary is
called tshark, and idl2eth is now idl2wrs. All other binaries have
kept the same name.
 
In addition to this name change, I have also changed the PREFIX from X11BASE
to LOCALBASE.

 
Ethereal(CUI 版: TEthereal) は主要な開発者が会社を辞めて商標権を失って wireshark(CUI 版: tshark) という別の名前で存続する事になった、ということです。
 
ということで ports を改めて見ると、 net/wireshark, net/wireshark-lite, net/tshark, net/tshark-lite が増えてました。
 
Wireshark の公式サイトは http://wireshark.org/ で、
現在、Ethereal 0.99 から更新された Wireshark 0.99.2 がリリースされています。
 
参考:
「Ethereal」は「Wireshark」に飲み込まれるのか?(ITpro)
Wireshark 公式サイト
Ethereal 公式サイト