ナビゲーション リンクのスキップホーム > そのまま使えるシリーズ > そのまま使えるランダム画像

そのまま使えるランダム画像

このページは、2017年8月9日現在の情報に基づいて掲載しております。
情報の信頼性は、法令の改正や温暖化の進行具合、摂取したコラーゲンの量、ムカデがどの足から歩き出したか等の様々な事象の影響を受け、日々刻々と常に変化しております。

背景色:
図形:
色1:
色2:
幅:
高さ:
図形の大きさ:
出現率: %

上記のパラメータに沿って、ランダムに画像を生成しています。
画像を右クリックのうえ「名前を付けて画像を保存」を選択して、画像を保存してください(Internet Exprolerの場合)。
生成された画像と全く同じ画像が再び生成される保証はありませんのでご注意ください。
生成された画像は、みなさまご自身の判断と責任において、ご自由にご活用ください。

パターンのないタイル(つまりランダム)

地下鉄駅の壁面を見ていたら、思いついてしまったWebツールです。
図形の形や大きさ、出現率などを変えてみると、いろいろなものに見えてくると思います。

構想を練りながらポチポチしたり、暇つぶしにポチポチしたり・・・。
偶然できた画像を壁紙にしてみたりしてもいいかもですね。

ASP.NETで画像を描くには

やっぱりそこはWebですので、Windowsフォームアプリのようにイメージ領域さえ配置すれば・・・とはいかないようです。
具体的には、イメージ領域を配置したWebフォーム(このページ)と、画像を描いて出力するページとを用意し、画像を出力するページに何らかの方法でパラメータを渡して・・・という具合に、少し手間暇が増えます。

ここではQueryStringによってパラメータを渡しています。Sessionを使うほどクリティカルなパラメータではないことや、QueryStringだろうがSessionだろうが受け取ったパラメータの値を精査するコードを書くことには変わりはない、などが理由です。

画像を描いて出力するページのPageディレクティブは、次のとおりです。

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="hogehoge.aspx.cs" Inherits="hogehoge" ContentType="image/png" %>
そのうえで、次のような感じで、バイナリをResponse.OutputStreamに流せばOKということになります。
protected void Page_Load(object sender, EventArgs e)
{
    var __width = 640;
    var __height = 384;

    using (var __bitmap = new System.Drawing.Bitmap(__width, __height))
    {
        ・
        ・
        ・
        ・

        __bitmap.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Png);
    }
}

ランダムといえばやっぱり乱数

.NETには、ざっくりと言うと、「とりあえず乱数を生成するクラス」と、「より厳密な乱数を生成するクラス」が用意されております。
具体的には、System.Randomクラスと、System.Security.Cryptography.RNGCryptoServiceProviderクラスです。

ここでは、それほど厳密な乱数は必要ないので、System.Randomクラスを使用しています。
System.Randomクラスは、シード値を指定するコンストラクタと、指定しないコンストラクタが用意されております。
シード値を指定しない場合には、Environment.TickCount(システム起動後のミリ秒単位の経過時間)がシード値として使用されます。
System.Randomクラスは、シード値が同じであれば全く同じ乱数(乱数と言ってよいかは不明)を返しますので、一回の処理の中で複数回使用する場合にはシード値を変える必要があるかと思います。
次のような具合にシード値を指定すると、手っ取り早いです。

var __seed = Environment.TickCount;
var __rnd1 = System.Random(__seed++);
var __rnd2 = System.Random(__seed++);

また、乱数を連続して生成する場面では、同じ数字を何度も生成してよい場合と、一度しか生成したくない場合とがあります。
System.Randomクラスは、同じ数字を何度も生成しますので、同じ数字を一度しか生成したくない場合は、System.Collections.Generic.Listクラスなどの配列を用いるとよいです。
そしてたぶん、次の関数をコピペして使っていただく方法が、最も手っ取り早い方法になるのかなと。

static int[] __GetRandomNumbers(int _minValue, int _maxValue, int _numbers, int _seed)
{
    return __GetRandomNumbers(_minValue, _maxValue, _numbers, _seed, true);
}
static int[] __GetRandomNumbers(int _minValue, int _maxValue, int _numbers, int _seed, bool _repeat)
{
    if(_maxValue < _minValue)
    {
        var __temp = _maxValue;
        _maxValue = _minValue;
        _minValue = __temp;
    }

    if (!_repeat && _numbers > _maxValue - _minValue + 1)
        _numbers = _maxValue - _minValue + 1;

    var __ret = new int[_numbers];
    var __rng = new System.Random(_seed);

    if (_repeat)
    {
        for (var i = 0; i < __ret.Length; i++)
            __ret[i] = __rng.Next(_minValue, _maxValue);
    }
    else
    {
        var __mother = new System.Collections.Generic.List<int>();
        for (var i = _minValue; i <= _maxValue; i++)
            __mother.Add(i);

        for (var i = 0; i < __ret.Length; i++)
        {
            var __index = __rng.Next(0, __mother.Count);
            __ret[i] = __mother[__index];
            __mother.RemoveAt(__index);
        }
    }

    return __ret;
}
_repeatにtrueを渡すと同じ数字を何度も生成する乱数になり、falseを渡すと同じ数字を一度しか生成しない乱数になります。

なお、発生したい乱数の範囲が狭い場合(例えば、0か1かを繰り返し発生させる場合など)に、発生する数字が著しく偏るようです(何度やっても0ばかり出る、みたいな・・・)。
範囲が狭いときには、乱数としては幅広く(0~99とか)発生させておきつつ、剰余を取って目的の範囲に収めてあげると、うまくいきました。

QueryStringを含むURLを簡単に生成するには

今回、パラメータを渡す方法としてQueryStringを採用したわけですが、URLに続けて「?hoge=fuga&aaa=bbb」といった文字列を生成するのって、エンコードとかいろいろ神経を使うものです。
そんな悩みを一発で解決する方法が、ASP.NETに用意されております。

var __query = System.Web.HttpUtility.ParseQueryString(string.Empty);

__query["hoge"] = "hoge";
__query["fuga"] = "fuga";
__query["aaa"] = "bbb";
__query["hensu_x"] = x;
__query["hensu_y"] = y;

var __urlWithQueryString = "test.aspx?" + __query.ToString();
という、嘘のようなホントの話です。

最後に、一度訪問したURLを指定するとWebブラウザはキャッシュを読みにいきますので、可変画像なのに変わらない!という事態に直面することになります。
URLの中に、たとえば、DateTime.Now.Ticks.ToString()を含めておくとよいでしょう。

星の描画方法を変えました

星の描き方を変えました。
詳しくは「そのまま使える多角形」をご参照ください。

本サイトは、下記のサイトポリシーに同意いただいたうえでご利用ください。

サイトポリシー | お問い合わせ | 運営会社(株式会社GAIDE)

Copyright © 2016 GAIDE CO., LTD. All rights reserved.