ビットマップの動的作成 [JavaScript]
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
画像をクリップボードコピーする [JavaScript]
画像をクリップボードコピーする.js (WSH版)
タイトル通りです。画像をアプリ起動なしで、いきなりクリップボードにコピーするものです。
画像ファイルをドラッグ&ドロップ するだけ。(よく使うならSendToに入れてもいいかも)
シングルクォートとダブルクォートが混じっていますが、PowerShellではダブルクォートはいろいろ変換されてしまます。
引用符規則について - PowerShell Microsoft Docs
https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7.2
そこで PowerShell内でシングルクォートが使えるように、PowerShellのコマンド自体はダブルクォートで囲いました。パス・ファイル名の中のシングルクォートは、シングルクォート2個に置き換え逃げ切っています。
以下をコピーして「画像をクリップボードコピーする.js」というファイル名で保存します。
(長いので切れて見えなくなっててすみません。)
if( WScript.Arguments.Count() === 0 )
{
WScript.createObject( 'WScript.Shell' ).Popup( 'Drag and drop the image file', 5, 'Copy Image File to Clipboard', 48);
WScript.Quit( 1 );
}
WScript.Quit( WScript.createObject( 'WScript.Shell' ).Run( "PowerShell -Command Add-Type -AssemblyName System.Windows.Forms;[Windows.Forms.Clipboard]::SetImage([System.Drawing.Image]::FromFile('" + WScript.Arguments.Item(0).replace("'", "''") + "'));", 0, true ) );