2011年9月9日金曜日

C#言語のみを使って開発されたOS「Cosmos」

C#言語のみを使ってCosmosというOSが開発されたとのこと。C言語は一切使用されていないという。
 
現段階ではコンパイルと実行にマイクロソフト社のVisual Studioが必要であるが、ソースコードのコンパイルはExpress版でもできるとのこと。近日中にVB.NETサポートが追加されるそうだ。
 
 

Eclipseでデバッグ

ブレークポイント
ブレークポイントは、実行時にその位置に来る(あるいは指定された状況が発生する)と実行が停止(中断)されるもの。
以下のような方法でブレークポイントを設定・削除できる。
* Javaソースの各行の左側をダブルクリックすると、ブレークポイントが設定される(ブレークポイントのマークをダブルクリックすると削除される)。
* Ctrl+Shift+Bで、現在のカーソルがある行にブレークポイントが設定される(ブレークポイントがあれば削除される)。
* メニューバーの「実行(R)」→「ブレークポイントの切り替え(K)」で、現在のカーソルがある行にブレークポイントが設定される(ブレークポイントがあれば削除される)。
現在どのようなブレークポイントが設定されているかは、ブレークポイントビューで確認できる。
* (「Java」パースペクティブ)メニューバーの「ウィンドウ(W)」→「ビューの表示(V)」→「その他(O)」⇒「デバッグ」→「ブレークポイント」
* (「デバッグ」パースペクティブ)メニューバーの「ウィンドウ(W)」→「ビューの表示(V)」→「ブレークポイント」
ブレークポイントビューに表示されている各ブレークポイントを右クリックしてプロパティーを表示することで、細かい設定をすることも出来る。

デバッグ実行(開始)
普通にmain()で始まるプログラム(直接Eclipseから実行できるプログラム)をデバッグする(ブレークポイントで止まるような実行をする)為には、デバッグモードで実行する必要がある。
* メニューバーの「実行(R)」→「デバッグ(G)」
* ツールバーの「デバッグ」ボタン

リモートデバッグ
Eclipse上から実行しないJavaプログラム(つまりバッチやシェル等から実行するJavaプログラム)もデバッグすることが出来る。
1. 実行時のjavaコマンドの引数にリモートデバッグ用のオプションを指定する。
2. Eclipseのリモートデバッグを実行する。
3. すると、Eclipse上で設定したブレークポイントに従ってデバッグできる。

javaコマンドのリモートデバッグ用オプション
JDK1.4
java -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y 実行クラス
java -Xrunjdwp:help
JDK1.5以降
java -agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=y 実行クラス
java -agentlib:jdwp=help

Eclipseで外部Javaアプリのデバッグをする(デバッグ情報を受け取る)には、以下のようにデバッグ実行する。
1. パッケージ・エクスプローラーで、デバッグしたいクラス(jarファイル)が含まれているプロジェクトを選択する。
2. メニューバーの「実行(R)」→「デバッグの構成(B)」で「デバッグ構成」ダイアログを開く。
3. 左ペインの「リモートJavaアプリケーション」を右クリックし、「新規」を選ぶ。
4. 「接続プロパティー(E)」の「ポート」に、JDWPのaddressで指定したポートを設定する。
5. 設定したリモートデバッグを実行する。

デバッグ操作
実行が停止(実行中断)されると、Eclipse上で色々操作することが出来る。

Shift + F5
ステップ・フィルターの有効・無効を切り替える。
ステップ・フィルターは、ステップ実行(?)で入る必要の無いクラスを指定するもの。java.*とかjavax.*等を想定しているらしい。
メニューバーの「ウィンドウ(W)」→「設定(P)」⇒「Java-デバッグ-ステップ・フィルター」でフィルターしたいクラスを指定する。
全てのインスタンス
 
ソース上でクラスを選択して右クリック→「すべてのインスタンス(T)」
Ctrl + Shift + N
指定されたクラスのインスタンスを全て表示する。
強制リターン
 
(ソース上で値を選択して)右クリック→「強制リターン(F)」
Alt + Shift + F
(Eclipse3.3からの新機能で、JDK1.6以降でしか使えないらしい)
現在のメソッドから即座にreturnする。
ソース上で選択していた箇所の値が戻り値となる。型が違っていたらエラーになってreturnできない。
戻り型がvoidのメソッドの場合は特に値を指定する必要は無い。
監視
 
ソース上で変数(や式)を選択して右クリック→「監視(T)」
 
選択した変数や計算式を「式」ビューに("監視式"として)追加する。
インスペクション
 
ソース上で変数や式を選択して右クリック→「インスペクション(E)」
Ctrl + Shift + I
選択した式の演算結果をポップアップで表示する。
ここでCtrl+Shift+Iを押すと、選択している式が「式」ビューに("インスペクション式"として)追加される。
※選択した式の中にメソッドがあれば、それも実行されるので注意
表示
 
ソース上で変数や式を選択して右クリック→「表示(Y)」
Ctrl + Shift + D
選択した式の演算結果をポップアップで表示する。
ここでCtrl+Shift+Dを押すと、選択している式と演算結果が「表示」ビューに表示される。
※選択した式の中にメソッドがあれば、それも実行されるので注意
実行
 
ソース上で式や文を選択して右クリック→「実行(X)」
Ctrl + U
選択した式や文を実行する。
(メソッドを呼び出したり変数に値をセットしたり出来る)
(ただし、return文を実行してもメソッドから抜けるわけではない)
指定行まで実行
 
ソース上の行を右クリック→「指定行まで実行(L)」
Ctrl + R
実行を再開し、ソース上のカーソルがある行(=指定行)まで来たら停止する。
(途中で他のブレークポイントにより停止することもある)
(if文等による分岐で指定行を通らない場合は、そのまま処理が続行されてゆく…)
ステップ実行中にfor文等のループに来て、そこを抜けたい場合に便利。
インスペクションと表示は機能が似ているので、使い分けがいまいち分からないが…。

「変数」ビュー
現在のメソッドから参照できる変数(ローカル変数・フィールド等)全ての値を一覧表示するビュー。
デバッグパースペクティブではデフォルトで表示される(と思う)が、メニューバーの「ウィンドウ(W)」→「ビューの表示(V)」→「変数」で表示することが出来る。
変数名に対しその値が表示される。プリミティブ型やStringの場合は、中身がそのまま表示される。
それ以外の参照型の場合はクラス名が表示される。この場合、変数名の欄が折りたたみになってフィールドが表示できるようになっているので、それを追っていけば中を確認することが出来る。
また、下部のペインに(たぶんtoString()を呼んだ結果の)値が表示される。
また、右クリック→「監視式の作成(T)」で「式」ビューに監視式として追加することも出来る。
「変数」ビューでは、プリミティブ型やStringの場合、値欄をクリックすれば値を変更することが出来る。
それ以外の参照型の場合でも、右クリック→「値の変更(C)」で値を変更することが出来る。
例えばString配列なら「new String[]{ "abc", "def" }」といった具合。

「式」ビュー
監視式やインスペクション式を表示するビュー。
メニューバーの「ウィンドウ(W)」→「ビューの表示(V)」→「式」で表示することが出来る。
変数や式を「式」ビューに追加しておくと、それらが一覧表示される。
個々の式を選択すると、右側にその値が表示される。参照型の場合、たぶんtoString()を呼んだ結果が返る。
監視式の追加は、右クリック→「監視式を追加(A)」や、インスペクション操作から行う。
インスペクション式の場合、右クリック→「監視式に変換(W)」で監視式に変更できる。
式には「変数のみ」だけでなく、演算やメソッド呼び出し、果ては文を書くことも出来る。
例えばMapの変数mapに対し、以下のような監視式が定義できる。
map
map.size()
new java.util.TreeMap(map)
StringBuilder sb = new StringBuilder();
for (Object key : map.keySet()) {
if (sb.length() > 0) sb.append(", ");
sb.append(key);
sb.append("=\"");
sb.append(map.get(key));
sb.append("\"");
}
return sb;
なお、変数は、現在表示中のメソッドのスコープから見られる変数が使われる。
(つまり、同名の変数であっても、デバッグ中のメソッドによってはローカル変数だったり親クラスのフィールドだったりする)
監視式の削除はDeleteキーまたは右クリック→「除去(O)」で行える。

「表示」ビュー
変数の内容や式の演算結果を一時的に表示するビュー。
表示する操作を行えば自動的に出てくるが、メニューバーの「ウィンドウ(W)」→「ビューの表示(V)」→「 表示」で表示することも出来る。
表示ビューの中は自由に編集する(Javaソースを書く)ことが出来る。
そして、ここで書いたソースも(選択して右クリックからメニューを開くことにより)インスペクション・表示・実行・監視・強制リターンに使うことが出来る!
変数の値を変更する例
n = 1
↑表示ビューに上記の内容を書いて全選択(Ctrl+A)して実行(Ctrl+U)すると、変数に値をセットすることが出来る。
新しいオブジェクトを作って強制リターンする例
Map m = new HashMap();
m.put("ZZZ", "zzz");
returm m;
↑Mapを返すメソッドの中で停止させ、表示ビューに上記の内容を書いて全選択(Ctrl+A)して強制リターンさせると、このマップを返した状態になる。
例外を発生させる例
throw new RuntimeException("zzz");
↑全選択(Ctrl+A)して実行(Ctrl+U)すると、例外を発生させることが出来る。
 その際の(スタックトレースの)例外発生箇所は、デバッグで停止していた行になる。

2011年9月8日木曜日

画像ファイルから読み込む方法

画像ファイルからImageを取得するには、ImageIO#read()を使用する。
内部で画像ファイルの種類を自動的に判断して読んでくれるらしい。
なお、画像として不正なファイル(対応していない種類の画像)だったときは例外は発生せず、nullが返る。

対応状況

種類

JDK1.4

JDK1.5

ビットマップ

bmp

×

 

png

jpeg

jpg

GIF

gif

 

パターン

コーディング例

File

import java.awt.Image;
import javax.imageio.ImageIO;
        public static Image loadImage(File f) {
               try {
                       BufferedImage img = ImageIO.read
(f);
                       return img;
               } catch (IOException e) {
                       throw new RuntimeException(e);
               }
        }

InputStream

        public static Image loadImage(String fileName) {
               InputStream is = null;
               try {
                       is = new FileInputStream(fileName);
                       BufferedImage img = ImageIO.read(is);
                       return img;
               } catch (IOException e) {
                       throw new RuntimeException(e);
               } finally {
                       if (is != null) try { is.close(); } catch (IOException e) {}
               }
        }

URL

        public static Image loadImage(String url) {
               try {
                       URL u = new URL(url);
                       BufferedImage img = ImageIO.read(u);
                       return img;
               } catch (IOException e) {
                       throw new RuntimeException(e);
               }
        }

他に、ToolKitを使う方法もあるようだ。[2010-01-08]

import java.awt.Toolkit;
               Image img = Toolkit.getDefaultToolkit().createImage(name);
               return img;

nameの型はString・URL・byte[]等。
また、ToolKit#getImage()というメソッドもある。こちらは画像インスタンスがバッファリングされる(同一の画像であれば同じインスタンスを返す)らしい。

新しい画像を作る方法

任意のサイズの新しい画像を作るには、BufferedImageを使用する。

import java.awt.Image;
import java.awt.image.BufferedImage;
        public static Image createImage(int width, int height) {
               return new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        }

TYPE_*_RGBを指定すると、Graphics#drawImage()を使った際にそのままGraphicsに描画される。[2007-02-26]
TYPE_*_ARGB(アルファ付き)を指定すると、RGB値が0のドットは透明色として扱われ、その部分は元のGraphicsの色が残る。

JDK1.5からはBufferedImagegetTransparency()というメソッドが追加された。
これが返す値により、透明色が扱えるかどうか判断できる。
返る値はOPAQUE(完全に不透明)、TRANSLUCENT(透明が使える)等。(この定数はTransparencyで定義されているが、Colorにも継承されている)
 

表示されている画面を取得する方法

現在 画面に表示されている内容を、そのまま取得(キャプチャー)することが出来る。
WindowsのPrint Screenキーに相当。

import java.awt.Rectangle;
import java.awt.Robot;
        public static Image captureScreen(int x, int y, int w, int h) throws AWTException {
               Robot robot = new Robot();
               Image img = robot.createScreenCapture(new Rectangle(x, y, w, h));
               return img;
        }

なお、画面サイズはToolkit#getScreenSize()で取得できる。

import java.awt.Dimension;
import java.awt.Toolkit;
        public static Image captureScreen() {
               Dimension sz = Toolkit.getDefaultToolkit().getScreenSize();
 
               try {
                       Robot robot = new Robot();
                       Image img = robot.createScreenCapture(new Rectangle(0, 0, sz.width, sz.height));
                       return img;
               } catch (AWTException e) {
                       throw new RuntimeException(e);
               }
        }

画像を加工する方法

Imageを加工するには、Graphicsを取得し、それに対して描画してやればよい。

黒で埋める例:

import java.awt.Graphics;
        public static void fill(Image img) {
               int w = img.getWidth(null);    //Imageの幅
               int h = img.getHeight(null);   //Imageの高さ
 
               Graphics g = img.getGraphics();
               g.setColor(Color.BLACK);              //黒
               g.fillRect(0, 0, w, h);
               g.dispose();
        }

BufferedImageの場合は、setRGB()で直接RGBコードを指定できる。
BufferedImageにアルファが指定されている場合、RGB値が0だと透明なドットとして扱われる。

指定された色を透明色に変更する例:

        public static void changeTransparent(BufferedImage img, Color c) {
               int w = img.getWidth();        //BufferedImageの幅
               int h = img.getHeight();       //BufferedImageの高さ
               int t = c.getRGB();    //透明色に変換する色のRGB値
 
               //RGB値を0(透明色)に置換
               for (int y = 0; y < h; y++) {
                       for (int x = 0; x < w; x++) {
                               if (img.getRGB(x, y) == t) img.setRGB(x, y, 0);
                       }
               }
        }

ImageをBufferedImageに変換する方法

BufferedImageのコンストラクターにImageをとるものがあればいいんだけど、そういうのは無いようだ(苦笑) [2010-01-08]

一番単純なのは、Graphicsを経由してコピー(描画)してやる方法。

(この方法だと、アルファ(透明色)とかの設定は引き継げないが)

           public static BufferedImage createBufferedImage(Image img) {

                      BufferedImage bimg = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);

 

                      Graphics g = bimg.getGraphics();

                      g.drawImage(img, 0, 0, null);

                      g.dispose();

 

                      return bimg;

           }

BufferedImageの一部分から新しいBufferedImageを作りたい場合は、専用のメソッドがある。

               BufferedImage simg = bimg.getSubimage(x, y, w, h);

画像をダイアログで表示する

どんな画像なのかを確認したい場合、アプレットならGraphicsが取得できるのでそこにImageを描画(コピー)すればよいが、Graphicsを持たないアプリケーションでもダイアログを使って表示してみることが出来る。

メッセージ表示ダイアログではアイコンを自分で指定できるので、Imageからアイコンを作ってそれを表示してやる。

           public static void showImageDialog(Image img) {

                      Icon icon = new ImageIcon(img);

 

                      JOptionPane.showMessageDialog(null,

                                  "←イメージ",                //メッセージ

                                  "イメージ確認",             //タイトル

                                  JOptionPane.PLAIN_MESSAGE,

                                  icon                            //画像のアイコン

                      );

           }

※(JDK1.4までは)ウィンドウアプリ以外からダイアログを使う場合のお約束として、main()の最後でSystem.exit()が必要。

 

画像をファイルに保存する例

BufferedImageは簡単にファイルに保存することが出来る。[2007-12-29]

ImageIO#write()でRenderedImageをファイル(File)やストリーム(OutputStream)に出力する。

RenderedImageはインターフェースで、BufferedImageはそれをimplementsしている。(Imageはダメ)

           public static void save(BufferedImage img, File f) throws IOException {

                      if (!ImageIO.write(img, "PNG", f)) {

                                  throw new IOException("フォーマットが対象外");

                      }

           }

           /**

            * BufferedImageをバイト配列に変換する例. [2010-01-08]

            * @param img イメージ

            * @return バイト配列

            * @throws IOException 変換できなかった場合

            */

           public static byte[] getBytes(BufferedImage img) throws IOException {

                      ByteArrayOutputStream bos = new ByteArrayOutputStream();

                      if (!ImageIO.write(img, "PNG", bos)) {

                                  throw new IOException("フォーマットが対象外");

                      }

                      return bos.toByteArray();

           }

2引数は画像の形式(フォーマット)を文字列で指定する。

どんなフォーマット文字列がサポートされているかは 以下のようにして確認できる。

                      String[] fs = ImageIO.getWriterFormatNames();

                      System.out.println(Arrays.toString(fs));

JDK1.6の場合:

[BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif]