// 計測する画像に関するクラス class currentImageClass { PImage img; String fullpathname; // 開いている画像ファイルのフルパス名 double scale; // 画像の拡大率 :注意 計測中にも変更できるが,計測精度が落ちる恐れがある.読み込み前に変更するか,再読み込みする boolean folder_mode; // フォルダーモード時,true; File[] files; // フォルダーモード:ファイルリスト int f_no; // フォルダーモード時の読みだし位置 int filter_no; // -1 : なし,0 : GRAY, 1 : INVERT int _counter; // 計測済みデータ数 pointDataClass [] measured = new pointDataClass[Max_measure]; targetMarkerClass target; // コンストラクター currentImageClass() { img = null; fullpathname = null; _counter = 0; scale = Initial_scale; // フォルダーモード関係 folder_mode = false; files = null; f_no = 0; filter_no = -1; // 計測データ領域の初期化 for (_counter = 0; _counter < Max_measure; _counter++) measured[_counter] = new pointDataClass(); // ターゲットマーカーの初期化 target = new targetMarkerClass(); } // 画像ファイルの読み込み PImage load(String path) { boolean reload = false; PImage img0; if (path == null) reload = true; if (! reload) fullpathname = path; if ((img0 = loadImage(fullpathname)) == null) return null; // 読み込み失敗時 // 読み込み完了 img = img0; println("Loaded image: " + fullpathname); if (scale != 1.0) { // 画像を拡大する場合 img.resize((int)(img.width * scale), (int)(img.height * scale)); } surface.setSize(img.width, img.height); if (! reload) _counter = 0; return img; } // 再読み込み PImage reload() { if (fullpathname == null) return null; // 異常な状態 return load(null); } // 計測データの格納 int measure(int x, int y) { if (_counter >= Max_measure) return _counter; // 異常な状態 measured[_counter].px = x; measured[_counter].py = y; measured[_counter].get_color(img); if (++_counter >= Max_measure) { // 最大計測数に達した場合 ci.export_data(); open_fileselector(); } return _counter; } // 計測取り消し int back() { if (--_counter < 0) _counter = 0; return _counter; } // ファイルへ出力 void export_data() { int cnt = 0; String dest_filename; PrintWriter output; dest_filename = fullpathname + Export_ext; // 拡張子の分解は面倒くさいので,単純に拡張子を追加する output = createWriter(dest_filename); if (output != null) { output.println("Scale: " + scale); for (cnt = 0; cnt < ci._counter; cnt++) { output.print(cnt + "\t" + ci.measured[cnt].px + "\t" + ci.measured[cnt].py); output.println("\t" + (int)red(ci.measured[cnt].c) + "\t" + (int)green(ci.measured[cnt].c) + "\t" + (int)blue(ci.measured[cnt].c)); } output.flush(); output.close(); println("Completed exporting datas to " + dest_filename); } else println("Error: Can't open file =" + dest_filename); } // 計測済みデータの出力 void flush_data() { if (ci.img != null && ci._counter > 0) export_data(); // 中断して次のファイルを選択した際に,計測済みのデータを出力する ci.img = null; } // フォルダーモードの開始 void open_folder(File [] f) { files = f; f_no = 0; folder_mode = true; println("[Folder mode]:Start"); if (next_image(true) == null) { // 次の画像ファイルが存在しなかった場合 quit_folder_mode(); } } // 次の画像を表示(フォルダーモード) PImage next_image() { return next_image(false); } PImage next_image(boolean first) { PImage ret = null; if (! first) f_no++; // 初回以外は最初にカウントアップする:次の画像だから for (; f_no < files.length; f_no++) { if (files[f_no].getPath().endsWith(Export_ext)) continue; // データファイルは読み飛ばす(ワーニングが少しは減る) if ((ret = loadImage(files[f_no].getAbsolutePath())) != null) break; } if (ret == null) return null; // 最後のファイルに到達(存在しない) ret = load(files[f_no].getAbsolutePath()); return ret; } void quit_folder_mode() { folder_mode = false; img = null; println("[Folder mode]:Quit"); } // 画像の拡大率変更 void rescale(double rate) { double pre_scale = scale; if (rate == 0.0) { if (scale == Initial_scale) return; // 初期値で変更なしの場合 else scale = Initial_scale; // 初期化 } else { scale *= rate; // if (scale < Initial_scale) scale = Initial_scale; } // 既に計測済みの場合はスケールを変換する if (_counter > 0) { int n; for (n = 0; n < _counter; n++) { measured[n].px = (int)(measured[n].px / pre_scale * scale); measured[n].py = (int)(measured[n].py / pre_scale * scale); } } println("Change scale " + pre_scale + " -> " + scale); reload(); // 画像の再読み込み } // フィルターの変更 void change_filter() { if (++filter_no > 1) filter_no = -1; } void apply_filter() { if (filter_no >= 0) filter(filter_type[filter_no]); } } // 計測するデータに関するクラス class pointDataClass { int px, py; // X, Y座標 color c; // 色 pointDataClass() { px = py = -1; // 特に意味はない } void get_color(PImage img) { c = img.pixels[px + py * img.width]; } } // ターゲットマーカーに関するクラス class targetMarkerClass { char mode; // 0: none, 1: cross, 2: circle, 3: poiont int size; int t_color; // 0, 1, 2 targetMarkerClass() { mode = 1; size = Target_size; } // ターゲットマーカーの形状を変更 void change_shape() { if (++mode > 3) mode = 0; } // ターゲットマーカーの色を変更 void change_color() { if (++t_color > 2) t_color = 0; } void plot(int x, int y) { stroke(Target_color[t_color][0], Target_color[t_color][1], Target_color[t_color][2]); noFill(); switch (mode) { case 0 : break; case 1 : line(x - size, y, x + size, y); line(x, y - size, x, y + size); break; case 2 : ellipse(x, y, size * 2, size * 2); break; case 3 : rectMode(CENTER); rect(x, y, 3, 3); break; default : mode = 0; } } }