![]() |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML LANG="ja"> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html;charset=Shift_JIS"> <TITLE>マンデルブロ アート</TITLE> </HEAD> <BODY BGCOLOR="#CCFFFF" onResize="resize()"> <CENTER> <B>マンデルブロ アート (Netscape 4)</B> <BR><BR> <SCRIPT LANGUAGE="JavaScript1.2" TYPE="text/javascript"> <!-- SIZE_X = 300; SIZE_Y = 300; SIZE_X_H = SIZE_X >> 1; SIZE_Y_H = SIZE_Y >> 1; // 現在の GIF イメージ データ(初期値は空白) cur_image_data = "GIF89a\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00" + "\xff\xff\xff\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x01\x4c" + "\x00\x3b\x00\x00\x00\x00\x00"; //--> </SCRIPT> <IMG NAME="img" SRC="javascript:cur_image_data" WIDTH="&{SIZE_X};" HEIGHT="&{SIZE_Y};"> <BR><BR> 現在の表示範囲<BR> <LAYER NAME="range"></LAYER> <TABLE CELLPADDING=0><TR><TD><BR><BR></TD></TR></TABLE> <FORM> パレット <SELECT NAME="pal" onChange="sel_palette()"> <OPTION SELECTED>8 色繰り返し <OPTION>64 色繰り返し 1 <OPTION>64 色繰り返し 2 <OPTION>グレー 256 階調 <OPTION>赤 256 階調 <OPTION>緑 256 階調 <OPTION>青 256 階調 <OPTION>赤 - 緑 - 青 <OPTION>赤 - 青 - 緑 <OPTION>緑 - 青 - 赤 <OPTION>緑 - 赤 - 青 <OPTION>青 - 赤 - 緑 <OPTION>青 - 緑 - 赤 <OPTION>ランダム </SELECT> <BR> </FORM> <TABLE CELLSPACING=0 CELLPADDING=0> <TR><TD ALIGN=LEFT><ILAYER NAME="p_l1" LEFT=-12 VISIBILITY="hide">集合</ILAYER></TD> <TD ALIGN=RIGHT><ILAYER NAME="p_l2" LEFT=12 VISIBILITY="hide">1 回</ILAYER></TD></TR> <TR><TD COLSPAN=2> <ILAYER NAME="p_back" WIDTH=258 HEIGHT=16 CLIP="0,0,258,16"> <SCRIPT LANGUAGE="JavaScript1.2" TYPE="text/javascript"> <!-- for(var i = 0; i < 256; i++) document.write("<LAYER NAME='p", String(i), "' LEFT=", String(1 + i), " TOP=1 WIDTH=1 HEIGHT=14></LAYER>"); //--> </SCRIPT> </ILAYER> </TD></TR> </TABLE> <SCRIPT LANGUAGE="JavaScript1.2" TYPE="text/javascript"> <!-- document.p_l1.visibility = "show"; document.p_l2.visibility = "show"; document.p_back.bgColor = "black"; //--> </SCRIPT> <BR> <FORM> <TABLE> <TR><TD VALIGN=TOP>倍率</TD><TD NOWRAP> <INPUT TYPE=RADIO NAME="factor" CHECKED onClick="sel_factor(0)"> 変更なし <BR> <INPUT TYPE=RADIO NAME="factor" onClick="sel_factor(1)"> 1.5 倍 <INPUT TYPE=RADIO NAME="factor" onClick="sel_factor(2)"> 2 倍 <INPUT TYPE=RADIO NAME="factor" onClick="sel_factor(3)"> 3 倍 <INPUT TYPE=RADIO NAME="factor" onClick="sel_factor(4)"> 4 倍 <INPUT TYPE=RADIO NAME="factor" onClick="sel_factor(5)"> 8 倍 <INPUT TYPE=RADIO NAME="factor" onClick="sel_factor(6)"> 16 倍 <BR> <INPUT TYPE=RADIO NAME="factor" onClick="sel_factor(7)"> 2/3 <INPUT TYPE=RADIO NAME="factor" onClick="sel_factor(8)"> 1/2 <INPUT TYPE=RADIO NAME="factor" onClick="sel_factor(9)"> 1/3 <INPUT TYPE=RADIO NAME="factor" onClick="sel_factor(10)"> 1/4 <INPUT TYPE=RADIO NAME="factor" onClick="sel_factor(11)"> 1/8 <INPUT TYPE=RADIO NAME="factor" onClick="sel_factor(12)"> 1/16 </TD></TR></TABLE> <BR> <INPUT TYPE=BUTTON NAME="reset" VALUE="初期位置・倍率" onClick="reset_para()"> <BR><BR> </FORM> <LAYER NAME="msg1" VISIBILITY="hide"><CENTER>計算中...</CENTER></LAYER> <LAYER NAME="msg2" VISIBILITY="hide"><CENTER>画像作成中...</CENTER></LAYER> <BR> <TABLE CELLSPACING=0 CELLPADDING=0> <TR><TD></TD></TR> <TR><TD> <ILAYER NAME="prog_back" BGCOLOR="black" WIDTH="&{SIZE_Y_H + 2};" HEIGHT=10 CLIP="0,0,&{SIZE_Y_H + 2};,10" VISIBILITY="hide"> <LAYER BGCOLOR="white" LEFT=1 TOP=1 WIDTH="&{SIZE_Y_H};" HEIGHT=8></LAYER> <LAYER NAME="prog" BGCOLOR="lime" LEFT=1 TOP=1 WIDTH=1 HEIGHT=8></LAYER> </ILAYER> </TD></TR> </TABLE> <ILAYER NAME="can_base" VISIBILITY="hide"> <FORM> <INPUT TYPE=BUTTON NAME="can" VALUE="中止" onClick="cancel = true"> <BR> </FORM> </ILAYER> </CENTER> <SCRIPT LANGUAGE="JavaScript1.2" TYPE="text/javascript"> <!-- // 画像クリック function clicked(e) { var x = e.pageX - document.img.x; var y = e.pageY - document.img.y; if(x < 0 || x >= SIZE_X || y < 0 || y >= SIZE_Y) return; if(input_disabled || !cur_image_data.length) // 入力ディスエーブル or イメージ未作成 return; var w_ratio = ratio; switch(cur_i_factor) { case 1: // x 1.5 w_ratio /= 1.5; break; case 2: // x 2 w_ratio /= 2; break; case 3: // x 3 w_ratio /= 3; break; case 4: // x 4 w_ratio /= 4; break; case 5: // x 8 w_ratio /= 8; break; case 6: // x 16 w_ratio /= 16; break; case 7: // 2/3 w_ratio *= 1.5; break; case 8: // 1/2 w_ratio *= 2; break; case 9: // 1/3 w_ratio *= 3; break; case 10: // 1/4 w_ratio *= 4; break; case 11: // 1/8 w_ratio *= 8; break; case 12: // 1/16 w_ratio *= 16; break; } if(w_ratio == 0) { alert("倍率が大きくなりすぎます"); return; } if(!isFinite(w_ratio)) { alert("倍率が小さくなりすぎます"); return; } var w_center_r = center_r + (x - SIZE_X_H) * ratio; var w_center_i = center_i + (y - SIZE_Y_H) * ratio; if(w_center_r - w_ratio == w_center_r || w_center_i - w_ratio == w_center_i || w_center_r + w_ratio == w_center_r || w_center_i + w_ratio == w_center_i // 桁落ち? || !isFinite(w_center_r - SIZE_X_H * w_ratio) || !isFinite(w_center_i - SIZE_Y_H * w_ratio) || !isFinite(w_center_r + SIZE_X_H * w_ratio) || !isFinite(w_center_i + SIZE_Y_H * w_ratio)) { alert("計算できません"); return; } center_r = w_center_r; center_i = w_center_i; ratio = w_ratio; document.forms[1].factor[0].checked = true; // x 1 に戻す cur_i_factor = 0; mandelbrot(); } function isFinite(num) { return !(num == Number.POSITIVE_INFINITY || num == Number.NEGATIVE_INFINITY); } // 初期位置・倍率 function reset_para() { if(input_disabled) // 入力ディスエーブル return; center_r = center_i = 0.0; ratio = 0.01; document.forms[1].factor[0].checked = true; // x 1 に戻す cur_i_factor = 0; mandelbrot(); } // マンデルブロ集合作成 function mandelbrot() { input_disabled = true; document.msg1.visibility = "show"; document.prog_back.document.prog.clip.right = 0; document.prog_back.visibility = "show"; document.can_base.visibility = "show"; cancel = false; setTimeout("mandelbrot1(0)", 0); } function mandelbrot1(y) { if(cancel) { end_proc(); return; } var b = center_i + (y - SIZE_Y_H) * ratio; for(var x = 0; x < SIZE_X; x++) { var a = center_r + (x - SIZE_X_H) * ratio; var zr, zi; var zr2, zi2; zr = zi = zr2 = zi2 = 0.0; var cnt; for(cnt = 255; cnt; cnt--) { zi = 2 * zr * zi + b; zr = zr2 - zi2 + a; if((zr2 = zr * zr) + (zi2 = zi * zi) > 4) break; } pixels[y][x] = cnt; } y++; if(!(y & 0x1)) document.prog_back.document.prog.clip.right = y >> 1; if(y == SIZE_Y) { if(cancel) { end_proc(); return; } setTimeout("create_image()", 0); } else { setTimeout("mandelbrot1(" + String(y) + ")", 0); } } function create_image() { image_data = ""; // Header,Logical Screen Descriptor,Global Color Table,Image Descriptor // と LZW Minimum Code Size var i; for(i = 0; i < header1.length; i++) putc(header1[i]); for(i = 0; i < 256; i++) { with(cur_palette[i]) { putc(r); putc(g); putc(b); } } for(i = 0; i < header2.length; i++) putc(header2[i]); block_cnt = 0; pack_buff = 0; pack_bits = 0; code_bits = 9; max_n = 512; n_code = 258; put_code(256); // Clear code = pixels[0][0]; prop = root_prop[code]; document.msg1.visibility = "hide"; document.msg2.visibility = "show"; document.prog_back.document.prog.clip.right = 0; setTimeout("create_image1(0, 1)", 0); } function create_image1(y, x) { if(cancel) { end_proc(); return; } while(x < SIZE_X) { // 次の 1 ピクセル var c = pixels[y][x++]; var cs = String.fromCharCode(c); // 辞書サーチ var i = -1; if(prop.chara) i = prop.chara.indexOf(cs); if(i == -1) { // 未登録 put_code(code); if(n_code == 4095) { // 辞書が一杯(のひとつ前) // 辞書クリア put_code(256); // Clear for(i = 0; i < 256; i++) { delete root_prop[i].chara; delete root_prop[i].prop; } n_code = 258; code_bits = 9; max_n = 512; } else { // 辞書に登録 if(prop.chara) { prop.chara += cs; prop.prop.push({code:n_code}); } else { prop.chara = cs; prop.prop = [{code:n_code}]; } if(n_code++ == max_n) { code_bits++; max_n <<= 1; } } code = c; prop = root_prop[c]; } else { // 登録済み code = prop.prop[i].code; prop = prop.prop[i]; } } y++; if(!(y & 0x1)) document.prog_back.document.prog.clip.right = y >> 1; if(y == SIZE_Y) setTimeout("create_image2()", 0); else setTimeout("create_image1(" + String(y) + ", 0)", 0); } function create_image2() { put_code(code); // 最後のコード put_code(257); // End of Information // コード パック用バッファ フラッシュ if(pack_bits) put_code(0); // ブロック バッファ フラッシュ if(block_cnt) { putc(block_cnt); for(var i = 0; i < block_cnt; i++) putc(block_buff[i]); } putc(0x00); // Block Terminator putc(0x3b); // Trailer // イメージ表示 cur_image_data = image_data; document.img.src = document.img.src; // 表示を更新 // 表示範囲 var str1 = range_num(center_i - SIZE_Y_H * ratio); if(str1.charAt(0) != "-") str1 = "+" + str1; str1 = range_num(center_r - SIZE_X_H * ratio) + str1 + "i"; var str2 = range_num(center_i + SIZE_Y_H * ratio); if(str2.charAt(0) != "-") str2 = "+" + str2; str2 = range_num(center_r + SIZE_X_H * ratio) + str2 + "i"; document.range.document.open(); document.range.document.write( "<CENTER><TABLE CELLPADDING=0><TR><TD NOWRAP>", str1, "<BR> 〜 ", str2, "<BR></TD></TR></TABLE></CENTER>"); document.range.document.close(); end_proc(); } // 表示範囲の数値をフォーマット function range_num(num) { var str = String(num).split("e"); if(str[0].charAt(0) == ".") str[0] = "0" + str[0]; else if(str[0].substr(0, 2) == "-.") str[0] = "-0" + str[0].substr(1); if(str.length == 1) return str[0]; return str[0] + "×10<SUP>" + str[1].replace(/\+/, "") + "</SUP>"; } // LZW コード出力 function put_code(code) { pack_buff |= code << pack_bits; pack_bits += code_bits; while(pack_bits >= 8) { block_buff[block_cnt++] = pack_buff & 0xff; if(block_cnt == 255) { putc(255); for(var i = 0; i < 255; i++) putc(block_buff[i]); block_cnt = 0; } pack_buff >>= 8; pack_bits -= 8; } } // イメージ データに 1 バイト出力 function putc(c) { image_data += String.fromCharCode(c); } // マンデルブロ集合作成終了 function end_proc() { // 辞書ルートを初期状態に戻す for(var i = 0; i < 256; i++) { delete root_prop[i].chara; delete root_prop[i].prop; } document.msg1.visibility = "hide"; document.msg2.visibility = "hide"; document.prog_back.visibility = "hide"; document.can_base.visibility = "hide"; input_disabled = false; } // パレット選択 function sel_palette() { var i; if(input_disabled) { // 入力ディスエーブル document.forms[0].pal.selectedIndex = cur_i_pal; return; } cur_i_pal = document.forms[0].pal.selectedIndex; if(cur_i_pal == 13) { // ランダム for(i = 0; i < 256; i++) { var v = Math.floor(Math.random() * 0x1000000); palette[13][i] = {r:v >> 16, g:(v >> 8) & 0xff, b:v & 0xff}; } } set_palette(); if(cur_image_data.length < 256) // イメージ未作成 return; // GIF イメージのカラー テーブルのみを書き換える. image_data = ""; for(i = 0; i < 256; i++) { with(cur_palette[i]) { putc(r); putc(g); putc(b); } } cur_image_data = cur_image_data.substr(0, header1.length) + image_data + cur_image_data.substr(header1.length + 256 * 3); document.img.src = document.img.src; // 表示を更新 } // パレット設定 function set_palette() { cur_palette = palette[cur_i_pal]; for(var i = 0; i < 256; i++) { with(cur_palette[i]) { document.p_back.document.layers["p" + String(i)].bgColor = ("0" + r.toString(16)).substr(-2) + ("0" + g.toString(16)).substr(-2) + ("0" + b.toString(16)).substr(-2); } } } // 倍率選択 function sel_factor(i_factor) { if(input_disabled) { // 入力ディスエーブル document.forms[1].factor[cur_i_factor].checked = true; return; } cur_i_factor = i_factor; } function resize() { // リサイズしたときレイヤー関係の表示が崩れる現象の対策 document.p_back.left = 0 for(var i = 0; i < 256; i++) { with(cur_palette[i]) { document.p_back.document.layers["p" + String(i)].bgColor = ("0" + r.toString(16)).substr(-2) + ("0" + g.toString(16)).substr(-2) + ("0" + b.toString(16)).substr(-2); } } } //---------------------------------------------------------- center_r = center_i = 0.0; // 表示中心値 ratio = 0.01; // 1 ピクセルの大きさ // イメージ配列 pixels = new Array(); pixels.length = SIZE_Y; for(i = 0; i < SIZE_Y; i++) { pixels[i] = new Array(); pixels[i].length = SIZE_X; } // Header,Logical Screen Descriptor header1 = [ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, // GIF89a SIZE_X & 0xff, SIZE_X >> 8, SIZE_Y & 0xff, SIZE_Y >> 8, 0xf7, // Global Color Table,256色 0x00, // Background Color Index 0x00 // Pixel Aspect Ratio ]; // Image Descriptor と LZW Minimum Code Size header2 = [ 0x2c, // Image Separator 0x00, 0x00, 0x00, 0x00, // 0,0 SIZE_X & 0xff, SIZE_X >> 8, SIZE_Y & 0xff, SIZE_Y >> 8, 0x00, 8 // 8 ビット ]; // 辞書ルート root_prop = new Array(); root_prop.length = 256; for(i = 0; i < 256; i++) root_prop[i] = {}; var n_code; // コード登録数 var code_bits; // コード ビット数 var max_n; // 最大コード登録数 var code; // コード var prop; // 辞書情報 var pack_buff; // コード パック用バッファ var pack_bits; // コード パック用バッファ格納ビット数 block_buff = new Array(); // ブロック バッファ block_buff.length = 255; var block_cnt; // ブロック バッファ格納バイト数 var image_data; // GIF イメージ データ var cancel; // 中止フラグ input_disabled = true; // 入力ディスエーブル フラグ // 各種パレット作成 palette = new Array(); palette.length = 14; for(i = 0; i < 14; i++) { palette[i] = new Array(); palette[i].length = 256; } for(i = 0; i < 256; i++) { palette[0][i] = {r:(i & 0x1) ? 255 : 0, g:(i & 0x2) ? 255 : 0, b:(i & 0x4) ? 255 : 0}; palette[1][i] = {r:(i & 0x03) * 85, g:((i & 0x0c) >> 2) * 85, b:((i & 0x30) >> 4) * 85}; palette[2][i] = {r:( i & 0x01 | ((i & 0x08) >> 2)) * 85, g:(((i & 0x02) >> 1) | ((i & 0x10) >> 3)) * 85, b:(((i & 0x04) >> 2) | ((i & 0x20) >> 4)) * 85}; palette[3][i] = {r:i, g:i, b:i}; palette[4][i] = {r:i, g:0, b:0}; palette[5][i] = {r:0, g:i, b:0}; palette[6][i] = {r:0, g:0, b:i}; } for(i = 0; i < 64; i++) { var v = Math.round(i * 255 / 63); palette[7 ][i ] = {r:255, g:v, b:0}; palette[7 ][127 - i] = {r:v, g:255, b:0}; palette[7 ][128 + i] = {r:0, g:255, b:v}; palette[7 ][255 - i] = {r:0, g:v, b:255}; palette[8 ][i ] = {r:255, g:0, b:v}; palette[8 ][127 - i] = {r:v, g:0, b:255}; palette[8 ][128 + i] = {r:0, g:v, b:255}; palette[8 ][255 - i] = {r:0, g:255, b:v}; palette[9 ][i ] = {r:0, g:255, b:v}; palette[9 ][127 - i] = {r:0, g:v, b:255}; palette[9 ][128 + i] = {r:v, g:0, b:255}; palette[9 ][255 - i] = {r:255, g:0, b:v}; palette[10][i ] = {r:v, g:255, b:0}; palette[10][127 - i] = {r:255, g:v, b:0}; palette[10][128 + i] = {r:255, g:0, b:v}; palette[10][255 - i] = {r:v, g:0, b:255}; palette[11][i ] = {r:v, g:0, b:255}; palette[11][127 - i] = {r:255, g:0, b:v}; palette[11][128 + i] = {r:255, g:v, b:0}; palette[11][255 - i] = {r:v, g:255, b:0}; palette[12][i ] = {r:0, g:v, b:255}; palette[12][127 - i] = {r:0, g:255, b:v}; palette[12][128 + i] = {r:v, g:255, b:0}; palette[12][255 - i] = {r:255, g:v, b:0}; } // 初期パレット設定 cur_i_pal = 0; set_palette(); cur_i_factor = 0; // ページを再ロードしたときコントロールの表示が初期化されない現象の対策 document.forms[0].pal.selectedIndex = 0; document.forms[1].factor[0].checked = true; captureEvents(Event.MOUSEDOWN); onmousedown = clicked; // 初期表示 mandelbrot(); //--> </SCRIPT> </BODY> </HTML> |