まだ重たいCMSをお使いですか?
毎秒1000リクエスト を捌く超高速CMS「adiary

2023/08/11(金)Perl DBI と prepare_cached() の罠

Webアプリケーションで、prepare_cached() を使うと色々問題があったのでメモ。

問題あり

prepare_cached() を使用すると、キャッシュヒット時(同じSQL文実行時)に$sthを再生成せずに再利用され、データ取得を含めた実行速度が220usが200usになるぐらいの効果があります。

しかし、prepare_cached() された状態でテーブルのカラムが変更されると問題が起こることが分かりました。

続きを読む

2023/02/02(木)adiary Version3.50 リリース情報

ダウンロードはこちらから

内部的にあちこちいじっているので、普段よりもバグ等出るかもしれません。

Ver3.50 : 2023/02/02

  • Perl 5.14.0以降が必要です。*1
  • 表示以外でのIE11サポートを止めました。
  • Google Analytics 4に対応しました。

細かい変更点

  • mod_rewriteを先に設定したとき、最初のアカウント追加がわかりにくい問題に対応。
  • 日付変更時間処理を除去しました。
  • 「プライベートブログ」かつ「表示パスワードモード」の時、直接ログイン可能にしました。
  • 自分のブログ作成時に標準デザインのロードをオフにできるようにしました。(Thanks to maccoy
  • 【記法】[tel:]タグと、[sms:]タグを追加しました。
  • 【httpd】.gitフォルダへのアクセスを禁止しました。
  • 【httpd】ルートフォルダ内(.httpd.plと同じディレクトリ内)のファイルアクセスを無視するようにしました。
  • 【DB】DB再接続機能を付けました。
  • 【DB】prapere() を prapere_cached() に変更しました。
  • 【Fix】.fcgi(socket mode) + Apache + リバースproxy運用時にうまく動作しない。
  • 【Fix】ツリー表示のノードがずれている。
  • 【Fix】記事編集画面でアップロード詳細ボタンが2回目以降効かない。
  • 【Fix】記事編集時、先頭数字のタイトルからリンクキーを自動設定すると、余計な文字がつく。
  • 【Fix/Theme】nature-forest, nature-sky のドロップダウンメニューの背景が正しくない。
  • 【Fix/MariaDB】テキスト検索がうまく実行できない。
  • 【Fix/Plugin】sitemap.xmlの日付が正しく表示されない。(Thanks to runner
  • 【Base/System】
    • 【Compiler】全面的に書き直し、ブロック処理のバグが修正されました。
    • 【Compiler】break の検出方法を変更して処理を効率化しました。
    • 【Compiler】next, last, break を () なしで書けるようになりました。
    • 【Compiler】正規表現が直接書けるようになりました。
    • 【Compiler】strict modeが実装されました。
    • 【Compiler】forexecをforeachと書けるようにしました。
    • 【Compiler】foreach, ifexec 等の begin を省略できるようにしました。
    • 【Compiler】"++x"や"y--"等の記述を可能にしました。
    • 【構文】call() ファイルが見つからない場合にエラー表示をするようにしました。
    • 【Auth】ユーザ管理まわりを大幅更新しました。
    • 【Auth】ログイン失敗sleep(fail_sleep)機能を削除しました。*2
    • <$Form_options.multipart_data_max_size> オプションを削除しました。
    • CSRF対策機能を除去しました。*3
  • その他(多数)
  • 【Ver3.50a/Fix】OGP/Twitter cardsの表示に記事情報が反映されない。
  • 【Ver3.50b/Fix】calc記法のceilの処理が正しくない。(Thanks to kjimba
  • 【Ver3.50c/Fix】メール通知のタイトルの %n 置換時に余計な「""」が付く。*4
  • 【Ver3.50d/Fix】Perl 5.36 で動かないバグを修正。記事編集画面で、画像タグの置換処理が一部不具合があったので修正。
  • 【Ver3.50e/Fix】フォームの型チェックが誤っていたので修正(Markdownでの不具合あり)。(Thanks to 1484
  • 【Ver3.50f/Fix】アルバムモード設定時、ログインができない。
  • 【Ver3.50g/Fix】PostgreSQL/MySQLモジュールのprepare_cached()をprepare()に修正。(詳細
  • 【Ver3.50h】メール通知プラグインで、投稿者のIP/Hostをメールに記載するようにしました。*5
  • 【Ver3.50i】
    • インポート処理にてWordpress XMLの判定を変更しました。
    • 【Fix】ニコニコ動画タグを追加・修正しました。(Thanks to りこ
    • 【Fix】Markdownのインランコード記法関連のエスケープ処理にバグがある。(Thanks to りこ
    • 【Fix】Markdownで見出し記法に<p>タグを出力してしまう。
  • 【Ver3.50j/Markdown/Fix】Ver3.50iにてMarkdown記法で[*toc]が無効になっていた。*6
  • 【Ver3.50k/Markdown/Fix】リスト記法の入れ子処理が正しくない。(Thanks to りこ
  • 【Ver3.50l】EXIFのOrientationタグ対策にImageMagickのAutoOrientメソッドを使用しました。(Thanks to りこ
  • 【Ver3.50l/Markdown/Fix】Codeブロック中のコメントがあると正しく表示されない。(Thanks to りこ
  • 【Ver3.50m/Markdown】Fenced code blocksの処理を新しいGFM仕様に合わせました。
  • 【Ver3.50n/Markdown/Fix】{ }記号のエスケープ処理を除去しました。(Thanks to りこ

*1 : Perl 5.8では動作しなくなりました。古いPerlを使用しているレンタルサーバの場合、レンタルサーバの設定画面からPerlを最新版に切り替えてください。

*2 : sleepしたところで複数同時ログインを試みればセキュリティ対策として意味がないため。

*3 : Cookieの近年の仕様変更により、IE11以外では問題がなくなったため。

*4 : 反映にはプラグインの再インストールが必要。

*5 : プラグインの再インストールが必要です。

*6 : 必要な行がなぜか消えてる謎のエンバグ……

今後とか

ちょうど3年ぶりのリリースとなりました。Githubの変更ログを見ればわかりますが、3年間少しずつ修正していました。

さすがに設計の古い部分が目立ってきたので、次は全面的に作り直して Version 4 になる予定です。

2022/09/30(金)[CSS] div で aspect-ratio を維持したまま object-fit 的なことがしたい

はてブ数 CSS

画像ファイルは、縦横比を維持して、枠の中で最大サイズに表示することが容易にできます。

object-fit_01.png

<!DOCTYPE html>
<head><style>
body    { padding: 10px; }
#frame1, #frame2 { display: inline-block; border: red 2px solid; }
#frame1 { width: 220px; height: 100px; }
#frame2 { width: 120px; height: 100px; }
img {
	width:		100%;
	height:		100%;
	object-fit:	contain;
}
</style></head>
<body>
<div id="frame1">
	<img src="img320x180.png">
</div>
<div id="frame2">
	<img src="img320x180.png">
</div>
</body>
</html>

これを img タグ画像ではなく div で実現しようとしても、divに対しての「object-fit」指定が無意味のため、うまくいきません。

そこでちょっと工夫して実現してみました。

続きを読む

2020/04/22(水)Chrome/AndroidでVideo/Canvasタグのアスペクト比でハマる

Android の Chrome でカメラから画像取得を試みたところ、縦横比がおかしくなってしまいました。この問題の解決を試みたメモ。

縦画面限定で、画像がおかしくなる

この画像はHTML/JavaScriptを使いスマホで正方形の枠を映したものです。

canvas-SP00.jpg

videoタグに 1600x900 のサイズを指定したあとカメラ画像を取得して、同サイズのcanvasタグに画像をコピー(drawImage())しました。縦に圧縮された横長画像になっています。

これは Chrome 固有の問題ではなく、Chromeのスマホエミュレーションでは何も問題なく表示されます。実機のスマホのChrome(or Firefox)でのみ起こります。色々テストしていると以下のことがわかりました。

  • スマホを横画面にすると正常になる。
  • 取得画像を 1:1 に設定すると正常になる。

テストしていたときは Canvas タグのみ描写していたのですが、videoタグと同時に表示するとこんな感じになりました。

canvas-SP01.jpg

videoソースが縦長?

mediaDevices.getUserMedia() の罠

16:9の画像をこんな感じで取得しようとしていました。

navigator.mediaDevices.getUserMedia({
	audio: false,
	video: {
		width:	1600,
		height:	 900,
		facingMode: "environment"
	}
}).then( (stream) => {

mediaDevices.getUserMediaの説明を隅々まで読むと書いてあるのですが、widthとheightの指定は要望であって強制ではありません

ピッタリとマッチする解像度がカメラ(ビデオソース)に存在しない場合、ブラウザはそれに近い画像サイズを設定します。スマホにおいては、そのサイズが 900x1600 なのです……。

ブラウザにおいて縦画面・横画面という区別はありません。ブラウザの media stream は状況(縦横)に応じてサイズが変化することを想定していないわけです。ですので、スマホのブラウザは縦横設定を無視して近い画像サイズを選定します

このvideoタグの表示領域は(白い部分以外)、論理的には 1600x900 の解像度の持ちますので、その部分を 1600x900 に引き伸ばすと横長縦圧縮画像が出来上がるというわけです。

縦画面、横画面両対応の画像を取得する

横画面専用のWebアプリなんて想定したくはないので、縦横兼用で使うにはどうしたら良いでしょうか? 正解はvideoソースを正方形にしてしまうことです。こうすれば、縦横回転しても、表示領域もサイズも変化がありません。

正方形映像の中から、必要な部分をクロップして canvas に転送すればよいわけです。

少し長くなりますが、以下がソースです。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width">
	<title>Reader test</title>
<style>
video, canvas {
	max-width:	min(480px, 100%);
	display:	block;
	border:		1px solid red;
}
video {
	height:		calc(min(100vw,480px) * 9 / 16);
	margin-bottom:	4px;
}
</style>
</head>
<body>
<video  id="video" muted playsinline></video>
<canvas id="canvas"></canvas>

<script>
const videoWidth  = 1600;
const videoHeight =  900;
const offset      = (videoWidth - videoHeight)/2;

const video  = document.getElementById('video');
video.width  = videoWidth;
video.height = videoWidth;
//video.height = videoHeight;

const canvas  = document.getElementById('canvas');
canvas.width  = videoWidth;
canvas.height = videoHeight;
const ctx     = canvas.getContext("2d")

navigator.mediaDevices.getUserMedia({
	audio: false,
	video: {
		width:	videoWidth,
		height:	videoWidth,
		// height: videoHeight,
      		facingMode: "environment"
	}
}).then( (stream) => {
	video.srcObject = stream;
	video.play();
	video.onloadedmetadata = (e) => {
		video.play();
		console.log(e);
	}
	setInterval(function(){
		// ctx.drawImage(video, 0, 0, videoWidth, videoHeight);
		ctx.drawImage(video,
			0, offset, videoWidth, videoHeight,
			0,      0, videoWidth, videoHeight
		);
	}, 100);
}).catch(function(e) {
	alert(e);
});
</script>
</body>
</html>

コメントアウト部が元々のソース(最初の画像を得たソース)との変化部分です。このソースで実際に画像を取得すると、以下のようになります。

canvas-SP02.jpg

無事、正しいアスペクト比の画像を得られました。*1

*1 : Androidアプリでも、写真撮影モードになるとなぜか正方形表示になるアプリが多くて気になっていたのですが、こういうややこしい問題を避けるためなのかもしれませんね……。

問題点

逆に、PCでは正方形の映像ソースを取れることは少ないようです*2

canvas-PC.jpg

上のように正方形を指定したのに横長のVideoソースになってしまいました……。

	video: {
		width:	{min: videoWidth, max: videoWidth},
		height:	{min: videoWidth, max: videoWidth},
   		facingMode: "environment"
	}

として強制的に正方形ビデオソースを要求すると、そんなの無いから!と怒られて(throw()されて)しまいます……。正方形ビデオソースは、スマホ限定の措置にして、PC等では普通に必要なピクセルサイズを指定するほうが問題は少ないようです。

もう面倒くさすぎるので、対応解像度をリストアップするAPIか、実ソースサイズを教えてくれるAPIを追加してくれないかな……。

*2 : 少なくとも自分の環境では

まとめ

  • スマホで縦横両対応にする場合は、正方形ビデオソースを使用し、canvas転送時にクロップすると良い。
  • ただし、PCでは正方形ビデオソースなんて使えない。

この辺 Mac/iPhone はどうなんでしょう?

2020/02/03(月)adiary Version3.40 リリース情報

ダウンロードはこちらから

Ver3.40の変更点

  • SpeedyCGI用の起動スクリプトを削除しました。
  • mod_perl対応コードを削除しました。
  • adiary.fcgiにUNIX domain socketで利用時の調整をしました。関連して、Nginxで設定が一部変更になっています。
  • 【httpd】パス設定機能を付けました。これにより Reverse Proxy での運用が楽になります。
  • 【httpd】UNIX domain socketモードを追加しました。
  • 【Plugin/webpush】通知送信時のステータスcodeを 201 か確認するようにしました。*1
  • 【Ver3.40a/Fix】リンク集の設定がうまく表示されない。(Thanks to やす
  • 【Ver3.40b/Fix】Perl5.8で2件目の投稿に失敗する。(Thanks to CCC
  • 【Ver3.40c/Fix】AmazonアフィリエイトIDの自動埋め込みが機能していない。
  • 【Ver3.40d】jQueryをVer3.6.2に更新。(Thanks to runner

*1 : 従来は200番台であることのみ確認していました。