<!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>Exif ビューア</TITLE>
</HEAD>
<BODY BGCOLOR="#CCFFFF" onResize="resize()">
<CENTER ID="back">
<B>Exif ビューア (Firefox 3)</B>
<BR>
<FORM onSubmit="return false">
<DIV STYLE="margin:2px">ファイル(Exif): <INPUT TYPE=FILE ID="file" SIZE=60 onChange="read()"></DIV>
<DIV ID="cont" STYLE="position:relative">
<DIV ID="img_win" STYLE="position:absolute; left:0; top:0; background-color:gray; overflow:auto">
<CANVAS ID="img" WIDTH=1 HEIGHT=1 STYLE="position:absolute; left:0; top:0; visibility:hidden"></CANVAS>
</DIV>
<TABLE ID="size" STYLE="position:absolute; left:0; margin-top:2px"><TR>
<TD VALIGN=TOP NOWRAP>表示サイズ:</TD>
<TD WIDTH=2></TD>
<TD NOWRAP>
<INPUT TYPE=RADIO NAME="scale" ID="fit" CHECKED onClick="scale_fit()"> 表示領域に合わせる<BR>
<INPUT TYPE=RADIO NAME="scale" ID="org" onClick="scale_org()"> 原寸<BR>
<INPUT TYPE=RADIO NAME="scale" ID="shr" onClick="scale_shr()"> 指定した割合で縮小
<INPUT TYPE=TEXT ID="cur_fact" READONLY VALUE="50" SIZE=5 STYLE="border:none; background-color:transparent; font-size:medium; text-align:right">%
<SPAN STYLE="white-space:pre"> </SPAN><INPUT TYPE=BUTTON VALUE="← 設定" onClick="set_factor()" STYLE="padding-left:0; padding-right:0">
<INPUT TYPE=TEXT ID="fact" SIZE=5> %<BR>
</TD>
</TR></TABLE>
<DIV ID="info_win" ALIGN=LEFT STYLE="position:absolute; top:0; background-color:white; overflow:auto">
</DIV>
</DIV>
</FORM>
<SPAN ID="msg" STYLE="position:absolute; left:0; top:0; border-style:double; text-align:center; padding:0.8em 2em; background-color:white; border-color:#CC0000; visibility:hidden">読み込み中...</SPAN>
<IFRAME ID="cvt_uc" WIDTH=1 HEIGHT=1 FRAMEBORDER=0 SCROLLING=NO STYLE="position:absolute; left:0; top:0; visibility:hidden"></IFRAME>
<IFRAME ID="cvt_gpm" WIDTH=1 HEIGHT=1 FRAMEBORDER=0 SCROLLING=NO STYLE="position:absolute; left:0; top:0; visibility:hidden"></IFRAME>
<IFRAME ID="cvt_gai" WIDTH=1 HEIGHT=1 FRAMEBORDER=0 SCROLLING=NO STYLE="position:absolute; left:0; top:0; visibility:hidden"></IFRAME>
</CENTER>
<SCRIPT LANGUAGE="JavaScript1.5" TYPE="text/javascript">
<!--
function resize() {
elem_img_win.style.width = elem_img_win.style.height
= elem_info_win.style.width = elem_info_win.style.height = "1px";
elem_size.style.top = elem_info_win.style.left = "0";
var img_win_width;
if((img_win_width = Math.floor(document.body.scrollWidth * 0.65)) < elem_size.offsetWidth)
img_win_width = elem_size.offsetWidth;
var cont_height;
if((cont_height = document.body.scrollHeight - elem_cont.offsetTop - elem_back.offsetTop)
<= elem_size.offsetHeight)
cont_height = elem_size.offsetHeight + 1;
elem_img_win.style.width = String(img_win_width) + "px";
elem_img_win.style.height = elem_size.style.top
= String(cont_height - elem_size.offsetHeight) + "px";
elem_info_win.style.left = String(img_win_width + 8) + "px";
var info_win_width;
if((info_win_width = elem_cont.clientWidth - img_win_width - 8) < 1)
info_win_width = 1;
elem_info_win.style.width = String(info_win_width) + "px";
elem_info_win.style.height = String(cont_height) + "px";
if(elem_img.style.visibility == "visible") {
if(elem_fit.checked) // 表示領域に合わせる
scale_fit();
else
adj_pos();
}
}
function fact_keypress(e) {
if(e.which == 13) { // Enter
set_factor();
return;
}
// 小数 キー入力チェック
return (e.which < 0x20 || e.which >= 0x30 && e.which <= 0x39 || e.which == 0x2e || e.ctrlKey || e.metaKey);
}
function read() {
// ファイル選択ダイアログをキャンセルしたとき,Firefox では change イベントは発生しないが,
// 他のブラウザでは発生するものもあるので,ファイル選択の有無を一応チェックしておく.
if(!elem_file.files.length)
return;
elem_file.disabled = true;
// FileUpload コントロールの近くに読み込み中メッセージが表示される場合,この
// タイミングでメッセージを表示すると,FileUpload コントロールの再描画でメッ
// セージの表示が潰されることがあるので,FileUpload コントロールの再描画の後
// でメッセージが表示されるようにタイミングを調整する.
setTimeout(read2, 0);
}
function read2() {
elem_img.style.visibility = "hidden";
elem_img.width = elem_img.height = 1;
elem_img.style.left = elem_img.style.top = "0";
elem_img.style.width = elem_img.style.height = "";
elem_info_win.innerHTML = "";
with(elem_msg) {
style.left = String(document.body.scrollLeft + ((document.body.clientWidth - offsetWidth ) >> 1)) + "px";
style.top = String(document.body.scrollTop + ((document.body.clientHeight - offsetHeight) >> 1)) + "px";
style.visibility = "visible";
}
document.documentElement.style.cursor = "wait";
elem_info_win.style.overflow = "hidden"; // スクロール バーに前のスクロール量が残ってしまうので,おまじない.
setTimeout(read3, 0);
}
function read3() {
elem_info_win.style.overflow = "auto"; // スクロール バーに前のスクロール量が残ってしまうので,おまじない.
// Firefox 7 では nsIDOMFile オブジェクトの getAsBinary(),getAsDataURL() 等が削除された.
// 代わりに,Firefox 3.6 で新設された FileReader オブジェクトを使って同様のことができるので,
// FileReader オブジェクトが使えればそれを使い,使えなければ以前のままの処理とするように修正
// した.
if(typeof FileReader == "function") {
file_reader = new FileReader();
file_reader.onload = read_fr;
file_reader.readAsBinaryString(elem_file.files.item(0));
}
else {
file = elem_file.files.item(0).getAsBinary();
read4();
}
}
function read_fr() {
file = file_reader.result;
file_reader = undefined;
read4();
}
function read4() {
if((file.length < 2) ? true : ((get_short_be(file, 0) == 0xffd8/*SOI*/) ? read_JPEG() : read_TIFF())) {
with(elem_msg) {
style.visibility = "hidden";
style.left = style.top = "0";
}
document.documentElement.style.cursor = "auto";
alert("ファイルが Exif 形式でないか、このプログラムでは対応していないバージョンのファイルです。");
elem_file.disabled = false;
return;
}
put_info(); // 情報表示
}
// 縮小割合設定
function set_factor() {
var fact = elem_fact.value;
if(fact.search(/\S/) == -1) // 未入力
return;
if(fact.search(/^\s*\d*\.?\d*\s*$/) == -1) {
fact = 0;
}
else {
if(isNaN(fact = parseFloat(fact)))
fact = 0;
else
fact = Math.round(fact * 100) / 100;
}
if(fact == 0 || fact > 100) {
alert("縮小割合の入力に誤りがあります。");
return;
}
factor = fact / 100;
elem_cur_fact.value = String(fact);
if(elem_shr.checked)
scale_shr();
}
// 表示領域に合わせる
function scale_fit() {
if(elem_img.width / elem_img_win.clientWidth > elem_img.height / elem_img_win.clientHeight) {
elem_img.style.width = (elem_img.width > elem_img_win.clientWidth) ? "100%" : "";
elem_img.style.height = "";
}
else {
elem_img.style.width = "";
elem_img.style.height = (elem_img.height > elem_img_win.clientHeight) ? "100%" : "";
}
adj_pos();
}
// 原寸
function scale_org() {
elem_img.style.width = elem_img.style.height = "";
adj_pos();
}
// 指定した割合で縮小
function scale_shr() {
elem_img.style.width = Math.round(elem_img.width * factor);
elem_img.style.height = "";
adj_pos();
}
// 画像位置調整
function adj_pos() {
// 一旦位置をゼロにして,スクロール バーの有無を確定する.
elem_img.style.left = elem_img.style.top = "0";
// 画像の幅/高さが表示領域より小さければセンタリング
if(elem_img.offsetWidth < elem_img_win.clientWidth)
elem_img.style.left = String((elem_img_win.clientWidth - elem_img.offsetWidth) >> 1) + "px";
if(elem_img.offsetHeight < elem_img_win.clientHeight)
elem_img.style.top = String((elem_img_win.clientHeight - elem_img.offsetHeight) >> 1) + "px";
}
// **** JPEG ****
function read_JPEG() {
var exif = false;
var Y = undefined;
var X;
for(var off = 2; ; ) {
var len;
if(off + 2 > file.length)
return -1;
switch(get_short_be(file, off)) { // marker
case 0xffda: // SOS
if(!exif)
return -1;
if(Y == undefined)
return -1;
img_width = X;
img_height = Y;
// JPEG のレンダリングはブラウザに任せる
elem_src = document.createElement("IMG");
elem_src.width = X;
elem_src.height = Y;
elem_src.onload = JPEG_loaded;
// Firefox 7 では nsIDOMFile オブジェクトの getAsBinary(),getAsDataURL() 等が削除された.
// 代わりに,Firefox 3.6 で新設された FileReader オブジェクトを使って同様のことができるので,
// FileReader オブジェクトが使えればそれを使い,使えなければ以前のままの処理とするように修正
// した.
if(typeof FileReader == "function")
// Firefox 77 以上では,画像のレンダリングが Exif 情報に従って行われるようになった.
// そのため,画像の回転/反転が二重に行われてしまうようになった.
// Exif 情報に従う回転/反転が有効になっている場合は,JPEG ファイルのデータを修正して,
// ブラウザに Exif 情報を認識させないようにする.
elem_src.src = "data:image/jpeg;base64," + btoa(
(getComputedStyle(document.documentElement)["imageOrientation"] == "from-image")
? file.substr(0, off_id) + "\0" + file.substr(off_id + 1) : file);
else
elem_src.src = elem_file.files.item(0).getAsDataURL();
return 0;
case 0xffe1: // APP1
if(off + 4 > file.length)
return -1;
len = get_short_be(file, off + 2);
if(off + 2 + len > file.length)
return -1;
if(len >= 8) {
if(file.substr(off + 4, 6) == "Exif\0\0") {
off_id = off + 4;
if(read_Exif(file.substr(off + 10, len - 8)))
return -1;
exif = true;
}
}
break;
case 0xffc0: // SOF0
case 0xffc2: // SOF2
if(off + 4 > file.length)
return -1;
len = get_short_be(file, off + 2);
if(off + 2 + len > file.length)
return -1;
if(len < 8)
return -1;
if(len != 8 + get_byte(file, off + 9) * 3)
return -1;
if(get_byte(file, off + 4) != 8)
return -1;
Y = get_short_be(file, off + 5);
X = get_short_be(file, off + 7);
break;
}
if(off + 4 > file.length)
return -1;
off += 2 + get_short_be(file, off + 2);
}
}
function JPEG_loaded() {
show_img(); // 画像表示
}
// **** TIFF ****
function read_TIFF() {
if(read_Exif(file))
return -1;
// チェック
switch(img_width = TIFF_tags[I_ImageWidth].value) {
case undefined:
case 0:
return -1;
}
switch(img_height = TIFF_tags[I_ImageLength].value) {
case undefined:
case 0:
return -1;
}
value = TIFF_tags[I_BitsPerSample].value;
if(value[0] != 8 || value[1] != 8 || value[2] != 8)
return -1;
if(TIFF_tags[I_Compression].value != 1) // no compression 以外
return -1;
if(TIFF_tags[I_SamplesPerPixel].value != 3)
return -1;
switch(RowsPerStrip = TIFF_tags[I_RowsPerStrip].value) {
case undefined: // Exif の仕様ではデフォルトなし
case 0:
return -1;
}
if((StripOffsets = TIFF_tags[I_StripOffsets].value) == undefined)
return -1;
if((StripByteCounts = TIFF_tags[I_StripByteCounts].value) == undefined)
return -1;
if(StripOffsets.length != StripByteCounts.length)
return -1;
var pc_chunky;
switch(TIFF_tags[I_PlanarConfiguration].value) {
case 1: // Chunky
pc_chunky = true;
if(StripOffsets.length
!= ((RowsPerStrip < img_height) ? Math.floor((img_height + RowsPerStrip - 1) / RowsPerStrip) : 1))
return -1;
break;
case 2: // Planar
pc_chunky = false;
if(StripOffsets.length
!= ((RowsPerStrip < img_height) ? 3 * Math.floor((img_height + RowsPerStrip - 1) / RowsPerStrip) : 3))
return -1;
break;
default:
return -1;
}
var pi_RGB;
var strip_bytes;
var ss_422;
var i;
switch(TIFF_tags[I_PhotometricInterpretation].value) {
case 2: // RGB
pi_RGB = true;
if(pc_chunky) { // Chunky
row_bytes = img_width * 3;
strip_bytes = RowsPerStrip * row_bytes;
for(i = 0; i < StripOffsets.length - 1; i++) {
if(StripByteCounts[i] != strip_bytes)
return -1;
}
if(StripByteCounts[i] != (img_height - (StripOffsets.length - 1) * RowsPerStrip) * row_bytes)
return -1;
}
else { // Planar
if(StripOffsets.length % 3)
return -1;
row_bytes = img_width;
strip_bytes = RowsPerStrip * row_bytes;
var strips1 = StripOffsets.length / 3;
for(i = 0; i < StripOffsets.length; i++) {
if(StripByteCounts[i]
!= (((i + 1) % strips1) ? strip_bytes : (img_height - (strips1 - 1) * RowsPerStrip) * row_bytes))
return -1;
}
}
break;
case 6: // YCbCr
pi_RGB = false;
if(!pc_chunky) // Chunky 以外
return -1;
if((value = TIFF_tags[I_YCbCrSubSampling].value) == undefined)
return -1;
if(value[0] != 2 || value[1] != 1 && value[1] != 2) // 4:2:2,4:2:0 以外
return -1;
if(!(ss_422 = (value[1] == 1))) { // 4:2:0
if(RowsPerStrip < img_height) {
if(RowsPerStrip % 2) // RowsPerStrip が奇数
return -1;
}
}
switch(TIFF_tags[I_YCbCrPositioning].value) {
case 1: // centered
cosited = false;
break;
case 2: // cosited
cosited = true;
break;
default:
return -1;
}
value = TIFF_tags[I_YCbCrCoefficients].value;
if(!value[0].d || !value[1].d || !value[2].d)
return -1;
LR = value[0].n / value[0].d;
LG = value[1].n / value[1].d;
LB = value[2].n / value[2].d;
width_odd = img_width % 2;
if(ss_422) { // 4:2:2
row_bytes = (img_width + width_odd) * 2;
strip_bytes = RowsPerStrip * row_bytes;
for(i = 0; i < StripOffsets.length - 1; i++) {
if(StripByteCounts[i] != strip_bytes)
return -1;
}
if(StripByteCounts[i] != (img_height - (StripOffsets.length - 1) * RowsPerStrip) * row_bytes)
return -1;
}
else { // 4:2:0
row_bytes = (img_width + width_odd) * 3; // 2 行分
strip_bytes = RowsPerStrip / 2 * row_bytes;
for(i = 0; i < StripOffsets.length - 1; i++) {
if(StripByteCounts[i] != strip_bytes)
return -1;
}
if(StripByteCounts[i]
!= (img_height - (StripOffsets.length - 1) * RowsPerStrip + img_height % 2) / 2 * row_bytes)
return -1;
}
break;
default:
return -1;
}
if((value = TIFF_tags[I_ReferenceBlackWhite].value) == undefined) {
// JEITA CP-3451A の仕様ではこうなっているが,YCbCr のときのデフォルト値は
// [0, 255, 128, 255, 128, 255] でなくていいのか?
RB0 = RB1 = RB2 = 0;
SC0 = 1;
SC1 = SC2 = (pi_RGB) ? 1 : 127 / 128;
}
else {
if(!value[0].d || !value[1].d || !value[2].d || !value[3].d || !value[4].d || !value[5].d)
return -1;
RB0 = value[0].n / value[0].d;
RB1 = value[2].n / value[2].d;
RB2 = value[4].n / value[4].d;
SC0 = 255 / (value[1].n / value[1].d - RB0);
var CR = (pi_RGB) ? 255 : 127;
SC1 = CR / (value[3].n / value[3].d - RB1);
SC2 = CR / (value[5].n / value[5].d - RB2);
}
// 画像
elem_src = document.createElement("CANVAS");
elem_src.width = img_width;
elem_src.height = img_height;
src_ctx = elem_src.getContext("2d");
src_ctx.fillStyle = "rgba(0,0,0,1)";
src_ctx.fillRect(0, 0, img_width, img_height);
src_img = src_ctx.getImageData(0, 0, img_width, img_height);
img_data = src_img.data;
i_strip = -1;
if(pi_RGB) { // RGB
if(pc_chunky) { // Chunky
img_rows = img_height;
strip_rows = 0;
i_img = 0;
setTimeout(TIFF_RGB_Chunky, 0);
}
else { // Planar
plane = -1;
img_rows = 0;
setTimeout(TIFF_RGB_Planar, 0);
}
}
else { // YCbCr
SC1_L = SC1 * (2 - 2 * LB);
SC2_L = SC2 * (2 - 2 * LR);
img_rows = img_height;
strip_rows = 0;
i_img = 0;
if(ss_422) { // 4:2:2
setTimeout(TIFF_YCbCr_422, 0);
}
else { // 4:2:0
img_stride = img_width * 4;
sub_width = (img_width + width_odd) / 2;
prev_Y0 = new Array();
prev_Y1 = new Array();
prev_Cb_L = new Array();
prev_Cr_L = new Array();
prev_Y0.length = prev_Y1.length = prev_Cb_L.length = prev_Cr_L.length = sub_width;
setTimeout(TIFF_YCbCr_420, 0);
}
}
return 0;
}
function TIFF_RGB_Chunky() {
for(var cnt = 100; cnt; cnt--) {
if(!strip_rows) {
strip_off = StripOffsets[++i_strip];
strip_rows = RowsPerStrip;
}
for(var off_end = strip_off + row_bytes; strip_off < off_end; strip_off += 3) {
var w;
w = Math.round((file.charCodeAt(strip_off ) - RB0) * SC0); // R
img_data[i_img ] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round((file.charCodeAt(strip_off + 1) - RB1) * SC1); // G
img_data[i_img + 1] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round((file.charCodeAt(strip_off + 2) - RB2) * SC2); // B
img_data[i_img + 2] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
i_img += 4;
}
if(!--img_rows) {
TIFF_ready();
return;
}
strip_rows--;
}
setTimeout(TIFF_RGB_Chunky, 0);
}
function TIFF_RGB_Planar() {
for(var cnt = 100; cnt; cnt--) {
if(!img_rows) {
if(plane == 2) {
TIFF_ready();
return;
}
switch(++plane) {
case 0:
RB = RB0;
SC = SC0;
break;
case 1:
RB = RB1;
SC = SC1;
break;
default:
RB = RB2;
SC = SC2;
}
i_img = plane;
img_rows = img_height;
strip_rows = 0;
}
if(!strip_rows) {
strip_off = StripOffsets[++i_strip];
strip_rows = RowsPerStrip;
}
for(var off_end = strip_off + row_bytes; strip_off < off_end; strip_off++) {
var w = Math.round((file.charCodeAt(strip_off) - RB) * SC);
img_data[i_img] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
i_img += 4;
}
img_rows--;
strip_rows--;
}
setTimeout(TIFF_RGB_Planar, 0);
}
function TIFF_YCbCr_422() {
for(var cnt = 100; cnt; cnt--) {
if(!strip_rows) {
strip_off = StripOffsets[++i_strip];
strip_rows = RowsPerStrip;
}
for(var off_end = strip_off + row_bytes; ; ) {
var Cb_L = (file.charCodeAt(strip_off + 2) - RB1) * SC1_L;
var Cr_L = (file.charCodeAt(strip_off + 3) - RB2) * SC2_L;
var Y;
var R, B;
var w;
Y = (file.charCodeAt(strip_off) - RB0) * SC0;
w = Math.round(R = Cr_L + Y); // R
img_data[i_img ] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round(B = Cb_L + Y); // B
img_data[i_img + 2] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round((Y - LB * B - LR * R) / LG); // G
img_data[i_img + 1] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
if((strip_off += 4) == off_end && width_odd) { // 幅が奇数のときの最終カラム
i_img += 4;
break;
}
Y = (file.charCodeAt(strip_off - 3) - RB0) * SC0;
if(cosited) {
if(strip_off < off_end) { // 最終カラム以外
Cb_L = (Cb_L + (file.charCodeAt(strip_off + 2) - RB1) * SC1_L) / 2;
Cr_L = (Cr_L + (file.charCodeAt(strip_off + 3) - RB2) * SC2_L) / 2;
}
}
w = Math.round(R = Cr_L + Y); // R
img_data[i_img + 4] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round(B = Cb_L + Y); // B
img_data[i_img + 6] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round((Y - LB * B - LR * R) / LG); // G
img_data[i_img + 5] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
i_img += 8;
if(strip_off == off_end) // 最終カラム
break;
}
if(!--img_rows) {
TIFF_ready();
return;
}
strip_rows--;
}
setTimeout(TIFF_YCbCr_422, 0);
}
function TIFF_YCbCr_420() {
for(var cnt = 50; cnt; cnt--) {
if(!strip_rows) {
strip_off = StripOffsets[++i_strip];
strip_rows = RowsPerStrip;
}
var i_prev = 0;
for(off_end = strip_off + row_bytes; ; ) {
var Cb_L = (file.charCodeAt(strip_off + 4) - RB1) * SC1_L;
var Cr_L = (file.charCodeAt(strip_off + 5) - RB2) * SC2_L;
var Cb_L_p, Cr_L_p;
var i_img2;
var Cb_L_2, Cr_L_2;
var Y;
var R, B;
var w;
if(img_rows < img_height) {
Cb_L_p = prev_Cb_L[i_prev];
Cr_L_p = prev_Cr_L[i_prev];
i_img2 = i_img - img_stride;
if(cosited) {
Cb_L_2 = (Cb_L_p + Cb_L) / 2;
Cr_L_2 = (Cr_L_p + Cr_L) / 2;
}
else {
Cb_L_2 = Cb_L_p;
Cr_L_2 = Cr_L_p;
}
Y = prev_Y0[i_prev];
w = Math.round(R = Cr_L_2 + Y); // R
img_data[i_img2 ] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round(B = Cb_L_2 + Y); // B
img_data[i_img2 + 2] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round((Y - LB * B - LR * R) / LG); // G
img_data[i_img2 + 1] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
}
Y = (file.charCodeAt(strip_off) - RB0) * SC0;
w = Math.round(R = Cr_L + Y); // R
img_data[i_img ] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round(B = Cb_L + Y); // B
img_data[i_img + 2] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round((Y - LB * B - LR * R) / LG); // G
img_data[i_img + 1] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
if(img_rows != 1) { // 高さが奇数のときの最終行以外
prev_Cb_L[i_prev] = Cb_L;
prev_Cr_L[i_prev] = Cr_L;
prev_Y0[i_prev] = (file.charCodeAt(strip_off + 2) - RB0) * SC0;
}
if((strip_off += 6) == off_end && width_odd) { // 幅が奇数のときの最終カラム
i_img += 4;
break;
}
var Cb_L_n;
var Cr_L_n;
var Cb_L_3 = Cb_L;
var Cr_L_3 = Cr_L;
if(cosited) {
if(strip_off < off_end) { // 最終カラム以外
Cb_L_n = (file.charCodeAt(strip_off + 4) - RB1) * SC1_L;
Cr_L_n = (file.charCodeAt(strip_off + 5) - RB2) * SC2_L;
Cb_L_3 = (Cb_L + Cb_L_n) / 2;
Cr_L_3 = (Cr_L + Cr_L_n) / 2;
}
}
if(img_rows < img_height) { // 最初の行以外
if(cosited) {
if(strip_off == off_end) { // 最終カラム
Cb_L_2 = (Cb_L_p + Cb_L) / 2;
Cr_L_2 = (Cr_L_p + Cr_L) / 2;
}
else {
Cb_L_2 = (Cb_L_p + prev_Cb_L[i_prev + 1] + Cb_L + Cb_L_n) / 4;
Cr_L_2 = (Cr_L_p + prev_Cr_L[i_prev + 1] + Cr_L + Cr_L_n) / 4;
}
}
else {
Cb_L_2 = Cb_L_p;
Cr_L_2 = Cr_L_p;
}
Y = prev_Y1[i_prev];
w = Math.round(R = Cr_L_2 + Y); // R
img_data[i_img2 + 4] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round(B = Cb_L_2 + Y); // B
img_data[i_img2 + 6] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round((Y - LB * B - LR * R) / LG); // G
img_data[i_img2 + 5] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
}
Y = (file.charCodeAt(strip_off - 5) - RB0) * SC0;
w = Math.round(R = Cr_L_3 + Y); // R
img_data[i_img + 4] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round(B = Cb_L_3 + Y); // B
img_data[i_img + 6] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round((Y - LB * B - LR * R) / LG); // G
img_data[i_img + 5] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
if(img_rows != 1) // 高さが奇数のときの最終行以外
prev_Y1[i_prev] = (file.charCodeAt(strip_off - 3) - RB0) * SC0;
i_img += 8;
if(strip_off == off_end) // 最終カラム
break;
i_prev++;
}
i_img += img_stride;
if((img_rows -= 2) <= 0) {
if(!img_rows) { // 高さが偶数
for(i_prev = 0; i_prev < sub_width; i_prev++) {
Cb_L = prev_Cb_L[i_prev];
Cr_L = prev_Cr_L[i_prev];
Y = prev_Y0[i_prev];
w = Math.round(R = Cr_L + Y); // R
img_data[i_img ] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round(B = Cb_L + Y); // B
img_data[i_img + 2] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round((Y - LB * B - LR * R) / LG); // G
img_data[i_img + 1] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
if(i == sub_width - 1 && width_odd) // 幅が奇数のときの最終カラム
break;
Y = prev_Y1[i_prev];
if(cosited) {
if(i < sub_width - 1) { // 最終カラム以外
Cb_L = (Cb_L + prev_Cb_L[i_prev + 1]) / 2;
Cr_L = (Cr_L + prev_Cr_L[i_prev + 1]) / 2;
}
}
w = Math.round(R = Cr_L + Y); // R
img_data[i_img + 4] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round(B = Cb_L + Y); // B
img_data[i_img + 6] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
w = Math.round((Y - LB * B - LR * R) / LG); // G
img_data[i_img + 5] = (w < 0) ? 0 : ((w > 255) ? 255 : w);
i_img += 8;
}
}
prev_Y0 = prev_Y1 = prev_Cb_L = prev_Cr_L = undefined;
TIFF_ready();
return;
}
strip_rows -= 2;
}
setTimeout(TIFF_YCbCr_420, 0);
}
function TIFF_ready() {
src_ctx.putImageData(src_img, 0, 0);
src_ctx = undefined;
src_img = undefined;
show_img(); // 画像表示
}
// Exif 情報読み込み
function read_Exif(tiff) {
// Image File Header
if(tiff.length < 8)
return -1;
switch(get_short_be(tiff, 0)) {
case 0x4949: // II
get_value[SHORT] = get_short = get_short_le;
get_value[LONG] = get_long = get_long_le;
get_slong = get_slong_le;
break;
case 0x4d4d: // MM
get_value[SHORT] = get_short = get_short_be;
get_value[LONG] = get_long = get_long_be;
get_slong = get_slong_be;
break;
default:
return -1;
}
if(get_short(tiff, 2) != 42)
return -1;
var value;
// 0th IFD
if(read_IFD(tiff, get_long(tiff, 4), TIFF_tags))
return -1;
// チェック
// 解像度
value = TIFF_tags[I_XResolution].value;
if(!value.d)
return -1;
resolution = value.n / value.d;
value = TIFF_tags[I_YResolution].value;
if(!value.d)
return -1;
if(resolution != value.n / value.d)
return -1;
// 画像方向
Orientation = TIFF_tags[I_Orientation].value;
if(!Orientation || Orientation > 8)
return -1;
// Exif IFD
if(TIFF_tags[I_Exif_IFD].value != undefined) {
if(read_IFD(tiff, TIFF_tags[I_Exif_IFD].value, Exif_tags))
return -1;
}
// チェック
// 被写体領域
if((value = Exif_tags[I_SubjectArea].value) != undefined) {
if(value.length < 2 || value.length > 4)
return -1;
}
// GPS IFD
if(TIFF_tags[I_GPS_IFD].value != undefined) {
if(read_IFD(tiff, TIFF_tags[I_GPS_IFD].value, GPS_tags))
return -1;
}
return 0;
}
// IFD 読み込み
function read_IFD(tiff, off, tags) {
if(!off || off + 2 > tiff.length)
return -1;
var n_dir = get_short(tiff, off);
off += 2;
if(off + n_dir * 12 + 4 > tiff.length)
return -1;
var i;
// 初期値(undefined or デフォルト値)
for(i = 0; i < tags.length; i++)
tags[i].value = tags[i][3];
for(; n_dir; n_dir--, off += 12) {
var tag = get_short(tiff, off); // Tag
for(var i_tag = 0; i_tag < tags.length; i_tag++) {
if(tags[i_tag][0] == tag) {
// Type
var type = get_short(tiff, off + 2);
if(tags[i_tag][1] == SHORT_LONG) { // SHORT or LONG
switch(type) {
case SHORT:
case LONG:
break;
default:
return -1;
}
}
else {
if(type != tags[i_tag][1])
return -1;
}
// Count
var count = get_long(tiff, off + 4);
if(tags[i_tag][2]) {
if(count != tags[i_tag][2])
return -1;
}
// Value or Offset
var val_off = off + 8;
if(count * field_size[type] > 4) {
val_off = get_long(tiff, val_off);
if(val_off + count * field_size[type] > tiff.length)
return -1;
}
switch(type) {
case ASCII:
case UNDEFINED:
tags[i_tag].value = tiff.substr(val_off, count);
break;
default:
if(tags[i_tag][2] == 1) { // Count
tags[i_tag].value = get_value[type](tiff, val_off);
}
else {
tags[i_tag].value = new Array();
tags[i_tag].value.length = count;
for(i = 0; i < count; i++) {
tags[i_tag].value[i] = get_value[type](tiff, val_off);
val_off += field_size[type];
}
}
}
break;
}
}
}
return 0;
}
// 画像表示
function show_img() {
var ctx = elem_img.getContext("2d");
if(Orientation < 5) {
elem_img.width = img_width;
elem_img.height = img_height;
var m11 = 1, m22 = 1;
switch(Orientation) {
case 2: // 上右
m11 = -1;
break;
case 3: // 下右
m11 = m22 = -1;
break;
case 4: // 下左
m22 = -1;
break;
}
ctx.setTransform(m11, 0, 0, m22, (m11 < 0) ? img_width : 0, (m22 < 0) ? img_height : 0);
}
else {
elem_img.width = img_height;
elem_img.height = img_width;
var m12 = 1, m21 = 1;
switch(Orientation) {
case 6: // 右上
m21 = -1;
break;
case 7: // 右下
m12 = m21 = -1;
break;
case 8: // 左下
m12 = -1;
break;
}
ctx.setTransform(0, m12, m21, 0, (m21 < 0) ? img_height : 0, (m12 < 0) ? img_width : 0);
}
ctx.drawImage(elem_src, 0, 0);
elem_src = undefined;
if (elem_fit.checked) // 表示領域に合わせる
scale_fit();
else if(elem_org.checked) // 原寸
scale_org();
else // 指定した割合で縮小
scale_shr();
elem_img.style.visibility = "visible";
with(elem_msg) {
style.visibility = "hidden";
style.left = style.top = "0";
}
document.documentElement.style.cursor = "auto";
elem_file.disabled = false;
}
// 情報表示
// Firefox 57 からは,"data" URL が同一オリジン ポリシーにより制限されるようになったため,
// コード変換に "data" URL を使うことができなくなった.
// 代わりに,FileReader と Blob のコンストラクタが実装されているバージョンでは FileReader
// を使うようにした.
function put_info() {
var value, value2;
var unit;
var str, str2;
var n, m;
var off;
var uc_src = undefined;
var gpm_src = undefined;
var gai_src = undefined;
var rtn;
var i;
info = "<TABLE CELLSPACING=0 STYLE='white-space:pre; margin:0; padding:4px 0'>";
// 画像の幅/高さ
info_item("サイズ", String(img_width) + " x " + String(img_height));
// 解像度
unit = ResolutionUnit_str[TIFF_tags[I_ResolutionUnit].value];
info_item("解像度", (unit == undefined) ? "不明" : String(resolution) + " " + unit);
// 作成日時
if((value = TIFF_tags[I_DateTime].value) != undefined)
info_item("作成日時", DateTime(value, (TIFF_tags[I_Exif_IFD].value == undefined)
? undefined : Exif_tags[I_SubsecTime].value));
// タイトル
if((value = TIFF_tags[I_ImageDescription].value) != undefined)
info_item("タイトル", ascii(value));
// メーカー
if((value = TIFF_tags[I_Make].value) != undefined)
info_item("メーカー", ascii(value));
// モデル
if((value = TIFF_tags[I_Model].value) != undefined)
info_item("モデル", ascii(value));
// ソフトウェア
if((value = TIFF_tags[I_Software].value) != undefined)
info_item("使用ソフトウェア", ascii(value));
// アーティスト
if((value = TIFF_tags[I_Artist].value) != undefined)
info_item("作者", ascii(value));
// 撮影著作権者/編集著作権者
if((value = TIFF_tags[I_Copyright].value) != undefined) {
str = "";
str2 = "";
if((i = value.indexOf("\0")) != -1) {
if((str = value.substr(0, i)) == " ")
str = "";
var i2;
if((i2 = value.indexOf("\0", i + 1)) != -1)
str2 = value.substr(i + 1, i2 - i - 1);
}
if(str.length)
info_item("撮影著作権者", info_text(str));
if(str2.length)
info_item("編集著作権者", info_text(str2));
}
// 付属情報
if(TIFF_tags[I_Exif_IFD].value != undefined) {
info_item("<BR>", "");
// 色空間情報
if((value = Exif_tags[I_ColorSpace].value) != undefined) {
str = ColorSpace_str[value];
info_item("色空間情報", (str == undefined) ? "不明" : str);
}
// 再生ガンマ
if((value = Exif_tags[I_Gamma].value) != undefined)
info_item("再生ガンマ", rational(value, 3, undefined));
// メーカー ノート
if((value = Exif_tags[I_MakerNote].value) != undefined)
info_item("メーカー ノート", "(" + String(value.length) + " バイト)");
// ユーザ コメント
if((value = Exif_tags[I_UserComment].value) != undefined) {
rtn = conv_text(value, "info_uc");
info_item("ユーザ コメント", rtn.txt);
if(rtn.src != undefined) {
if(fr_uc == undefined)
elem_cvt_uc.onload = uc_loaded;
uc_src = rtn.src;
}
}
// 関連音声ファイル
if((value = Exif_tags[I_RelatedSoundFile].value) != undefined)
info_item("関連音声ファイル", ascii(value));
// 原画像データの生成日時
if((value = Exif_tags[I_DateTimeOriginal].value) != undefined)
info_item("原画像データ生成日時", DateTime(value, Exif_tags[I_SubsecTimeOriginal].value));
// ディジタル データの作成日時
if((value = Exif_tags[I_DateTimeDigitized].value) != undefined)
info_item("ディジタル データ作成日時", DateTime(value, Exif_tags[I_SubsecTimeDigitized].value));
// 露出時間
if((value = Exif_tags[I_ExposureTime].value) != undefined)
info_item("露出時間",
(value.d) ? ((value.n == 1) ? "1/" + String(value.d)
: rational(value, 6, undefined)) + " 秒"
: "不明");
// Fナンバー
if((value = Exif_tags[I_FNumber].value) != undefined)
info_item("F値", rational(value, 1, undefined));
// 露出プログラム
value = Exif_tags[I_ExposureProgram].value;
info_item("露出プログラム", ((value > 8) ? "不明" : ExposureProgram_str[value]));
// スペクトル感度
if((value = Exif_tags[I_SpectralSensitivity].value) != undefined)
info_item("スペクトル感度", ascii(value));
// ISO スピード レート
if((value = Exif_tags[I_ISOSpeedRatings].value) != undefined) {
str = "";
for(i = 0; i < value.length; i++) {
if(i)
str += ", ";
str += String(value[i]);
}
info_item("ISO スピード レート", str);
}
// 光電変換関数
if((value = Exif_tags[I_OECF].value) != undefined) {
if(value.length < 4) {
str = "不明";
}
else {
n = get_short(value, 0);
m = get_short(value, 2);
off = 4;
str = "<TABLE CELLSPACING=0 CELLPADDING=0 STYLE='white-space:pre'><TR>";
for(i = n; i; i--) {
if((value2 = get_asciiz(value, off)) == undefined)
break;
str += "<TD STYLE='padding-right:1em'>" + info_text(value2) + "</TD>";
off += value2.length + 1;
}
if(i) {
str = "不明";
}
else {
if(off + n * m * 8 == value.length) {
str += "</TR>";
for(; m; m--) {
str += "<TR>";
for(i = n; i; i--) {
str += "<TD STYLE='padding-right:1em'>"
+ rational(get_srational(value, off), 3, undefined)
+ "</TD>";
off += 8;
}
str += "</TR>";
}
str += "</TABLE>";
}
else {
str = "不明";
}
}
}
info_item("光電変換関数", str);
}
// シャッター スピード
if((value = Exif_tags[I_ShutterSpeedValue].value) != undefined)
info_item("シャッター スピード", rational(value, 3, "APEX"));
// 絞り値
if((value = Exif_tags[I_ApertureValue].value) != undefined)
info_item("絞り値", rational(value, 3, "APEX"));
// 輝度値
if((value = Exif_tags[I_BrightnessValue].value) != undefined)
info_item("輝度値", (value.n == -1/*FFFFFFFF.H*/) ? "不明" : rational(value, 3, "APEX"));
// 露光補正値
if((value = Exif_tags[I_ExposureBiasValue].value) != undefined)
info_item("露出補正値", rational(value, 3, "APEX"));
// レンズ最小F値
if((value = Exif_tags[I_MaxApertureValue].value) != undefined)
info_item("レンズ最小F値", rational(value, 3, "APEX"));
// 被写体距離
if((value = Exif_tags[I_SubjectDistance].value) != undefined) {
switch(value.n) {
case 0:
str = "不明";
break;
case 4294967295: // FFFFFFFF.H
str = "∞";
break;
default:
str = rational(value, 3, "m");
}
info_item("被写体距離", str);
}
// 測光方式
info_item("測光方式",
((str = MeteringMode_str[Exif_tags[I_MeteringMode].value]) == undefined) ? "不明" : str);
// 光源
info_item("光源",
((str = LightSource_str[Exif_tags[I_LightSource].value]) == undefined) ? "不明" : str);
// フラッシュ
if((value = Exif_tags[I_Flash].value) != undefined) {
str = ((value & 0x01) ? "ストロボ発光" : "ストロボ発光せず") + "<BR>";
switch(value & 0x06) {
case 0x00:
str += "ストロボのリターン検出機能なし";
break;
case 0x04:
str += "ストロボのリターン検出されず";
break;
case 0x06:
str += "ストロボのリターン検出";
break;
default:
str += "ストロボのリターン状態不明";
}
str += "<BR>";
switch(value & 0x18) {
case 0x08:
str += "強制発光モード";
break;
case 0x10:
str += "強制非発光モード";
break;
case 0x18:
str += "自動発光モード";
break;
default:
str += "ストロボ モード不明";
}
str += "<BR>";
str += ((value & 0x20) ? "ストロボ機能なし" : "ストロボ機能あり") + "<BR>";
str += (value & 0x40) ? "赤目軽減あり" : "赤目軽減なし、または赤目モード不明";
info_item("フラッシュ", str);
}
// レンズ焦点距離
if((value = Exif_tags[I_FocalLength].value) != undefined)
info_item("レンズ焦点距離", rational(value, 1, "mm"));
// 被写体領域
if((value = Exif_tags[I_SubjectArea].value) != undefined) {
str = "X: " + String(value[0]) + ", Y: " + String(value[1]);
switch(value.length) {
case 3:
str += ", 直径: " + String(value[2]);
break;
case 4:
str += ", 幅: " + String(value[2]) + ", 高さ: " + String(value[3]);
break;
}
info_item("被写体領域", str);
}
// フラッシュ強度
if((value = Exif_tags[I_FlashEnergy].value) != undefined)
info_item("フラッシュ強度", rational(value, 1, "BCPS"));
// 空間周波数応答
if((value = Exif_tags[I_SpatialFrequencyResponse].value) != undefined) {
if(value.length < 4) {
str = "不明";
}
else {
n = get_short(value, 0);
m = get_short(value, 2);
off = 4;
str = "<TABLE CELLSPACING=0 CELLPADDING=0 STYLE='white-space:pre'><TR>";
for(i = n; i; i--) {
if((value2 = get_asciiz(value, off)) == undefined)
break;
str += "<TD STYLE='padding-right:1em'>" + info_text(value2) + "</TD>";
off += value2.length + 1;
}
if(i) {
str = "不明";
}
else {
if(off + n * m * 8 == value.length) {
str += "</TR>";
for(; m; m--) {
str += "<TR>";
for(i = n; i; i--) {
str += "<TD STYLE='padding-right:1em'>"
+ rational(get_rational(value, off), 3, undefined)
+ "</TD>";
off += 8;
}
str += "</TR>";
}
str += "</TABLE>";
}
else {
str = "不明";
}
}
}
info_item("空間周波数応答", str);
}
// 焦点面解像度単位
unit = ResolutionUnit_str[Exif_tags[I_FocalPlaneResolutionUnit].value];
// 焦点面の幅の解像度
if((value = Exif_tags[I_FocalPlaneXResolution].value) != undefined)
info_item("焦点面の幅の解像度",
(unit == undefined) ? "不明" : rational(value, 1, unit));
// 焦点面の高さの解像度
if((value = Exif_tags[I_FocalPlaneYResolution].value) != undefined)
info_item("焦点面の高さの解像度",
(unit == undefined) ? "不明" : rational(value, 1, unit));
// 被写体位置
if((value = Exif_tags[I_SubjectLocation].value) != undefined)
info_item("被写体位置", "X: " + String(value[0]) + ", Y: " + String(value[1]));
// 露出インデックス
if((value = Exif_tags[I_ExposureIndex].value) != undefined)
info_item("露出インデックス", rational(value, 1, undefined));
// センサ方式
if((value = Exif_tags[I_SensingMethod].value) != undefined)
info_item("センサ方式", ((str = SensingMethod_str[value]) == undefined) ? "不明" : str);
// ファイル ソース
info_item("ファイル ソース",
((value = Exif_tags[I_FileSource].value.charCodeAt()) > 3) ? "不明" : FileSource_str[value]);
// シーン タイプ
info_item("シーン タイプ",
(Exif_tags[I_SceneType].value.charCodeAt() == 1) ? "直接撮影された画像" : "不明");
// CFA パターン
if((value = Exif_tags[I_CFAPattern].value) != undefined) {
if(value.length < 4) {
str = "不明";
}
else {
n = get_short(value, 0);
m = get_short(value, 2);
if(4 + n * m == value.length) {
off = 4;
str = "<TABLE CELLSPACING=0 CELLPADDING=0 STYLE='white-space:pre'>";
for(; m; m--) {
str += "<TR>";
for(i = n; i; i--) {
value2 = get_byte(value, off);
str += "<TD STYLE='padding-right:1em'>" + ((value2 > 6) ? "不明" : CFA_str[value2])
+ "</TD>";
off++;
}
str += "</TR>";
}
str += "</TABLE>";
}
else {
str = "不明";
}
}
info_item("CFA パターン", str);
}
// 個別画像処理
info_item("個別画像処理",
((value = Exif_tags[I_CustomRendered].value) > 1) ? "不明" : CustomRendered_str[value]);
// 露出モード
if((value = Exif_tags[I_ExposureMode].value) != undefined)
info_item("露出モード", (value > 2) ? "不明" : ExposureMode_str[value]);
// ホワイト バランス
if((value = Exif_tags[I_WhiteBalance].value) != undefined)
info_item("ホワイト バランス", (value > 1) ? "不明" : WhiteBalance_str[value]);
// ディジタル ズーム倍率
if((value = Exif_tags[I_DigitalZoomRatio].value) != undefined)
info_item("ディジタル ズーム倍率",
(value.n) ? rational(value, 1, undefined) : "ディジタル ズーム未使用");
// 35mm 換算レンズ焦点距離
if((value = Exif_tags[I_FocalLengthIn35mmFilm].value) != undefined)
info_item("35mm 換算レンズ焦点距離", (value) ? String(value) + " mm" : "不明");
// 撮影シーン タイプ
info_item("撮影シーン タイプ",
((value = Exif_tags[I_SceneCaptureType].value) > 3) ? "不明" : SceneCaptureType_str[value]);
// ゲイン制御
if((value = Exif_tags[I_GainControl].value) != undefined)
info_item("ゲイン制御", (value > 4) ? "不明" : GainControl_str[value]);
// 撮影コントラスト
info_item("撮影コントラスト",
((value = Exif_tags[I_Contrast].value) > 2) ? "不明" : Contrast_str[value]);
// 撮影彩度
info_item("撮影彩度", ((value = Exif_tags[I_Saturation].value) > 2) ? "不明" : Saturation_str[value]);
// 撮影シャープネス
info_item("撮影シャープネス",
((value = Exif_tags[I_Sharpness].value) > 2) ? "不明" : Sharpness_str[value]);
// 撮影条件記述情報
if((value = Exif_tags[I_DeviceSettingDescription].value) != undefined) {
if(value.length < 4) {
str = "";
}
else {
n = get_short(value, 0);
m = get_short(value, 2);
off = 4;
str = "<TABLE CELLSPACING=0 CELLPADDING=0 STYLE='white-space:pre'>";
for(; m; m--) {
str += "<TR>";
for(i = n; i; i--) {
if(off + 2 > value.length)
break;
// JEITA CP-3451A の仕様では Signature を含むことになっているが,Signature のバイト オーダーが
// TIFF ヘッダのバイト オーダーと違ったら,Signature のバイト オーダーに従うのだろうか?
var get_short_w;
switch(get_short_be(value, off)) {
case 0xfeff: // big endian
get_short_w = get_short_be;
off += 2;
break;
case 0xfffe: // little endian
get_short_w = get_short_le;
off += 2;
break;
default: // Signature が無いときは TIFF ヘッダのバイト オーダーに従う
get_short_w = get_short;
}
str2 = "";
for(; ; ) {
if(off + 2 > value.length) {
value2 = true;
break;
}
value2 = get_short_w(value, off);
off += 2;
if(!value2)
break;
str2 += String.fromCharCode(value2);
}
if(value2)
break;
str += "<TD STYLE='padding-right:1em'>" + info_text(str2) + "</TD>";
}
if(i)
break;
str += "</TR>";
}
if(m)
str = "";
else
str += "</TABLE>";
}
info_item("撮影条件記述情報", str);
}
// 被写体距離レンジ
if((value = Exif_tags[I_SubjectDistanceRange].value) != undefined)
info_item("被写体距離レンジ", ((str = SubjectDistanceRange_str[value]) == undefined) ? "不明" : str);
// 画像ユニーク ID
if((value = Exif_tags[I_ImageUniqueID].value) != undefined)
info_item("画像ユニーク ID", ascii(value));
}
// GPS
if(TIFF_tags[I_GPS_IFD].value != undefined) {
info_item("<BR>", "");
// 緯度,経度
str = "";
if((value = GPS_tags[I_GPSLatitudeRef].value) != undefined
&& (value2 = GPS_tags[I_GPSLatitude].value) != undefined) {
unit = LatitudeRef_str[ascii(value)];
if(unit != undefined && value2[0].d && value2[1].d && value2[2].d) {
str = unit + " " + String(value2[0].n / value2[0].d) + "度";
if(value2[0].d == 1) {
str += String(value2[1].n / value2[1].d) + "分";
if(value2[1].d == 1)
str += String(value2[2].n / value2[2].d) + "秒";
}
}
else {
str = "緯度不明";
}
}
if((value = GPS_tags[I_GPSLongitudeRef].value) != undefined
&& (value2 = GPS_tags[I_GPSLongitude].value) != undefined) {
if(str.length)
str += "<BR>";
unit = LongitudeRef_str[ascii(value)];
if(unit != undefined && value2[0].d && value2[1].d && value2[2].d) {
str += unit + " " + String(value2[0].n / value2[0].d) + "度";
if(value2[0].d == 1) {
str += String(value2[1].n / value2[1].d) + "分";
if(value2[1].d == 1)
str += String(value2[2].n / value2[2].d) + "秒";
}
}
else {
str += "経度不明";
}
}
if(str.length)
info_item("経緯度", str);
// 高度
if((value = GPS_tags[I_GPSAltitude].value) != undefined) {
switch(GPS_tags[I_GPSAltitudeRef].value) {
case 0:
str = "";
break;
case 1:
str = "-";
break;
default:
str = undefined;
}
info_item("高度", (str == undefined || !value.d) ? "不明" : str + rational(value, 1, "m"));
}
// GPS 時間(原子時計の時間)
if((value = GPS_tags[I_GPSTimeStamp].value) != undefined) {
if(!value[0].d || !value[1].d || !value[2].d) {
str = "不明";
}
else {
str = String(value[0].n / value[0].d) + "時";
if(value[0].d == 1) {
str += String(value[1].n / value[1].d) + "分";
if(value[1].d == 1)
str += String(value[2].n / value[2].d) + "秒";
}
str += " UTC";
}
info_item("GPS 時間", str);
}
// 測位に使った衛星信号
if((value = GPS_tags[I_GPSSatellites].value) != undefined)
info_item("測位に用いた衛星信号", ascii(value));
// GPS 受信機の状態
if((value = GPS_tags[I_GPSStatus].value) != undefined) {
str = GPSStatus_str[ascii(value)];
info_item("GPS 受信機の状態", (str == undefined) ? "不明" : str);
}
// GPS の測位方法
if((value = GPS_tags[I_GPSMeasureMode].value) != undefined) {
str = GPSMeasureMode_str[ascii(value)];
info_item("GPS の測位方法", (str == undefined) ? "不明" : str);
}
// 測位の信頼性
if((value = GPS_tags[I_GPSDOP].value) != undefined)
info_item("測位の信頼性", rational(value, 1, undefined));
// 速度
if((value = GPS_tags[I_GPSSpeed].value) != undefined) {
unit = GPSSpeedRef_str[ascii(GPS_tags[I_GPSSpeedRef].value)];
info_item("速度", (unit == undefined) ? "不明" : rational(value, 1, unit));
}
// 進行方向
if((value = GPS_tags[I_GPSTrack].value) != undefined) {
unit = DirectionRef_str[ascii(GPS_tags[I_GPSTrackRef].value)];
info_item("進行方向",
(unit == undefined || !value.d)
? "不明" : unit + " " + (value.n / value.d).toFixed(2) + " 度");
}
// 撮影した画像の方向
if((value = GPS_tags[I_GPSImgDirection].value) != undefined) {
unit = DirectionRef_str[ascii(GPS_tags[I_GPSImgDirectionRef].value)];
info_item("撮影した画像の方向",
(unit == undefined || !value.d)
? "不明" : unit + " " + (value.n / value.d).toFixed(2) + " 度");
}
// 測位に用いた地図データ
if((value = GPS_tags[I_GPSMapDatum].value) != undefined)
info_item("測地系", ascii(value));
// 目的地の緯度,目的地の経度
str = "";
if((value = GPS_tags[I_GPSDestLatitudeRef].value) != undefined
&& (value2 = GPS_tags[I_GPSDestLatitude].value) != undefined) {
unit = LatitudeRef_str[ascii(value)];
if(unit != undefined && value2[0].d && value2[1].d && value2[2].d) {
str = unit + " " + String(value2[0].n / value2[0].d) + "度";
if(value2[0].d == 1) {
str += String(value2[1].n / value2[1].d) + "分";
if(value2[1].d == 1)
str += String(value2[2].n / value2[2].d) + "秒";
}
}
else {
str = "緯度不明";
}
}
if((value = GPS_tags[I_GPSDestLongitudeRef].value) != undefined
&& (value2 = GPS_tags[I_GPSDestLongitude].value) != undefined) {
if(str.length)
str += "<BR>";
unit = LongitudeRef_str[ascii(value)];
if(unit != undefined && value2[0].d && value2[1].d && value2[2].d) {
str += unit + " " + String(value2[0].n / value2[0].d) + "度";
if(value2[0].d == 1) {
str += String(value2[1].n / value2[1].d) + "分";
if(value2[1].d == 1)
str += String(value2[2].n / value2[2].d) + "秒";
}
}
else {
str += "経度不明";
}
}
if(str.length)
info_item("目的地の経緯度", str);
// 目的地の方角
if((value = GPS_tags[I_GPSDestBearing].value) != undefined) {
unit = DirectionRef_str[ascii(GPS_tags[I_GPSDestBearingRef].value)];
info_item("目的地の方角",
(unit == undefined || !value.d)
? "不明" : unit + " " + (value.n / value.d).toFixed(2) + " 度");
}
// 目的地までの距離
if((value = GPS_tags[I_GPSDestDistance].value) != undefined) {
unit = GPSDestDistanceRef_str[ascii(GPS_tags[I_GPSDestDistanceRef].value)];
info_item("目的地までの距離", (unit == undefined) ? "不明" : rational(value, 1, unit));
}
// 測位方式の名称
if((value = GPS_tags[I_GPSProcessingMethod].value) != undefined) {
rtn = conv_text(value, "info_gpm");
info_item("測位方式", rtn.txt);
if(rtn.src != undefined) {
if(fr_uc == undefined)
elem_cvt_gpm.onload = gpm_loaded;
gpm_src = rtn.src;
}
}
// 測位地点の名称
if((value = GPS_tags[I_GPSAreaInformation].value) != undefined) {
rtn = conv_text(value, "info_gai");
info_item("測位地点", rtn.txt);
if(rtn.src != undefined) {
if(fr_uc == undefined)
elem_cvt_gai.onload = gai_loaded;
gai_src = rtn.src;
}
}
// GPS 日付
if((value = GPS_tags[I_GPSDateStamp].value) != undefined) {
var dt = value.match(/(\d{4}):(\d{2}):(\d{2})/);
if(dt == null) {
str = "不明";
}
else {
if(dt[2].charAt(0) == "0")
dt[2] = dt[2].substr(1);
if(dt[3].charAt(0) == "0")
dt[3] = dt[3].substr(1);
str = dt[1] + "年" + dt[2] + "月" + dt[3] + "日 UTC";
}
info_item("GPS 日付", str);
}
// GPS 補正測位
if((value = GPS_tags[I_GPSDifferential].value) != undefined)
info_item("GPS 補正測位", (value > 1) ? "不明" : GPSDifferential_str[value]);
}
info += "</TABLE>";
elem_info_win.innerHTML = info;
if(uc_src != undefined) {
if(fr_uc == undefined)
elem_cvt_uc.src = uc_src;
else
fr_uc.readAsText(uc_src.blb, uc_src.enc);
}
if(gpm_src != undefined) {
if(fr_uc == undefined)
elem_cvt_gpm.src = gpm_src;
else
fr_gpm.readAsText(gpm_src.blb, gpm_src.enc);
}
if(gai_src != undefined) {
if(fr_uc == undefined)
elem_cvt_gai.src = gai_src;
else
fr_gai.readAsText(gai_src.blb, gai_src.enc);
}
}
function info_item(nam, val) {
info += "<TR><TD VALIGN=TOP STYLE='padding:0 4px'>" + nam
+ "</TD><TD VALIGN=TOP STYLE='padding:0 4px'>" + val + "</TD></TR>";
}
function ascii(value) {
var len = value.indexOf("\0");
return info_text((len == -1) ? value : value.substr(0, len));
}
function rational(value, digits, unit) {
if(value.d) {
var str = (value.n / value.d).toFixed(digits);
for(var i = str.length - 1; str[i] != "."; i--) {
if(str[i] != "0") {
i++;
break;
}
}
str = str.substr(0, i);
if(unit != undefined)
str += " " + unit;
return str;
}
return "不明";
}
function DateTime(value_dt, value_sub) {
var dt = value_dt.match(/(\d{4}):(\d{2}):(\d{2}) (\d{2}):(\d{2}):(\d{2})/);
if(dt == null)
return "不明";
if(dt[2].charAt(0) == "0")
dt[2] = dt[2].substr(1);
if(dt[3].charAt(0) == "0")
dt[3] = dt[3].substr(1);
if(dt[4].charAt(0) == "0")
dt[4] = dt[4].substr(1);
if(dt[5].charAt(0) == "0")
dt[5] = dt[5].substr(1);
if(dt[6].charAt(0) == "0")
dt[6] = dt[6].substr(1);
var str = dt[1] + "年" + dt[2] + "月" + dt[3] + "日 " + dt[4] + "時" + dt[5] + "分" + dt[6];
if(value_sub != undefined) {
var sub;
if((sub = ascii(value_sub)).length)
str += "." + sub;
}
return str + "秒";
}
// コード変換
// コード変換に "data" URL を使うことができなくなったバージョンへの対応で,
// FileReader を使う処理を追加した.
function conv_text(value, id) {
if(value.length < 8)
return {txt:""};
var str;
var bin;
var i;
switch(value.substr(0, 8)) {
case "ASCII\0\0\0": // ASCII
return {txt:info_text(value.substr(8))};
case "JIS\0\0\0\0\0": // JIS
// JEITA CP-3451A の仕様では「JIS X0208-1990」としか書かれていない.
// JIS X 0201 のラテン文字集合等と組み合わせて使うのか等,詳細は不明.
// ここでは単純に,ISO-2022-JP エンコーディングであるものとして扱うことにする.
if(fr_uc == undefined) {
str = "";
for(i = 8; i < value.length; i++)
str += "%" + ("0" + value.charCodeAt(i).toString(16)).substr(-2);
return {txt:"<SPAN ID='" + id + "'></SPAN>", src:"data:text/plain;charset=ISO-2022-JP," + str};
}
bin = new Uint8Array(value.length - 8);
for(i = 8; i < value.length; i++)
bin[i - 8] = value.charCodeAt(i);
// Firefox 15 より前のバージョンでは,Blob のコンストラクタに TypedArray を渡すとエラーになる.
// ArrayBuffer なら OK なので,ArrayBuffer を取得して渡している.
return {txt:"<SPAN ID='" + id + "'></SPAN>", src:{blb:new Blob([bin.buffer]), enc:"ISO-2022-JP"}};
case "UNICODE\0": // Unicode
str = "";
for(i = 8; i + 1 < value.length; i += 2)
str += String.fromCharCode(get_short(value, i));
return {txt:info_text(str)};
case "\0\0\0\0\0\0\0\0": // Undefined
// PC に依存.ここではシフト JIS と仮定.
if(fr_uc == undefined) {
str = "";
for(i = 8; i < value.length; i++)
str += "%" + ("0" + value.charCodeAt(i).toString(16)).substr(-2);
return {txt:"<SPAN ID='" + id + "'></SPAN>", src:"data:text/plain;charset=Shift_JIS," + str};
}
bin = new Uint8Array(value.length - 8);
for(i = 8; i < value.length; i++)
bin[i - 8] = value.charCodeAt(i);
// Firefox 15 より前のバージョンでは,Blob のコンストラクタに TypedArray を渡すとエラーになる.
// ArrayBuffer なら OK なので,ArrayBuffer を取得して渡している.
return {txt:"<SPAN ID='" + id + "'></SPAN>", src:{blb:new Blob([bin.buffer]), enc:"Shift_JIS"}};
}
return {txt:""};
}
function uc_loaded() {
document.getElementById("info_uc").innerHTML = info_text(this.contentDocument.body.textContent);
};
function gpm_loaded() {
document.getElementById("info_gpm").innerHTML = info_text(this.contentDocument.body.textContent);
};
function gai_loaded() {
document.getElementById("info_gai").innerHTML = info_text(this.contentDocument.body.textContent);
};
function fr_uc_loaded() {
document.getElementById("info_uc").innerHTML = info_text(fr_uc.result);
};
function fr_gpm_loaded() {
document.getElementById("info_gpm").innerHTML = info_text(fr_gpm.result);
};
function fr_gai_loaded() {
document.getElementById("info_gai").innerHTML = info_text(fr_gai.result);
};
function info_text(text) {
elem_esc.textContent = text.replace(/[\x01-\x1f]/g, " ").replace(/ *$/, "");
return elem_esc.innerHTML;
}
// BYTE 取得
function get_byte(data, off) {
return data.charCodeAt(off);
}
// SHORT 取得
var get_short;
// big endian の SHORT 取得
function get_short_be(data, off) {
return (data.charCodeAt(off) << 8) | data.charCodeAt(off + 1);
}
// little endian の SHORT 取得
function get_short_le(data, off) {
return (data.charCodeAt(off + 1) << 8) | data.charCodeAt(off);
}
// LONG 取得
var get_long;
// big endian の LONG 取得
function get_long_be(data, off) {
return data.charCodeAt(off) * 0x1000000
+ ((data.charCodeAt(off + 1) << 16) | (data.charCodeAt(off + 2) << 8) | data.charCodeAt(off + 3));
}
// little endian の LONG 取得
function get_long_le(data, off) {
return data.charCodeAt(off + 3) * 0x1000000
+ ((data.charCodeAt(off + 2) << 16) | (data.charCodeAt(off + 1) << 8) | data.charCodeAt(off));
}
// SLONG 取得
var get_slong;
// big endian の SLONG 取得
function get_slong_be(data, off) {
return (data.charCodeAt(off) << 24) | (data.charCodeAt(off + 1) << 16)
| (data.charCodeAt(off + 2) << 8) | data.charCodeAt(off + 3);
}
// little endian の SLONG 取得
function get_slong_le(data, off) {
return (data.charCodeAt(off + 3) << 24) | (data.charCodeAt(off + 2) << 16)
| (data.charCodeAt(off + 1) << 8) | data.charCodeAt(off);
}
// RATIONAL 取得
function get_rational(data, off) {
return {n:get_long(data, off), d:get_long(data, off + 4)};
}
// SRATIONAL 取得
function get_srational(data, off) {
return {n:get_slong(data, off), d:get_slong(data, off + 4)};
}
// null 終端 ASCII 文字列取得
function get_asciiz(data, off) {
var str = "";
for(; ; ) {
var c;
if((c = data.charAt(off)) == "\0")
return str;
str += c;
if(++off == data.length)
return undefined;
}
}
//----------------------------------------------------------
// TIFF field types
BYTE = 1;
ASCII = 2;
SHORT = 3;
LONG = 4;
RATIONAL = 5;
//SBYTE = 6;
UNDEFINED = 7;
//SSHORT = 8;
//SLONG = 9;
SRATIONAL = 10;
//FLOAT = 11;
//DOUBLE = 12;
SHORT_LONG = 0x10000; // SHORT or LONG
field_size = [0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8];
// 値取得関数テーブル
get_value = [
undefined,
get_byte,
undefined,
undefined, // get_short(endian 確定後に設定)
undefined, // get_long (endian 確定後に設定)
get_rational,
undefined,
undefined,
undefined,
undefined,
get_srational,
undefined,
undefined
];
// TIFF Rev.6.0 IFD
TIFF_tags = [
// Tag Type Count デフォルト
// A. 画像データの構成に関するタグ
[ 256, SHORT_LONG, 1 ], // ImageWidth
[ 257, SHORT_LONG, 1 ], // ImageLength
[ 258, SHORT, 3, [8, 8, 8] ], // BitsPerSample
[ 259, SHORT, 1 ], // Compression
[ 262, SHORT, 1 ], // PhotometricInterpretation
[ 274, SHORT, 1, 1 ], // Orientation
[ 277, SHORT, 1, 3 ], // SamplesPerPixel
[ 284, SHORT, 1, 1 ], // PlanarConfiguration
[ 530, SHORT, 2 ], // YCbCrSubSampling
[ 531, SHORT, 1, 1 ], // YCbCrPositioning
[ 282, RATIONAL, 1, {n:72, d:1} ], // XResolution
[ 283, RATIONAL, 1, {n:72, d:1} ], // YResolution
[ 296, SHORT, 1, 2 ], // ResolutionUnit
// B. 画像の記録位置に関するタグ
[ 273, SHORT_LONG, 0 ], // StripOffsets
[ 278, SHORT_LONG, 1 ], // RowsPerStrip
[ 279, SHORT_LONG, 0 ], // StripByteCounts
// JPEGInterchangeFormat
// JPEGInterchangeFormatLength
// C. 画像データの特性に関するタグ
[ 301, SHORT, 768 ], // TransferFunction Count: 3 * 256
[ 318, RATIONAL, 2 ], // WhitePoint
[ 319, RATIONAL, 6 ], // PrimaryChromaticities
[ 529, RATIONAL, 3, [{n:299, d:1000},
{n:587, d:1000},
{n:114, d:1000}]], // YCbCrCoefficients
[ 532, RATIONAL, 6 ], // ReferenceBlackWhite
// D. その他のタグ
[ 306, ASCII, 20 ], // DateTime
[ 270, ASCII, 0 ], // ImageDescription
[ 271, ASCII, 0 ], // Make
[ 272, ASCII, 0 ], // Model
[ 305, ASCII, 0 ], // Software
[ 315, ASCII, 0 ], // Artist
[33432, ASCII, 0 ], // Copyright
// Exif プライベート タグ
[34665, LONG, 1 ], // Exif IFD
[34853, LONG, 1 ] // GPS IFD
];
I_ImageWidth = 0;
I_ImageLength = 1;
I_BitsPerSample = 2;
I_Compression = 3;
I_PhotometricInterpretation = 4;
I_Orientation = 5;
I_SamplesPerPixel = 6;
I_PlanarConfiguration = 7;
I_YCbCrSubSampling = 8;
I_YCbCrPositioning = 9;
I_XResolution = 10;
I_YResolution = 11;
I_ResolutionUnit = 12;
I_StripOffsets = 13;
I_RowsPerStrip = 14;
I_StripByteCounts = 15;
I_YCbCrCoefficients = 19;
I_ReferenceBlackWhite = 20;
I_DateTime = 21;
I_ImageDescription = 22;
I_Make = 23;
I_Model = 24;
I_Software = 25;
I_Artist = 26
I_Copyright = 27;
I_Exif_IFD = 28;
I_GPS_IFD = 29;
// Exif IFD
Exif_tags = [
// Tag Type Count デフォルト
// A. バージョンに関するタグ
[36864, UNDEFINED, 4, "0221"], // Exif バージョン
[40960, UNDEFINED, 4, "0100"], // 対応フラッシュピックス バージョン
// B. 画像データの特性に関するタグ
[40961, SHORT, 1 ], // 色空間情報
[42240, RATIONAL, 1 ], // 再生ガンマ
// C. 構造に関するタグ
[37121, UNDEFINED, 4 ], // 各コンポーネントの意味
[37122, RATIONAL, 1 ], // 画像圧縮モード
[40962, SHORT_LONG, 1 ], // 実効画像幅
[40963, SHORT_LONG, 1 ], // 実効画像高さ
// D. ユーザ情報に関するタグ
[37500, UNDEFINED, 0 ], // メーカ ノート
[37510, UNDEFINED, 0 ], // ユーザ コメント
// E. 関連ファイル情報に関するタグ
[40964, ASCII, 13 ], // 関連音声ファイル
// F. 日時に関するタグ
[36867, ASCII, 20 ], // 原画像データの生成日時
[36868, ASCII, 20 ], // ディジタル データの作成日時
[37520, ASCII, 0 ], // DateTime のサブセック
[37521, ASCII, 0 ], // DateTimeOriginal のサブセック
[37522, ASCII, 0 ], // DateTimeDigitized のサブセック
// G. 撮影条件に関するタグ
[33434, RATIONAL, 1 ], // 露出時間
[33437, RATIONAL, 1 ], // Fナンバー
[34850, SHORT, 1, 0 ], // 露出プログラム
[34852, ASCII, 0 ], // スペクトル感度
[34855, SHORT, 0 ], // ISO スピード レート
[34856, UNDEFINED, 0 ], // 光電変換関数
[37377, SRATIONAL, 1 ], // シャッター スピード
[37378, RATIONAL, 1 ], // 絞り値
[37379, SRATIONAL, 1 ], // 輝度値
[37380, SRATIONAL, 1 ], // 露光補正値
[37381, RATIONAL, 1 ], // レンズ最小F値
[37382, RATIONAL, 1 ], // 被写体距離
[37383, SHORT, 1, 0 ], // 測光方式
[37384, SHORT, 1, 0 ], // 光源
[37385, SHORT, 1 ], // フラッシュ
[37386, RATIONAL, 1 ], // レンズ焦点距離
[37396, SHORT, 0 ], // 被写体領域 Count: 2 〜 4
[41483, RATIONAL, 1 ], // フラッシュ強度
[41484, UNDEFINED, 0 ], // 空間周波数応答
[41486, RATIONAL, 1 ], // 焦点面の幅の解像度
[41487, RATIONAL, 1 ], // 焦点面の高さの解像度
[41488, SHORT, 1, 2 ], // 焦点面解像度単位
[41492, SHORT, 2 ], // 被写体位置
[41493, RATIONAL, 1 ], // 露出インデックス
[41495, SHORT, 1 ], // センサ方式
[41728, UNDEFINED, 1, "\x03"], // ファイル ソース
[41729, UNDEFINED, 1, "\x01"], // シーン タイプ
[41730, UNDEFINED, 0 ], // CFA パターン
[41985, SHORT, 1, 0 ], // 個別画像処理
[41986, SHORT, 1 ], // 露出モード
[41987, SHORT, 1 ], // ホワイト バランス
[41988, RATIONAL, 1 ], // ディジタル ズーム倍率
[41989, SHORT, 1 ], // 35mm 換算レンズ焦点距離
[41990, SHORT, 1, 0 ], // 撮影シーン タイプ
[41991, SHORT, 1 ], // ゲイン制御
[41992, SHORT, 1, 0 ], // 撮影コントラスト
[41993, SHORT, 1, 0 ], // 撮影彩度
[41994, SHORT, 1, 0 ], // 撮影シャープネス
[41995, UNDEFINED, 0 ], // 撮影条件記述情報
[41996, SHORT, 1 ], // 被写体距離レンジ
// H. その他のタグ
[42016, ASCII, 33 ] // 画像ユニーク ID
];
I_ColorSpace = 2;
I_Gamma = 3;
I_MakerNote = 8;
I_UserComment = 9;
I_RelatedSoundFile = 10;
I_DateTimeOriginal = 11;
I_DateTimeDigitized = 12;
I_SubsecTime = 13;
I_SubsecTimeOriginal = 14;
I_SubsecTimeDigitized = 15;
I_ExposureTime = 16;
I_FNumber = 17;
I_ExposureProgram = 18;
I_SpectralSensitivity = 19;
I_ISOSpeedRatings = 20;
I_OECF = 21;
I_ShutterSpeedValue = 22;
I_ApertureValue = 23;
I_BrightnessValue = 24;
I_ExposureBiasValue = 25;
I_MaxApertureValue = 26;
I_SubjectDistance = 27;
I_MeteringMode = 28;
I_LightSource = 29;
I_Flash = 30;
I_FocalLength = 31;
I_SubjectArea = 32;
I_FlashEnergy = 33;
I_SpatialFrequencyResponse = 34;
I_FocalPlaneXResolution = 35;
I_FocalPlaneYResolution = 36;
I_FocalPlaneResolutionUnit = 37;
I_SubjectLocation = 38;
I_ExposureIndex = 39;
I_SensingMethod = 40;
I_FileSource = 41;
I_SceneType = 42;
I_CFAPattern = 43;
I_CustomRendered = 44;
I_ExposureMode = 45;
I_WhiteBalance = 46;
I_DigitalZoomRatio = 47;
I_FocalLengthIn35mmFilm = 48;
I_SceneCaptureType = 49;
I_GainControl = 50;
I_Contrast = 51;
I_Saturation = 52;
I_Sharpness = 53;
I_DeviceSettingDescription = 54;
I_SubjectDistanceRange = 55;
I_ImageUniqueID = 56;
// GPS IFD
GPS_tags = [
// Tag Type Count デフォルト
// A. GPS に関するタグ
[ 0, BYTE, 4, [2, 2, 0, 0]], // GPS タグのバージョン
[ 1, ASCII, 2 ], // 北緯(N) or 南緯(S)
[ 2, RATIONAL, 3 ], // 緯度(数値)
[ 3, ASCII, 2 ], // 東経(E) or 西経(W)
[ 4, RATIONAL, 3 ], // 経度(数値)
[ 5, BYTE, 1, 0 ], // 高度の基準
[ 6, RATIONAL, 1 ], // 高度(数値)
[ 7, RATIONAL, 3 ], // GPS 時間(原子時計の時間)
[ 8, ASCII, 0 ], // 測位に使った衛星信号
[ 9, ASCII, 2 ], // GPS 受信機の状態
[10, ASCII, 2 ], // GPS の測位方法
[11, RATIONAL, 1 ], // 測位の信頼性
[12, ASCII, 2, "K" ], // 速度の単位
[13, RATIONAL, 1 ], // 速度(数値)
[14, ASCII, 2, "T" ], // 進行方向の単位
[15, RATIONAL, 1 ], // 進行方向(数値)
[16, ASCII, 2, "T" ], // 撮影した画像の方向の単位
[17, RATIONAL, 1 ], // 撮影した画像の方向(数値)
[18, ASCII, 0 ], // 測位に用いた地図データ
[19, ASCII, 2 ], // 目的地の北緯(N) or 南緯(S)
[20, RATIONAL, 3 ], // 目的地の緯度(数値)
[21, ASCII, 2 ], // 目的地の東経(E) or 西経(W)
[22, RATIONAL, 3 ], // 目的地の経度(数値)
[23, ASCII, 2, "T" ], // 目的地の方角の単位
[24, RATIONAL, 1 ], // 目的の方角(数値)
[25, ASCII, 2, "K" ], // 目的地までの距離の単位
[26, RATIONAL, 1 ], // 目的地までの距離(数値)
[27, UNDEFINED, 0 ], // 測位方式の名称
[28, UNDEFINED, 0 ], // 測位地点の名称
[29, ASCII, 11 ], // GPS 日付
[30, SHORT, 1 ] // GPS 補正測位
];
I_GPSLatitudeRef = 1;
I_GPSLatitude = 2;
I_GPSLongitudeRef = 3;
I_GPSLongitude = 4;
I_GPSAltitudeRef = 5;
I_GPSAltitude = 6;
I_GPSTimeStamp = 7;
I_GPSSatellites = 8;
I_GPSStatus = 9;
I_GPSMeasureMode = 10;
I_GPSDOP = 11;
I_GPSSpeedRef = 12;
I_GPSSpeed = 13;
I_GPSTrackRef = 14;
I_GPSTrack = 15;
I_GPSImgDirectionRef = 16;
I_GPSImgDirection = 17;
I_GPSMapDatum = 18;
I_GPSDestLatitudeRef = 19;
I_GPSDestLatitude = 20;
I_GPSDestLongitudeRef = 21;
I_GPSDestLongitude = 22;
I_GPSDestBearingRef = 23;
I_GPSDestBearing = 24;
I_GPSDestDistanceRef = 25;
I_GPSDestDistance = 26;
I_GPSProcessingMethod = 27;
I_GPSAreaInformation = 28;
I_GPSDateStamp = 29;
I_GPSDifferential = 30;
ResolutionUnit_str = [];
ResolutionUnit_str[2] = "DPI"; ResolutionUnit_str[3] = "ドット/cm";
ColorSpace_str = {1:"sRGB", 0xffff:"Uncalibrated"};
ExposureProgram_str = ["", "マニュアル", "通常プログラム", "絞り優先", "シャッター優先",
"creative プログラム", "action プログラム", "人物モード", "風景モード"];
MeteringMode_str = [undefined, "平均", "中央重点", "スポット", "マルチ スポット", "分割測光", "部分測光"];
MeteringMode_str[255] = "その他";
LightSource_str = [];
LightSource_str[1] = "昼光"; LightSource_str[2] = "蛍光灯"; LightSource_str[3] = "タングステン";
LightSource_str[4] = "フラッシュ";
LightSource_str[9] = "晴天"; LightSource_str[10] = "曇天"; LightSource_str[11] = "日陰";
LightSource_str[12] = "昼光色蛍光灯"; LightSource_str[13] = "昼白色蛍光灯"; LightSource_str[14] = "白色蛍光灯";
LightSource_str[15] = "温白色蛍光灯";
LightSource_str[17] = "標準光 A"; LightSource_str[18] = "標準光 B"; LightSource_str[19] = "標準光 C";
LightSource_str[20] = "D55"; LightSource_str[21] = "D65"; LightSource_str[22] = "D75"; LightSource_str[23] = "D50";
LightSource_str[24] = "ISO studio tungsten";
LightSource_str[255] = "その他";
SensingMethod_str = [undefined, "", "単板カラー センサ", "2 板カラー センサ", "3 板カラー センサ",
"色順次カラー センサ", undefined, "3 線リニア センサ", "色順次リニア センサ"];
FileSource_str = ["その他", "透過型スキャナ", "反射型スキャナ", "DSC"];
CFA_str = ["RED", "GREEN", "BLUE", "CYAN", "MAGENTA", "YELLOW", "WHITE"];
CustomRendered_str = ["通常処理", "特殊処理"];
ExposureMode_str = ["自動", "マニュアル", "オート ブラケット"];
WhiteBalance_str = ["自動", "マニュアル"];
SceneCaptureType_str = ["標準", "風景", "人物", "夜景"];
GainControl_str = ["なし", "弱い増感", "強い増感", "弱い減感", "強い減感"];
Contrast_str = ["標準", "軟調", "硬調"];
Saturation_str = ["標準", "低彩度", "高彩度"];
Sharpness_str = ["標準", "弱い", "強い"];
SubjectDistanceRange_str = [undefined, "マクロ", "近景", "遠景"];
LatitudeRef_str = {"N":"北緯", "S":"南緯"};
LongitudeRef_str = {"E":"東経", "W":"西経"};
GPSStatus_str = {"A":"測位中", "V":"未測位(中断中)"};
GPSMeasureMode_str = {"2":"2 次元測位中", "3":"3 次元測位中"};
GPSSpeedRef_str = {"K":"km/h", "M":"mi/h", "N":"ノット"};
DirectionRef_str = {"T":"真方位", "M":"磁気方位"};
GPSDestDistanceRef_str = {"K":"km", "M":"mi", "N":"海里"};
GPSDifferential_str = ["単独測位", "Differential 補正測位"];
elem_back = document.getElementById("back");
elem_file = document.getElementById("file");
elem_cont = document.getElementById("cont");
elem_img_win = document.getElementById("img_win");
elem_img = document.getElementById("img");
elem_size = document.getElementById("size");
elem_fit = document.getElementById("fit");
elem_org = document.getElementById("org");
elem_shr = document.getElementById("shr");
elem_cur_fact = document.getElementById("cur_fact");
elem_fact = document.getElementById("fact");
elem_info_win = document.getElementById("info_win");
elem_msg = document.getElementById("msg");
elem_cvt_uc = document.getElementById("cvt_uc");
elem_cvt_gpm = document.getElementById("cvt_gpm");
elem_cvt_gai = document.getElementById("cvt_gai");
elem_esc = document.createElement("SPAN");
factor = 0.5; // 縮小割合 初期値 50%
resize();
elem_fact.onkeypress = fact_keypress;
if(typeof Blob == "function") {
fr_uc = new FileReader();
fr_uc.onload = fr_uc_loaded;
fr_gpm = new FileReader();
fr_gpm.onload = fr_gpm_loaded;
fr_gai = new FileReader();
fr_gai.onload = fr_gai_loaded;
}
else {
fr_uc = undefined;
}
document.forms[0].reset(); // ページを再ロードしたときのため
//-->
</SCRIPT>
</BODY>
</HTML>
|