画像ビューアを開発しているのですが、
画像処理した後にJpegとして保存すると赤っぽくなっていた原因が分かった。
Javaのせいにしてたけど、完全なミスでした。^^;

Java6でImageIOを使ってjpeg,gif,png,bmpと保存できるようになったけど、注意点が必要。

元ソースが「TYPE_INT_ARGB」の場合の話です。

png (32bitフルカラー・インデックスカラーに対応)
どんなカラーモデルでも保存可能
α値つきの32ビットのColorModelでもOK。なんでもOK。
IndexColorModelでも可能。透明色指定も可能。
但しIndexColorModelの場合ビットが8に固定される?
使用されている色が256以下なら、IndexColorModelで保存したほうがいいのかな。

jpg/jpeg (24bitフルカラーのみ対応※・グレイスケール(TYPE_BYTE_GRAY)は試してないです)
TYPE_INT_ARGB の場合、保存できるが赤っぽくなる※。
保存する場合に、ColorConvertOpのfilterを使って、TYPE_INT_RGBに変換が必要。
IndexColorModelは試してないからわからない。
仕様上、透明色の指定は不可能。

bmp (24bitフルカラー・インデックスカラーに対応)
TYPE_INT_ARGB の場合、32ビットってのもbmpとして可能そうなんだけど、保存失敗します。
TYPE_INT_RGBに変換するか、IndexColorModelのBufferedImageを作成する。
仕様上、透明色の指定は不可能。

gif (インデックスカラーのみ対応)
TYPE_INT_ARGB の場合、保存不可能。
TYPE_INT_RGBへ変換すると、自動的に256色に減色してくれる。(但し、α値の透明色は無視される。)
透明色を指定したい場合は、自分で減色して、透明色つきのIndexColorModelのBufferedImageを作成すること。

こんな感じ。

保存するだけなら「TYPE_INT_RGB」に変換することで、
jpeg,gif,png,bmp一応全ての拡張子として保存できるんだけど。

実際に、それぞれ特性をいかした保存形式で保存しようと思うと、
カラーモデルを考えないといけないから結構面倒。

一応、今回の更新で、これらは全て使えるようにしてみました。

ちなみに、BufferedImageのgetType() で、いま「TYPE_INT_RGB」なのか「TYPE_INT_ARGB」なのか、
getColorModel()で、「IndexColorModel」なのか普通の「ColorModel」なのか調べることが出来ます。

おさらい
TYPE_INT_ARGB … 通常こっちかな、透明色・赤・緑・青 の順番
TYPE_INT_RGB … 保存する場合は何も考えなくていいから楽。
TYPE_BYTE_INDEXED … GIF画像とかインデックスカラーの画像を作るときこっち。
TYPE_BYTE_GRAY … 試してないけど、jpegでグレイスケールで保存できるのかな。
TYPE_BYTE_BINARY … 試してないけど、wbmpで保存できるのかな。

もう一度、保存読み込みして、確認してみたんだけど、どうやらImageIOはTYPE_INT_ARGBの場合
透明度情報も含めたjpegで保存してくれることが分かった。
透明度をjpegに含めるって、仕様上やっていいのかな。よくわかんない。Flashは対応してるらしい。
それで、対応していないソフト?は赤っぽく表示してしまったというわけ。
透明度もたせた画像形式って可逆圧縮のpngしかないから、
Javaのゲームとかでフルカラー+透明度の画像を用意したい時は、
アルファチャンネル付きのjpegで保存しておくっていうのも手かもしれない。


2009年7月26日追記

画像の読み書きのサンプルを作ったので、どうぞ利用してみてください。自由に使ってもらって結構です。
画像をファイルとして読み書きする

たぶん、Java1.6には、IndexColorModelで保存するときにバグ?があるかもしれません。
例えば、0番以外を、透明色に指定した場合、うまく画像が保存できません。
また、透明色の黒と、透明色ではない黒が、存在するときもうまく保存できないようです。
あと、IndexColorModelでbmp保存すると、うまく保存できません。
誰か原因分かるかいたら教えてください。


2010年2月26日追記

関連記事を書きました。
「BufferedImage」の TYPE_4BYTE_ABGR から TYPE_INT_ARGB にする方法
「BufferedImage」の TYPE_BYTE_GRAY から TYPE_BYTE_INDEXED にする方法

関連記事

  • ビューア開発 – バイラテラルフィルタ追加しましたビューア開発 – バイラテラルフィルタ追加しました 前々から追加追加しようと思って、初めて作ってみた。 日本語の資料がtpotさんのバイラテラルフィルタしかなくて、勉強するのが大変でした。 海外のサイトはもっとよくわかんない謎の式だらけ。 要約すると、バイラテラルフィルタってのは、注目画素の輝度と、フィルタ処理する時の近傍画素の輝度の差(距離)を マイナスの係数をかけて、指数関数の中れたもの を A […] Posted in ツール制作
  • Bresenhamアルゴリズムで線分の計算は早いのかなBresenhamアルゴリズムで線分の計算は早いのかな 以前、直線を描くのにこんなのを作った。 特に工夫点もない、素直な方法である。 #module "linem" #deffunc line2 int line_x1,int line_y1,int line_x2,int line_y2 line_xabs = abs(line_x1-line_x2) line_yabs = […] Posted in アルゴリズム
  • Javaで3Dゲーム開発日記 part5 画像補間Javaで3Dゲーム開発日記 part5 画像補間 以前の続きでテクスチャのパーリンノイズの補間法の話です。 いい加減補間について調べようといろいろとプログラムして作ってみました。 テクスチャなので、上下と左右が繋がるように補間します。 8x8px → 256x256px […] Posted in ゲーム制作
  • 「BufferedImage」の TYPE_4BYTE_ABGR から TYPE_INT_ARGB にする方法「BufferedImage」の TYPE_4BYTE_ABGR から TYPE_INT_ARGB にする方法 Java の BufferedImage は getType() を使うことでタイプを知ることが出来ます。 byte型でABGRの順に記録されている場合は、BufferedImage.TYPE_4BYTE_ABGR int型でARGBが記録されている場合は、BufferedImage.TYPE_INT_ARGB になります。 TYPE_4BYTE_ABGR […] Posted in プログラミング
  • SMFプレイヤーをつくろう!リベンジ「セットテンポと分解能」SMFプレイヤーをつくろう!リベンジ「セットテンポと分解能」 以前(2007/4/30)、HSPでMCI(Media Control Interface)を利用せずに SMF(スタンダードMIDIファイル .mid)を再生するためのモジュールを作ってSMFプレーヤーを作りました。(ここ) しかし実はこれには色々と問題が山積みになっていたりする。 1. なんかメタイベント,SysExイベントが正常に送れていないっぽい? 2. […] Posted in ツール制作
  • Eclipseから実行可能JAR作成とProGuardの難読化の一連の流れEclipseから実行可能JAR作成とProGuardの難読化の一連の流れ Eclipseを使ってJavaアプリケーションを作成して、 それを公開用のjarファイル作成までの流れを簡単に説明します。 まずは、単純に実行可能のJARファイルの作成方法です。 1. Eclipse で「ファイル(F)」→「エクスポート(O)...」を選択する。 2. 「Java」→「実行可能 JAR ファイル」を選んで「次へ(N) >」を選択する。 3. […] Posted in プログラミング