SSブログ

ビットマップの動的作成 [JavaScript]

createbmp.png
canvas 使えば!?っていうことなんですけど。

・ビットマップをバイナリーファイルの配列として作る
・ファイルイメージ上で画像を編集
・Base64でエンコードしてテキストとしてソースを指定

というゴリゴリした処理で canvas を使うことなく画像を表示します。
ネットで拾った情報をアレンジして何とか形にしたものです。
JavaScriptのオブジェクトとか、よくわかってないので間違ってたらすみません。
HTA形式なら、ファイル保存もできます。
ソースは長いですが、フルカラー24bitとモノクロ1bitの2つと、base64エンコードと、HTA用ファイル保存などの組み合わせだけで、やってることは単純です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ビットマップの動的作成 Dynamic creation of bitmap</title>
<script>
var Bitmap = function() {       // full color (24bit)
    // Property
    this.width     = 0;
    this.height    = 0;
    this.lineBytes = 0;
    this.fileData  = [ 66,77, 54,0,0,0, 0,0, 0,0, 54,0,0,0,     // Bitmap File Header (14 bytes)
                       40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0, 0,0,0,0, 0,0,0,0,
                        0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];    // Information Header (40 bytes)
    // Method
    this.setSize = function(w, h) {
        this.width     = w;
        this.height    = h;
        this.lineBytes = ((w * 3 + 3) >> 2) << 2;
        setArrayLong( this.fileData,  2, 54 + this.lineBytes * h );
        setArrayLong( this.fileData, 18, w );
        setArrayLong( this.fileData, 22, h );
        this.fileData.length = 54 + this.lineBytes * h;
    } 
    this.setPixel = function(x, y, r, g, b) {
        var index = (this.height - y - 1) * this.lineBytes  +  x * 3;
        this.fileData[ index + 54 ] = b;
        this.fileData[ index + 55 ] = g;
        this.fileData[ index + 56 ] = r;
    }
    this.fillRect = function(x1, y1, x2, y2, r, g, b) {
        for(var x=x1; x<=x2; x++) for(var y=y1; y<=y2; y++) this.setPixel(x, y, r, g, b);
    }
    // Local Scope Function
    function setArrayLong(arr, index, num) {
        for(var i=0; i<4; i++)  arr[index + i] = ( num >> ( i * 8 ) ) & 0xff;
    }
}

var BitmapMono = function() {   // 2color monochrome (1bit)
    // Property
    this.width     = 0;
    this.height    = 0;
    this.lineBytes = 0;
    this.fileData  = [ 66,77, 62,0,0,0, 0,0, 0,0, 62,0,0,0,     // Bitmap File Header (14 bytes)
                       40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 1,0, 0,0,0,0, 0,0,0,0,
                        0,0,0,0, 0,0,0,0, 2,0,0,0, 0,0,0,0,     // Information Header (40 bytes)
                       255,255,255,0,  0,0,0,0 ];               // Color palette       (8 bytes)
    // Method
    this.setSize = function(w, h) {
        this.width     = w;
        this.height    = h;
        this.lineBytes = ((w + 31) >> 5) << 2;
        setArrayLong( this.fileData,  2, 62 + this.lineBytes * h );
        setArrayLong( this.fileData, 18, w );
        setArrayLong( this.fileData, 22, h );
        this.fileData.length = 62 + this.lineBytes * h;
    } 
    this.setPixel = function(x, y, pal) {
        var index = (this.height - y - 1) * this.lineBytes  + (x >> 3);
        if( pal ) this.fileData[ index + 62 ] |=  (128 >> (x % 8)); // 128 = 0b10000000
        else      this.fileData[ index + 62 ] &= ~(128 >> (x % 8));
    }
    this.fillRect = function(x1, y1, x2, y2, pal) {
        for(var x=x1; x<=x2; x++) for(var y=y1; y<=y2; y++) this.setPixel(x, y, pal);
    }
    // Local Scope Function
    function setArrayLong(arr, index, num) {
        for(var i=0; i<4; i++)  arr[index + i] = ( num >> ( i * 8 ) ) & 0xff;
    }
}

function saveFile( bytes, filename ) {  // File writing (* Only for HTA)
    var stream = new ActiveXObject('ADODB.Stream'); 
    stream.Type = 2;                // 1:adTypeBinary  2:adTypeText
    stream.Charset = 'iso-8859-1';  // To get as a byte type array
    stream.Open();
    for(var i=0; i<bytes.length; i++) stream.WriteText( String.fromCharCode( bytes[i] ) );
    stream.SaveToFile( filename, 2 );
    stream.Close();
}

function encodeBase64( bytes ) {        // Encode to Base64
    var i, len, table = [], base64 = '';
    for (i=65; i< 91; i++)  table.push(String.fromCharCode(i));
    for (i=97; i<123; i++)  table.push(String.fromCharCode(i));
    for (i= 0; i< 10; i++)  table.push(i.toString(10));
    table.push('+');
    table.push('/');
    for (i=0, len=bytes.length; i<len-2; i+=3) {
        base64 += table[  (bytes[i]   & 0xfc) >> 2  ];
        base64 += table[ ((bytes[i]   & 0x03) << 4) | ((bytes[i+1] & 0xf0) >> 4) ];
        base64 += table[ ((bytes[i+1] & 0x0f) << 2) | ((bytes[i+2] & 0xc0) >> 6) ];
        base64 += table[   bytes[i+2] & 0x3f        ];
    }
    if (len === i+1) {          // last 1 byte
        base64 += table[  (bytes[i]   & 0xfc) >> 2  ];
        base64 += table[ ((bytes[i]   & 0x03) << 4) ] + '==';
    }else if (len === i+2) {    // last 2 bytes
        base64 += table[  (bytes[i]   & 0xfc) >> 2  ];
        base64 += table[ ((bytes[i]   & 0x03) << 4) | ((bytes[i+1] & 0xf0) >> 4) ];
        base64 += table[ ((bytes[i+1] & 0x0f) << 2) ] + '=';
    }
    return base64;
}

function main() {
    var bmp1 = new BitmapMono();
    var bmp2 = new Bitmap();
    bmp1.setSize( 32, 32);
    for(var i=0; i<32; i++)  bmp1.setPixel( i, i, 1);
    document.getElementById('bmp').innerHTML  = '<img src="data:image/bmp;base64,'+ encodeBase64( bmp1.fileData ) + '" >';
    bmp2.setSize( 32, 32);
    for(var i=0; i<32; i++)  bmp2.setPixel( i, i, i*8, 255-i*8, 0);
    document.getElementById('bmp').innerHTML += '<img src="data:image/bmp;base64,'+ encodeBase64( bmp2.fileData ) + '" >';
    // * Can be saved for HTA
    // saveFile(bmp1.fileData, 'test1.bmp');
    // saveFile(bmp2.fileData, 'test2.bmp');
}
</script>
</head>
<body>
<h1>ビットマップの動的作成</h1>
<p>
<ul>
  <li>ビットマップをバイナリーファイルの配列として作る
  <li>ファイルイメージ上で画像を編集
  <li>Base64でエンコードしてテキストとしてソースを指定
</ul>
<p><button onclick="main()">create Bitmap</button>
<p id="bmp"></p>
</body>
</html>

タグ:HTA
nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。