GIF_anim.htm

戻る

<!DOCTYPE HTML>
<HTML LANG="ja">

<HEAD>
<META CHARSET="Shift_JIS">
<TITLE>GIF アニメーション</TITLE>
</HEAD>

<BODY STYLE="background-color:#CCFFFF">
<DIV STYLE="text-align:center">
<B>GIF アニメーション</B>
<BR><BR>

<FORM>
<DIV STYLE="position:relative; display:inline-block; text-align:left; white-space:nowrap">
動画ファイル:<BR>
<INPUT TYPE=FILE ID="file" SIZE=60 onChange="sel_file()">
</DIV>
<BR><BR>

<DIV STYLE="position:relative; display:inline-block">
<VIDEO ID="vid" CONTROLS STYLE="position:relative; background-color:black"></VIDEO>
<IFRAME ID="gif" STYLE="position:absolute; left:0; top:0; border:0; visibility:hidden"></IFRAME>
</DIV>
<BR><BR>

<TABLE STYLE="margin-left:auto; margin-right:auto; text-align:left; white-space:nowrap">
<TR><TD>
開始位置:
<INPUT TYPE=TEXT ID="fr_h" SIZE=2 STYLE="text-align:right"> 時間
<INPUT TYPE=TEXT ID="fr_m" SIZE=2 STYLE="text-align:right"> 分
<INPUT TYPE=TEXT ID="fr_s" SIZE=2 STYLE="text-align:right"> 秒
<INPUT TYPE=TEXT ID="fr_ms" SIZE=3 STYLE="text-align:right"> ms
<INPUT TYPE=BUTTON ID="fr_cur" VALUE="現在位置" DISABLED onClick="set_cur(0)" STYLE="padding-left:0.1em; padding-right:0.1em">
</TD></TR>
<TR><TD>
終了位置:
<INPUT TYPE=TEXT ID="to_h" SIZE=2 STYLE="text-align:right"> 時間
<INPUT TYPE=TEXT ID="to_m" SIZE=2 STYLE="text-align:right"> 分
<INPUT TYPE=TEXT ID="to_s" SIZE=2 STYLE="text-align:right"> 秒
<INPUT TYPE=TEXT ID="to_ms" SIZE=3 STYLE="text-align:right"> ms
<INPUT TYPE=BUTTON ID="to_cur" VALUE="現在位置" DISABLED onClick="set_cur(1)" STYLE="padding-left:0.1em; padding-right:0.1em">
</TD></TR>
<TR><TD>
フレーム間隔: <INPUT TYPE=TEXT ID="int" SIZE=4 STYLE="text-align:right"> ×10ms
</TD></TR>
<TR><TD>
ループ再生:
<LABEL><INPUT TYPE=RADIO ID="lp_never" NAME="loop" CHECKED> しない</LABEL>
<LABEL><INPUT TYPE=RADIO NAME="loop" STYLE="margin-left:0.5em"> 無限</LABEL>
<LABEL><INPUT TYPE=RADIO ID="lp_cnt" NAME="loop" STYLE="margin-left:0.5em"> </LABEL><INPUT TYPE=TEXT ID="lp_times" SIZE=4 STYLE="text-align:right"><LABEL FOR="lp_cnt"> 回</LABEL>
</TD></TR>
<TR><TD>
<BR>
<INPUT TYPE=BUTTON ID="cre" VALUE="作成" DISABLED onClick="create_gif()">
<SPAN ID="sts" STYLE="margin-left:1em"></SPAN>
</TD></TR>
<TR><TD>
フレーム: <SPAN ID="frms" STYLE="display:inline-block; min-width:2.5em"></SPAN>
<SPAN STYLE="margin-left:1em">時間:</SPAN> <SPAN ID="time" STYLE="display:inline-block; min-width:8em"></SPAN>
</TD></TR>
<TR><TD>
<BR>
<INPUT TYPE=BUTTON ID="view" VALUE="表示" DISABLED onClick="view_gif()">
<INPUT TYPE=BUTTON ID="cls" VALUE="表示終了" DISABLED onClick="close_gif()" STYLE="margin-left:2em">
<INPUT TYPE=BUTTON ID="save" VALUE="保存" DISABLED onClick="save_gif()" STYLE="margin-left:2em">
</TD></TR>
</TABLE>
</FORM>

</DIV>

<A ID="dl" STYLE="display:none"></A><!--保存処理用-->

<SCRIPT TYPE="text/javascript">
<!--

function sel_file() {
  var file = elem_file.files.item(0);
  if(elem_vid.src != "")
    URL.revokeObjectURL(elem_vid.src);
  elem_vid.src = URL.createObjectURL(file);
  elem_vid.load();
  file_name = file.name;

  close_gif();
  elem_gif.src = "";
  elem_cre.disabled = true;
  elem_sts.textContent = elem_frms.textContent = elem_time.textContent = "";
  elem_view.disabled = true;
  elem_save.disabled = true;
  if(gif_img != undefined) {
    URL.revokeObjectURL(gif_page);
    URL.revokeObjectURL(gif_img);
    gif_img = undefined;
  }
}

function vid_canplay() {
  if(!elem_vid.videoWidth) {
    vid_error();
    return;
  }
  elem_fr_cur.disabled = elem_to_cur.disabled = false;
  elem_cre.disabled = false;
}

function vid_error() {
  frames = undefined;
  elem_file.disabled = false;
  elem_vid.controls = true;
  elem_gif.src = "";
  elem_fr_cur.disabled = elem_to_cur.disabled = true;
  elem_cre.value = "作成";
  elem_sts.textContent = elem_frms.textContent = elem_time.textContent = "";
  elem_view.disabled = true;
  elem_save.disabled = true;
  if(gif_img != undefined) {
    URL.revokeObjectURL(gif_page);
    URL.revokeObjectURL(gif_img);
    gif_img = undefined;
  }

  alert("動画を再生できません。");
}

// 開始位置/終了位置にビデオの現在位置を設定
function set_cur(i) {
  var time = elem_vid.currentTime;
  var int = Math.floor(time);
  elem_ms[i].value = String(Math.floor((time - int) * 1000));
  var rem = int % 60;
  elem_s[i].value = String(rem);
  int = (int - rem) / 60;
  if(int) {
    rem = int % 60;
    elem_m[i].value = String(rem);
    int = (int - rem) / 60;
    elem_h[i].value = (int) ? String(int) : "";
  }
  else {
    elem_h[i].value = elem_m[i].value = "";
  }
}

function lp_times_click() {
  elem_lp_cnt.click();
}

// 作成/中止
function create_gif() {
  if(frames != undefined) {  // 作成中
    cancel = true;
    return;
  }

  var i;

  close_gif();
  elem_file.disabled = true;
  elem_gif.src = "";
  elem_sts.textContent = elem_frms.textContent = elem_time.textContent = "";
  elem_view.disabled = true;
  elem_save.disabled = true;
  if(gif_img != undefined) {
    URL.revokeObjectURL(gif_page);
    URL.revokeObjectURL(gif_img);
    gif_img = undefined;
  }

  // 入力チェック
  var err;

  // 開始位置
  var fr_h, fr_m, fr_s, fr_ms;
  err = true;
  fr_h = elem_h[0].value.trim();
  fr_h = (fr_h == "") ? 0 : (fr_h.search(/^\d+$/) == -1) ? -1 : parseInt(fr_h, 10);
  if(fr_h >= 0) {
    fr_m = elem_m[0].value.trim();
    fr_m = (fr_m == "") ? 0 : (fr_m.search(/^\d+$/) == -1) ? -1 : parseInt(fr_m, 10);
    if(fr_m >= 0 && fr_m < 60) {
      fr_s = elem_s[0].value.trim();
      fr_s = (fr_s == "") ? 0 : (fr_s.search(/^\d+$/) == -1) ? -1 : parseInt(fr_s, 10);
      if(fr_s >= 0 && fr_s < 60) {
        fr_ms = elem_ms[0].value.trim();
        fr_ms = (fr_ms == "") ? 0 : (fr_ms.search(/^\d+$/) == -1) ? -1 : parseInt(fr_ms, 10);
        if(fr_ms >= 0 && fr_ms < 1000)
          err = false;
      }
    }
  }
  if(err) {
    alert("開始位置の入力に誤りがあります。");
    return;
  }

  // 終了位置
  var to_h, to_m, to_s, to_ms;
  err = true;
  to_h = elem_h[1].value.trim();
  to_m = elem_m[1].value.trim();
  to_s = elem_s[1].value.trim();
  to_ms = elem_ms[1].value.trim();
  if(to_h == "" && to_m == "" && to_s == "" && to_ms == "") {  // 入力なし
    to_time = Math.floor(elem_vid.duration * 1000);
  }
  else {
    to_time = undefined;

    to_h = (to_h == "") ? 0 : (to_h.search(/^\d+$/) == -1) ? -1 : parseInt(to_h, 10);
    if(to_h >= 0) {
      to_m = (to_m == "") ? 0 : (to_m.search(/^\d+$/) == -1) ? -1 : parseInt(to_m, 10);
      if(to_m >= 0 && to_m < 60) {
        to_s = (to_s == "") ? 0 : (to_s.search(/^\d+$/) == -1) ? -1 : parseInt(to_s, 10);
        if(to_s >= 0 && to_s < 60) {
          to_ms = (to_ms == "") ? 0 : (to_ms.search(/^\d+$/) == -1) ? -1 : parseInt(to_ms, 10);
          if(to_ms >= 0 && to_ms < 1000)
            err = false;
        }
      }
    }
    if(err) {
      alert("終了位置の入力に誤りがあります。");
      return;
    }
  }

  fr_time = (fr_h * 3600 + fr_m * 60 + fr_s) * 1000 + fr_ms;
  if(fr_time >= elem_vid.duration * 1000) {
    alert("開始位置が動画の長さを超えています。");
    return;
  }
  if(to_time == undefined) {  // 終了位置 入力あり
    to_time = (to_h * 3600 + to_m * 60 + to_s) * 1000 + to_ms;
    if(to_time > elem_vid.duration * 1000) {
      alert("終了位置が動画の長さを超えています。");
      return;
    }
    if(fr_time > to_time) {
      alert("終了位置が開始位置より前です。");
      return;
    }
  }

  // フレーム間隔
  interval = elem_int.value;
  interval = (interval.search(/^\s*\d+\s*$/) == -1) ? 0 : parseInt(interval, 10);
  if(interval <= 0 || interval > 65535) {
    alert("フレーム間隔の入力に誤りがあります。");
    return;
  }

  // ループ回数
  if(elem_lp_cnt.checked) {
    lp_times = elem_lp_times.value;
    lp_times = (lp_times.search(/^\s*\d+\s*$/) == -1) ? 0 : parseInt(lp_times, 10);
    if(lp_times <= 1 || lp_times > 65536) {
      alert("ループ再生の再生回数の入力に誤りがあります。");
      return;
    }
  }

  elem_vid.controls = false;
  elem_vid.pause()
  save_time = elem_vid.currentTime;

  with(elem_work) {
    width  = elem_gif.width  = img_width  = elem_vid.videoWidth;
    height = elem_gif.height = img_height = elem_vid.videoHeight;
    ctx_work = getContext("2d");
  }
  data_len = (img_width * img_height) << 2;

  // GIF データ
  gif_data = [];
  gif_block = new Uint8Array(10000);
  i_gif_block = 0;

  gif_header[I_SCREEN_WIDTH     ] = gif_frame[I_IMAGE_WIDTH     ] = img_width & 0xff;
  gif_header[I_SCREEN_WIDTH  + 1] = gif_frame[I_IMAGE_WIDTH  + 1] = img_width >> 8;
  gif_header[I_SCREEN_HEIGHT    ] = gif_frame[I_IMAGE_HEIGHT    ] = img_height & 0xff;
  gif_header[I_SCREEN_HEIGHT + 1] = gif_frame[I_IMAGE_HEIGHT + 1] = img_height >> 8;
  gif_frame[I_DELAY_TIME    ] = interval & 0xff;
  gif_frame[I_DELAY_TIME + 1] = interval >> 8;

  // Header,Logical Screen Descriptor
  for(i = 0; i < gif_header.length; i++)
    putc(gif_header[i]);

  // ループ再生
  if(!elem_lp_never.checked) {  // ループ再生 あり
    // Application Extension (Loop)
    if(elem_lp_cnt.checked) {  // 回数指定
      var times = lp_times - 1;
      gif_loop[I_LOOP_TIMES    ] = times & 0xff;
      gif_loop[I_LOOP_TIMES + 1] = times >> 8;
    }
    else {  // 無限
      gif_loop[I_LOOP_TIMES] = gif_loop[I_LOOP_TIMES + 1] = 0;
    }
    for(i = 0; i < gif_loop.length; i++)
      putc(gif_loop[i]);
  }

  frames = 0;
  cancel = false;
  elem_cre.value = "中止";
  elem_sts.textContent = "作成中";

  // 最初のフレーム
  elem_vid.currentTime = fr_time / 1000;
}

function vid_seeked() {
  if(frames == undefined)  // 作成中でない
    return;

  if(cancel) {  // 中止
    frames = undefined;
    elem_file.disabled = false;
    elem_vid.currentTime = save_time;
    elem_vid.controls = true;
    elem_cre.value = "作成";
    elem_sts.textContent = elem_frms.textContent = elem_time.textContent = "";
    return;
  }

  elem_frms.textContent = String(++frames);
  var gif_time = frames * interval;
  var time = fr_time + gif_time * 10;
  if(time > to_time) {
    var excess = Math.floor((time - to_time) / 10);
    gif_time -= excess;

    var delay = interval - excess;
    gif_frame[I_DELAY_TIME    ] = delay & 0xff;
    gif_frame[I_DELAY_TIME + 1] = delay >> 8;
  }
  var cs = gif_time % 100;
  var int = (gif_time - cs) / 100;
  var sec = int % 60;
  var min = (int - sec) / 60;
  elem_time.textContent = ((min) ? String(min) + "分 " : "") + String(sec) + "秒 " + String(cs * 10) + "ms";

  // Firefox では,幅/高さを指定しないと正しく描画されない場合がある.
//ctx_work.drawImage(elem_vid, 0, 0);
  ctx_work.drawImage(elem_vid, 0, 0, img_width, img_height);

  create_frame(ctx_work.getImageData(0, 0, img_width, img_height).data);  // フレーム作成

  if(time < to_time) {
    // 次のフレーム
    elem_vid.currentTime = time / 1000;
    return;
  }

  putc(0x3b);  // Trailer

  // GIF データ フラッシュ
  if(i_gif_block)
    gif_data.push(new Uint8Array(gif_block.buffer, 0, i_gif_block));

  gif_img = URL.createObjectURL(new Blob(gif_data, {type:"image/gif"}));
  gif_page = URL.createObjectURL(new Blob(
    ["<HTML><BODY STYLE='margin:0'><IMG SRC='" + gif_img + "'></BODY></HTML>"],
    {type:"text/html;charset=US-ASCII"}));
  new_img = true;

  frames = undefined;
  elem_file.disabled = false;
  elem_vid.currentTime = save_time;
  elem_vid.controls = true;
  elem_cre.value = "作成";
  elem_sts.textContent = "作成完了";
  elem_view.disabled = false;
  elem_save.disabled = false;
}

// フレーム作成
function create_frame(data) {
  reduce_color(data);  // 256色に減色

  var prop;
  var i;

  // Graphic Control Extension,Image Descriptor
  for(i = 0; i < gif_frame.length; i++)
    putc(gif_frame[i]);
  // Local Color Table
  for(i = 0; i < n_colors; i++) {
    putc(colors_r[i]);
    putc(colors_g[i]);
    putc(colors_b[i]);
  }
  // ダミー
  for(i = (256 - i) * 3; i; i--)
    putc(0);

  // LZW Minimum Code Size
  putc(8);  // 8 ビット

  // 辞書ルート
  // 機能的には Map が適しているが,こちらの方が速かった.
  var root_prop = [];
  while(root_prop.length < 256) {
    (prop = []).chara = emp_str;
    root_prop.push(prop);
  }

  var n_code = 258;  // コード登録数
  var code_bits = 9;  // コード ビット数
  var max_n = 512;  // 最大コード登録数
  var dict_code;  // コード
  var dict_prop;  // 辞書情報
  var pack_buff = 0;  // コード パック用バッファ
  var pack_bits = 0;  // コード パック用バッファ格納ビット数
  var block_cnt = 0;  // ブロック バッファ格納バイト数

  put_code(256);  // Clear

  for(var i_data = 0; i_data < data_len; i_data +=4) {
    // 近似色のインデックスを求める
    var r = data[i_data    ];
    var g = data[i_data + 1];
    var b = data[i_data + 2];
    var min = 0x7fffffff;
    var c;
    for(i = 0; i < n_colors; i++) {
      var dr = r - colors_r[i];
      var dg = g - colors_g[i];
      var db = b - colors_b[i];
      var ra = (r << 1) - dr;  // r + colors_r[i]
      var d2 = ((1024 + ra) * (dr * dr)) + ((dg * dg) << 11) + ((1536 - ra) * (db * db));
      if(d2 < min) {
        min = d2;
        c = i;
      }
    }

    if(!i_data) {  // 最初のピクセル
      dict_prop = root_prop[dict_code = c];
      continue;
    }

    var cs = String.fromCharCode(c);
    // 辞書サーチ
    if((i = dict_prop.chara.indexOf(cs)) < 0) {  // 未登録
      put_code(dict_code);

      if(n_code == 4096) {  // 辞書が一杯
        // 辞書クリア
        put_code(256);  // Clear

        for(i = 0; i < 256; i++) {
          prop = root_prop[i];
          prop.chara = emp_str;
          prop.length = 0;
        }
        n_code = 258;
        code_bits = 9;
        max_n = 512;
      }
      else {
        // 辞書に登録
        dict_prop.chara += cs;
        (prop = []).chara = emp_str;
        prop.code = n_code;
        dict_prop.push(prop);
        if(n_code++ == max_n) {
          code_bits++;
          max_n <<= 1;
        }
      }
      dict_prop = root_prop[dict_code = c];
    }
    else {  // 登録済み
      dict_code = (dict_prop = dict_prop[i]).code;
    }
  }

  put_code(dict_code);  // 最後のコード
  put_code(257);  // End of Information
  // コード パック用バッファ フラッシュ
  if(pack_bits)
    put_code(0);

  // ブロック バッファ フラッシュ
  if(block_cnt) {
    putc(block_cnt);
    for(i = 0; i < block_cnt; i++)
      putc(block_buff[i]);
  }

  putc(0x00);  // Block Terminator

  //----------------

  // 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;
    }
  }
}

// 256色に減色
function reduce_color(data) {
  var leaves = 0;  // 葉の数
  var root = new Map();  // ルート ノード
  var internal = {};  // 内部ノード リスト

  for(var i_data = 0; i_data < data_len; i_data += 4) {
    var r = data[i_data    ];
    var g = data[i_data + 1];
    var b = data[i_data + 2];
    var color = (r << 16) | (g << 8) | b;

    // 色追加
    for(var level = 0, node = root; ; level++, node = child) {
      var key = color & (0x808080 >> level);
      var child = node.get(key);
      if(child == undefined) {  // ノードなし
        // ノード追加
        node.set(key, child = new Map());

        if(level == 7) {  // 葉
          child.pixels = 1;
          child.r_sum = r;
          child.g_sum = g;
          child.b_sum = b;

          leaves++;

          while(leaves > 256) {  // 葉の数が 256 より多い
            // 葉を減らす
            for(level = 6; ; level--) {
              if(internal[level] != undefined)
                break;
            }
            node = internal[level];
            internal[level] = node.next;

            var pixels = 0;
            var r_sum = 0;
            var g_sum = 0;
            var b_sum = 0;
            for(child of node.values()) {
              pixels += child.pixels;
              r_sum += child.r_sum;
              g_sum += child.g_sum;
              b_sum += child.b_sum;
            }
            leaves -= node.size - 1;
            node.clear();  // 子ノード リスト クリア

            node.pixels = pixels;
            node.r_sum = r_sum;
            node.g_sum = g_sum;
            node.b_sum = b_sum;
          }

          break;
        }
        else {
          child.next = internal[level];
          internal[level] = child;
        }
      }
      else {
        if(!child.size) {  // 葉
          child.pixels++;
          child.r_sum += r;
          child.g_sum += g;
          child.b_sum += b;

          break;
        }
      }
    }
  }

  // カラー テーブル作成
  var i_color = 0;
  get_colors(root);
  n_colors = leaves;

  //----------------

  // カラー テーブル作成
  function get_colors(node) {
    for(var child of node.values()) {
      if(child.size) {  // 内部ノード
        get_colors(child);
      }
      else {
        colors_r[i_color] = child.r_sum / child.pixels;
        colors_g[i_color] = child.g_sum / child.pixels;
        colors_b[i_color] = child.b_sum / child.pixels;
        i_color++;
      }
      if(i_color == leaves)
        break;
    }
  }
}

// GIF データに 1 バイト出力
function putc(c) {
  gif_block[i_gif_block++] = c;
  if(i_gif_block == 10000) {
    gif_data.push(gif_block);
    gif_block = new Uint8Array(10000);
    i_gif_block = 0;
  }
}

// GIF 表示
function view_gif() {
  elem_vid.pause()
  if(new_img) {
    elem_gif.src = gif_page;

    new_img = false;
  }
  else {
    elem_gif.contentDocument.location.reload();
  }
  elem_gif.style.visibility = "";
  elem_cls.disabled = false;
}

// GIF 表示終了
function close_gif() {
  elem_gif.style.visibility = "hidden";
  elem_cls.disabled = true;
}

// GIF ファイル保存
function save_gif() {
  with(document.getElementById("dl")) {
    var i = file_name.lastIndexOf(".");
    download = ((i <= 0) ? file_name : file_name.substring(0, i)) + ".gif";
    if(href != "")
      URL.revokeObjectURL(href);
    href = URL.createObjectURL(new Blob(gif_data, {type:"application/octet-stream"}));
    click();
  }
}

// 整数 キー入力チェック
function check_int(e) {
  return (e.which < 0x20 || e.which >= 0x30 && e.which <= 0x39 || e.ctrlKey || e.metaKey);
}

//----------------------------------------------------------

  // カラー テーブル
  colors_r = new Uint8Array(256);
  colors_g = new Uint8Array(256);
  colors_b = new Uint8Array(256);

  block_buff = new Uint8Array(255);  // ブロック バッファ

  // Header,Logical Screen Descriptor
  gif_header = [
    0x47, 0x49, 0x46, 0x38, 0x39, 0x61,  // Signature,Version  GIF89a
    0x00, 0x00, 0x00, 0x00,              // Logical Screen Width,Logical Screen Height
    0x77,                                // Global Color Table Flag,Color Resolution,
                                         // Sort Flag,Size of Global Color Table
                                         // 8 ビット,256色
    0x00,                                // Background Color Index
    0x00                                 // Pixel Aspect Ratio
  ];
  I_SCREEN_WIDTH = 6;
  I_SCREEN_HEIGHT = 8;
  // Application Extension (Loop)
  gif_loop = [
    0x21,                                // Extension Introducer
    0xff,                                // Application Label
    0x0b,                                // Block Size
    0x4e, 0x45, 0x54, 0x53, 0x43, 0x41,  // Application Identifier  NETSCAPE
    0x50, 0x45,
    0x32, 0x2e, 0x30,                    // Appl. Authentication Code  2.0
    0x03,                                // Sub-block Data Size
    0x01,                                // Sub-block ID
    0x00, 0x00,                          // Number of Times
    0                                    // Block Terminator
  ];
  I_LOOP_TIMES = 16
  // Graphic Control Extension,Image Descriptor
  gif_frame = [
    0x21,                                // Extension Introducer
    0xf9,                                // Graphic Control Label
    4,                                   // Block Size
    0x04,                                // Disposal Method,User Input Flag,Transparent Color Flag
                                         // Do not dispose
    0x00, 0x00,                          // Delay Time
    0,                                   // Transparent Color Index
    0,                                   // Block Terminator
    0x2c,                                // Image Separator
    0x00, 0x00, 0x00, 0x00,              // Image Left Position,Image Top Position
    0x00, 0x00, 0x00, 0x00,              // Image Width,Image Height
    0x87,                                // Local Color Table Flag,Interlace Flag,
                                         // Sort Flag,Size of Local Color Table
                                         // Local Color Table,256色
  ];
  I_DELAY_TIME = 4;
  I_IMAGE_WIDTH = 13;
  I_IMAGE_HEIGHT = 15;

  elem_file = document.getElementById("file");
  elem_vid = document.getElementById("vid");
  elem_gif = document.getElementById("gif");
  elem_h = [document.getElementById("fr_h"), document.getElementById("to_h")];
  elem_m = [document.getElementById("fr_m"), document.getElementById("to_m")];
  elem_s = [document.getElementById("fr_s"), document.getElementById("to_s")];
  elem_ms = [document.getElementById("fr_ms"), document.getElementById("to_ms")];
  elem_fr_cur = document.getElementById("fr_cur");
  elem_to_cur = document.getElementById("to_cur");
  elem_int = document.getElementById("int");
  elem_lp_never = document.getElementById("lp_never");
  elem_lp_cnt = document.getElementById("lp_cnt");
  elem_lp_times = document.getElementById("lp_times");
  elem_cre = document.getElementById("cre");
  elem_sts = document.getElementById("sts");
  elem_frms = document.getElementById("frms");
  elem_time = document.getElementById("time");
  elem_view = document.getElementById("view");
  elem_cls = document.getElementById("cls");
  elem_save = document.getElementById("save");

  elem_work = document.createElement("CANVAS");

  elem_vid.addEventListener("canplay", vid_canplay, false);
  elem_vid.addEventListener("error", vid_error, false);
  elem_vid.addEventListener("seeked", vid_seeked, false);

  elem_h[0].onkeypress = elem_m[0].onkeypress = elem_s[0].onkeypress = elem_ms[0].onkeypress =
  elem_h[1].onkeypress = elem_m[1].onkeypress = elem_s[1].onkeypress = elem_ms[1].onkeypress
    = check_int;
  elem_int.onkeypress = check_int;
  elem_lp_times.onkeypress = check_int;
  elem_lp_times.onclick = lp_times_click;

  frames = undefined;
  gif_img = undefined
  new_img = false;
  emp_str = "";

  // ページを再ロードしたときのため
  document.forms[0].reset();
  elem_file.disabled = false;
  elem_fr_cur.disabled = elem_to_cur.disabled = true;
  elem_cre.disabled = true;
  elem_view.disabled = true;
  elem_cls.disabled = true;
  elem_save.disabled = true;

//-->
</SCRIPT>

</BODY>

</HTML>