mysql のバックアップ

MySQLのバックアップは以前ちょっとだけメモっていたが、今回crontabに登録するためシェルに書き込む。

例:
#!/bin/sh
cd /usr/local/mysql/bin/
date=`date +%Y-%m-%d`
./mysqldump -u root -q testdatabase > /home/user1/db_backup/backup-$date.sql
rmdate=`date –date ’10 day ago’ +%Y-%m-%d`
rmfile=/home/user1/db_backup/backup-$rmdate.sql

if [ -e $rmfile ]; then
rm -f $rmfile
fi

このシェルを毎日実行すると、日付を入れたバックアップファイルを生成し11日目からは古いファイルを削除します。mysqldump の -q はメモリを節約したいため。

尚、復元する時は予めDBを一旦削除して作り直してから
# cd /usr/local/mysql/bin/
# ./mysql -u root testdatabase < /home/user1/db_backup/backup-2006-07-31.sql
とコマンド発行して回復。

参考:MySQL講座 +++[smart]
http://www.rfs.jp/server/mysql/02/07.html

PHP+GDで画像の透過

昨日のようにぬりつぶしだと、指定座標の色が透過用ではなかったり、また他の透過させたい背景のところまで色が連続していなかったりするとまるで使えません。そこで今度は正確なカラーインデックスを取得して割り当てれば大丈夫なのでは?ということで透過処理を下記のコードにいれかえます。

$white = imagecolorexact($backimg, 255, 0, 255);
imagecolortransparent($backimg, $white);

これなら行けるかと思えば前回の強制処理とは違うので画像も選ぶ必要があります。
透過書き出しとしっても種類がありFireworksの場合ではgif/pngともに8bit色インデックス透明カラー(255,0,255)を指定します。

早速やってみたところ、元画像gifの場合は成功しましたがpngで失敗。
ちょっとトレースしてみたら、imagecolorexactでgifの場合必ず-1が返ってきていてimagecolortransparentが役に立ってない。pngでは正の整数が返っているようだが…。

と言うことで上記の透過処理そのものを外すとgif/png共に成功… orz…
全然意味ないどころか障害になってた。

前に同じように透過処理をしないまま合成したときはマットカラー?と思われる色が塗りつぶされていたりしたので全く信頼できない不安定状態です。(多分元画像側でしっかりフォーマットを統一させれば大丈夫と思うが最近のデザイナーはフォーマット知識無いから大変)

PHPとGDのどっちがバグってるのか検討も付かないなー。
今のところ元画像をgifにして書き出しをpng/gifで使い分けるほうが安全かもしれないです。

20060714-1gd_marge

PHP+GDでアバターの着せ替え

最近、仕事でGD使うことが多くなって実はそれを利用してアバターの合成とかやってたりします。
アバターとはYahoo!等に設定されている着せ替え可能なキャラクターのことですね。FLASHやアプリだとパーツごとに渡してあとはFLASH/アプリに任せれば良いのですが、ウェブページの場合は最終的に一枚の画像に合成しないといけないんですね。PHPで合成するなら簡単、透過画像も透過のまま合成できます。但しそのままでは出力時に透過がなくなるので透過を残す場合はちょっと工夫が必要です。

背景と前景の画像ピクセルサイズはが同一の場合のサンプル

// 背景にする画像を読み込み(PNG画像の場合)
$backimg = imagecreatefrompng(‘background.png’);

// 画像サイズの取得
$size = getimagesize(‘background.png’);

// 前景にする画像を読み込み
$frontimg = imagecreatefrompng(‘front.png’);

// 合成処理 ($backimgの上に$frontimgを合成して結果が$frontimg$backimgに上書きされる)
imagecopymerge( $backimg, $frontimg, 0,0,0,0, $size[0], $size[1], 100);

// 背景と前景をあわせても透過部分が残る場合は出力時に透過にするように処理(特殊)
// 透過色を255,0,255に定義
$white = imagecolorallocate( $frontimg$backimg, 255,0,255);
// 先程の設定色を透過色として設定
imagecolortransparent($frontimg$backimg,$white);
// 透過色で塗りつぶしてみる
imagefill($frontimg$backimg,0,0,$white);

// ファイルに書き出しの場合
imagepng($frontimg$backimg,’marge.png’);

// 画像として画面に出力の場合
header(“Content-Type: image/png”);
imagepng($frontimg$backimg);

上記の方法は透過パレット色を指定しない場合で(0,0)の位置が透過対象でない場合失敗します。透過色を統一して指定する場合はimagefillが不要になると思います。その場合imagecolorecact等で取得したインデックスでないと失敗します。(その方法は次回に)

またこの方法ではアニメーションができない。リアルタイムで反映させたりアニメーションさせるのであればJavaScriptになるのかなー?サイト製作はPerl/PHPばかり多くてCSS/JavaScriptには手が回らない。 orz…

追記:2008年12月1日
長らく誤記を放置してました。すみません。途中でマージ後の出力先を勘違いしていた模様です。随分前のエントリーの為透過処理辺りのフォーマットによるルールとか今では記憶が怪しい・・・。

実際に動作するソースは次のエントリーにリンクを張っていますのでこちらも参照お願いします。