とても久しぶりに、「新館」の方に手を付けてみようという気になった(というか、まったくのほったらかしなのであったが)。で、いろいろ触っているのだが、トップページが殺風景なので、ランダムにサイト内の画像でも表示させてみよう、という気になる。ランダムに画像を選ぶ方法はさておき、最初は選んだ画像を<img>タグのWIDTH属性でサイズ指定していたが、大きな画像だと無意味にダウンロードサイズが大きくなってしまう。そこで、サーバ側でリサイズを行い、それをクライアントに送り返すことを考えた。
リンク:なおさん亭::新館
通常、<img>タグのSRC属性には静的画像へのURLを指定するが、今回はここにASP.NETファイル(.aspx)を指定して、動的に返される画像を表示することにする。このASP.NETファイルは、引数にimageとしてもとの画像ファイルのパス(サーバ内)、sizeとして長い方の辺のピクセル数を指定する。とすると、<img>タグは以下のようになる(SRC属性以外は省略)。
<img src="~/showimage.aspx?image=~/image/xxxx.jpg&size=320">
問題は、showimage.aspxの中身であるが、
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
<script runat="server">
protected void Page_Load(Object sender, EventArgs e){
string filename = Request.QueryString["image"];
filename = Server.MapPath(filename);
Bitmap bmp = new Bitmap(filename);
int w = bmp.Width;
int h = bmp.Height;
int t = Int16.Parse(Request.QueryString["size"]);
if (w > h)
{
h = (h * t) / w;
w = t;
}
else
{
w = (w * t) / h;
h = t;
}
Bitmap newbmp = new Bitmap(w, h, PixelFormat.Format24bppRgb);
Graphics graph = Graphics.FromImage(newbmp);
graph.DrawImage(bmp, 0, 0, w, h);
Response.ContentType = "image/jpeg";
newbmp.Save(Response.OutputStream, ImageFormat.Jpeg);
Response.End();
newbmp.Dispose();
graph.Dispose();
}
</script>
とまぁ、こんな感じである。
キモは、
- 元画像のためのBitmapオブジェクトを用意し、
- 新画像のためのBitmapオブジェクトも用意し、
- 新画像に画像を転写するためのGraphicsオブジェクトも用意し、
- 画像を転写し、HTTP出力ストリームに書き出す。
といった流れになる。元画像のBitmapオブジェクトで直接リサイズできたり、Graphicsオブジェクトなぞ使わずに転写を行いたいところだが、GDI+の構造からこれはできない。だが、できあがった画像にMIMEタイプを指定し、単に書き出せば済むあたりは、フレームワークを使うメリットである。
この方法を使うと、単に拡大、縮小するというほかに、文字を入れたり、画像の調整をしたり、いろいろな加工処理を間に挟むことができるので、応用範囲が広い。難点は、サーバに負荷がかかることで、静的画像を単に送り出すことに比べると比べものにならない。なので、ページ内に何枚も画像がある場合、すべてに使うようなことは避けるべきである。
実際の動きは、「新館」のトップページで確かめて欲しい(単に画像が出るだけだが、画像のパスを見るとASP.NETファイルになっているはずである)。