概要
センサやカメラなど、リアルタイムに計測したイメージデータが撮像できるという条件のとき、そのイメージデータをブラウザ上で随時更新する処理を考えるときに、imgタグでは画像が更新されないことに気づき、ちょっと詰まった。
ASP.NETによる対処法のメモを残す。
原因と対応方法
原因を考えていたところ、ブラウザ側でキャッシュが働いていて、画像を一時保存しているため。
主な方法は2つ。両者ともにメリットがあり、設計指針によって決めればよい。
(1) "Display_20210405_130903.png"などととして、キャプチャ画像をリネームして読み込む。
メリット
-
画像をストレージに自動的に確保でき、キャプチャした画像データを常にログとして自動で残し続けることが出来る。
-
時系列データと画像が残っていることから、作業や管理、デバッグがしやすい。
(2) キャッシュを持たない設定にすることで対応する。
メリット
-
ブラウザのキャッシュの影響を考慮せずに、運用が出来る。例えば、メモリ制限があるPCで動かすことを考えて、キャッシュを持つ設定にすると、キャッシュ分だけ画像を残してしまう&そのキャッシュを読み取る処理が発生するので、メモリ効率が悪化してしまい、システム全体でのリアルタイムの動きに影響を与えるかも。
-
アプリの見た目上、原理的には「画像が更新されていない」という状況を防ぐことが出来る。
今回は(2)で対処することを考える。
注意
-
実際にセンサやカメラを使う部分はConfidentialなので、違う画像を使って差し替えます。
-
今のところ、オンラインで動かすことは考えていませんので、urlはローカル設定のものを使っています。ご注意を
ソースコード
(1) Razorページ(View)を以下のように定義
1秒ごとに、サーバサイドにGETリクエストを行ない、画像のみを変更する。
<img src="@Url.Action( "TestLoad", "OPDebug" )" id="OpTestLoadImage" />
@section Scripts{
@Scripts.Render("~/bundles/jqueryval")
<script>
$(function () {
setInterval(
function() {
$('#OpTestLoadImage').attr('src', '@Url.Action("TestLoad", "OPDebug")');
}, 1000);
});
</script>
}
(2) Controllersでコントローラを以下のように定義
using System.Drawing;
using System.Threading.Tasks;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Services;
using OPLocal.ViewModels;
namespace OPLocal.Controllers
{
public class OPDebugController : Controller
{
/* --- 既存ソースコードのため、一部省略 */
public FileContentResult TestLoad()
{
/* 次の行がポイント */
Response.Cache.SetNoStore();
var img = new WebImage(Server.MapPath("..") + @"\display.png");
return new FileContentResult(img.GetBytes(), string.Format("image/{0}", img.ImageFormat));
}
}
}
Response.Cache.SetNoStore();がポイントで、これによって、ブラウザ側がキャッシュを持つのを防いでくれるようになる。
(3) ソリューション直下にdisplay.pngと、"org1.png"、"org2.png"を設定。
カメラから取り込まれたデータが、display.pngとして保存されると想定するが、とりあえずダミーで、リアルタイムのカメラの動きの代わりに、org1.bmpとorg2.bmpのどちらかをリネームして表示できるようにするものとする。
実行結果
以下、他のGET命令によるルーティングを行なわない前提で検証
予想通り動いてくれた。
この後は、リアルタイム処理中は、実際にキャプチャフォルダをローカルに設定し、そのローカルに設定したファイルのうち最新のものを保存する。それを、読み取ることで解決する予定。