質問: ### 実現したいこと Javaで画像のフォーマットを調べて、「JPEGのときは~、PNGのときは~」と処理を分岐させたいです。 画像フォーマットは、javax.imageio.ImageReaderクラスのgetFormatNameメソッドで取得します。 ### 質問1 ImageReader#getFormatNameメソッドは具体的に、どんな値を返すのでしょうか? "PNG" OR "png", "JPEG" or "jpg"などが知りたいです。 公式サイトには、具体的に何が返るのか書かれていませんでした。 > > > Returns a String identifying the format of the input source. > > The default implementation returns originatingProvider.getFormatNames()[0]. Implementations that may not have an originating service provider, or which desire a different naming policy should override this method. > > > ### 質問2 getFormatNameメソッドの戻り値は、別クラスで定数として定義されていますか? 定義されているならば、それを参照して判定したいです。 ### 質問3 getFormatNameメソッドを実行したところ、戻り値は * JPEG画像は"JPEG" * PNG画像は"png" でした。 戻り値が大文字/小文字統一されていないのは、なぜでしょうか?
回答: ### 質問1 `ImageReader`や`ImageWriter`のインターフェイスと実装は、サービス・プロバイダー・インターフェイス(SPI)という仕組みを使っていて、直接コードをつなげないような作りになっています。 OracleJDKやOpenJDKでは(確認したわけでは無いですが、おそらく)デフォルトでは`ImageReader`クラスの実装として`com.sun.imageio.plugins.jpeg.JPEGImageReader`や`com.sun.imageio.plugins.png.PNGImageReader`が使われますが、デフォルト以外やそれ以外の実装ではこれらのクラスは使われない可能性があります。 (`com.sun`パッケージは旧Sun Microsystem社の(現在はOracle社の)Java実装に由来するものなので、使われないどころか、そのクラス自体が存在しないJava実装の可能性があるということです。GNU Classpathがその一例です。) そのため、それらのクラスに直接アクセスすることは推奨されていません。 同様の理由で、`com.sun`や`sun`で始まるパッケージの非公開APIは直接アクセスすることは推奨されていません。 これらを理解した上であえてハックするということはありますが、当然自己責任になりますし、原則として使用しないほうが良いです。 サービスプロバイダーについては、下記を参照してください。 `javax.imageio.spi.IIORegistry` - Java SE 8 API ドキュメント サービス・プロバイダ・インターフェース - Wikipedia ### 質問2 > > getFormatNameメソッドの戻り値は、別クラスで定数として定義されていますか? > > > されてはいますが、質問1で書いたように、参照するべきでないクラスにあって、かつ`private`なので参照できません。 JPEGは下記のクラスにあります。 `com.sun.imageio.plugins.jpeg.JPEG` (.java) - GrepCode Class Source PNGは下記のクラスにあります。 `com.sun.imageio.plugins.png.PNGImageReaderSpi` (.java) - GrepCode Class Source `originatingProvider.getFormatNames()[0]`はこれの最初の要素を指しています。 JPEGは`"JPEG"`に、PNGは`"png"`になります。 ### 質問3 これは分かりません。 インターフェイス側は`originatingProvider.getFormatNames()[0]`を返すようになっているのにもかかわらず、実装側を作った人が、特に統一することを考えずに配列の順番を決めてしまったんだと思います。