web-dev-qa-db-ja.com

Javaを使用して画像の高さと幅を取得する方法は?

ImageIO.read を使用して画像の高さと幅を取得する以外の方法はありますか?

スレッドをロックする問題が発生したためです。

at com.Sun.medialib.codec.jpeg.Decoder.njpeg_decode(Native Method)      
at com.Sun.medialib.codec.jpeg.Decoder.decode(Decoder.Java:87)      
at com.Sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader.decode(CLibJPEGImageReader.Java:73)     
 - locked <0xd96fb668> (a com.Sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader)      
at com.Sun.media.imageioimpl.plugins.clib.CLibImageReader.getImage(CLibImageReader.Java:320)    
 - locked <0xd96fb668> (a com.Sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader)     
 at com.Sun.media.imageioimpl.plugins.clib.CLibImageReader.read(CLibImageReader.Java:384)   
 - locked <0xd96fb668> (a com.Sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader)      
at javax.imageio.ImageIO.read(ImageIO.Java:1400)      
at javax.imageio.ImageIO.read(ImageIO.Java:1322)

このエラーはSunアプリサーバーでのみ発生するため、Sunのバグであると思われます。

93
Dick Song

これは非常にシンプルで便利なものです。

BufferedImage bimg = ImageIO.read(new File(filename));
int width          = bimg.getWidth();
int height         = bimg.getHeight();
264
Apurv

これは、@ Kayによる素晴らしい投稿を書き直したもので、IOExceptionをスローし、早期終了を提供します。

/**
 * Gets image dimensions for given file 
 * @param imgFile image file
 * @return dimensions of image
 * @throws IOException if the file is not a known image
 */
public static Dimension getImageDimension(File imgFile) throws IOException {
  int pos = imgFile.getName().lastIndexOf(".");
  if (pos == -1)
    throw new IOException("No extension for file: " + imgFile.getAbsolutePath());
  String suffix = imgFile.getName().substring(pos + 1);
  Iterator<ImageReader> iter = ImageIO.getImageReadersBySuffix(suffix);
  while(iter.hasNext()) {
    ImageReader reader = iter.next();
    try {
      ImageInputStream stream = new FileImageInputStream(imgFile);
      reader.setInput(stream);
      int width = reader.getWidth(reader.getMinIndex());
      int height = reader.getHeight(reader.getMinIndex());
      return new Dimension(width, height);
    } catch (IOException e) {
      log.warn("Error reading: " + imgFile.getAbsolutePath(), e);
    } finally {
      reader.dispose();
    }
  }

  throw new IOException("Not a known image file: " + imgFile.getAbsolutePath());
}

私の回答は、自分の入力が回答としてふさわしいとみなされるほど高くはないと思います。

59
Andrew Taylor

画像サイズを読み取る別の方法を見つけました(より一般的)。 ImageReaderと連携してImageIOクラスを使用できます。サンプルコードは次のとおりです。

private Dimension getImageDim(final String path) {
    Dimension result = null;
    String suffix = this.getFileSuffix(path);
    Iterator<ImageReader> iter = ImageIO.getImageReadersBySuffix(suffix);
    if (iter.hasNext()) {
        ImageReader reader = iter.next();
        try {
            ImageInputStream stream = new FileImageInputStream(new File(path));
            reader.setInput(stream);
            int width = reader.getWidth(reader.getMinIndex());
            int height = reader.getHeight(reader.getMinIndex());
            result = new Dimension(width, height);
        } catch (IOException e) {
            log(e.getMessage());
        } finally {
            reader.dispose();
        }
    } else {
        log("No reader found for given format: " + suffix));
    }
    return result;
}

GetFileSuffixは、「。」なしでパスの拡張子を返すメソッドです。したがって、例:png、jpgなど。実装例は次のとおりです。

private String getFileSuffix(final String path) {
    String result = null;
    if (path != null) {
        result = "";
        if (path.lastIndexOf('.') != -1) {
            result = path.substring(path.lastIndexOf('.'));
            if (result.startsWith(".")) {
                result = result.substring(1);
            }
        }
    }
    return result;
}

このソリューションは、画像全体ではなく画像サイズのみがファイルから読み取られるため、非常に高速です。私はそれをテストしましたが、ImageIO.readのパフォーマンスとの比較はありません。誰かがこれが役立つことを願っています。

44
user350756

リストされているさまざまなアプローチのいくつかを使用して、パフォーマンスをテストしようとしました。多くの要因が結果に影響を及ぼすため、厳密なテストを行うのは困難です。 330個のjpgファイルを含むフォルダーと330個のpngファイルを含むフォルダーの2つを用意しました。どちらの場合も、平均ファイルサイズは4Mbでした。次に、各ファイルに対してgetDimensionを呼び出しました。 getDimensionメソッドの各実装と各画像タイプは個別にテストされました(個別の実行)。私が得た実行時間は次のとおりです(jpgの最初の数、pngの2番目の数):

1(Apurv) - 101454ms, 84611ms
2(joinJpegs) - 471ms, N/A
3(Andrew Taylor) - 707ms, 68ms
4(Karussell, ImageIcon) - 106655ms, 100898ms
5(user350756) - 2649ms, 68ms

寸法を取得するためにファイル全体をロードするメソッドもあれば、画像からヘッダー情報を読み取るだけで取得するメソッドもあることは明らかです。これらの数値は、アプリケーションのパフォーマンスが重要な場合に役立つと思います。

このスレッドへの貢献に感謝します-とても助かります。

40
mp31415

Jpegバイナリデータをファイルとしてロードし、jpegヘッダーを自分で解析できます。探しているのは0xFFC0またはStart of Frameヘッダーです。

Start of frame marker (FFC0)

* the first two bytes, the length, after the marker indicate the number of bytes, including the two length bytes, that this header contains
* P -- one byte: sample precision in bits (usually 8, for baseline JPEG)
* Y -- two bytes
* X -- two bytes
* Nf -- one byte: the number of components in the image
      o 3 for color baseline JPEG images
      o 1 for grayscale baseline JPEG images

* Nf times:
      o Component ID -- one byte
      o H and V sampling factors -- one byte: H is first four bits and V is second four bits
      o Quantization table number-- one byte

The H and V sampling factors dictate the final size of the component they are associated with. For instance, the color space defaults to YCbCr and the H and V sampling factors for each component, Y, Cb, and Cr, default to 2, 1, and 1, respectively (2 for both H and V of the Y component, etc.) in the Jpeg-6a library by the Independent Jpeg Group. While this does mean that the Y component will be twice the size of the other two components--giving it a higher resolution, the lower resolution components are quartered in size during compression in order to achieve this difference. Thus, the Cb and Cr components must be quadrupled in size during decompression.

ヘッダーの詳細については、ウィキペディアのjpegエントリを確認するか、上記の情報 here を入手しました。

Sunフォーラムで this post から取得した以下のコードに似た方法を使用しました。

import Java.awt.Dimension;
import Java.io.*;

public class JPEGDim {

public static Dimension getJPEGDimension(File f) throws IOException {
    FileInputStream fis = new FileInputStream(f);

    // check for SOI marker
    if (fis.read() != 255 || fis.read() != 216)
        throw new RuntimeException("SOI (Start Of Image) marker 0xff 0xd8 missing");

    Dimension d = null;

    while (fis.read() == 255) {
        int marker = fis.read();
        int len = fis.read() << 8 | fis.read();

        if (marker == 192) {
            fis.skip(1);

            int height = fis.read() << 8 | fis.read();
            int width = fis.read() << 8 | fis.read();

            d = new Dimension(width, height);
            break;
        }

        fis.skip(len - 2);
    }

    fis.close();

    return d;
}

public static void main(String[] args) throws IOException {
    System.out.println(getJPEGDimension(new File(args[0])));
}

}

13
joinJpegs

簡単な方法:

BufferedImage readImage = null;

try {
    readImage = ImageIO.read(new File(your path);
    int h = readImage.getHeight();
    int w = readImage.getWidth();
} catch (Exception e) {
    readImage = null;
}
9
user1215499

ImageIO.readの問題は、本当に遅いことです。必要なのは、画像ヘッダーを読み取ってサイズを取得することだけです。 ImageIO.getImageReaderは完璧な候補です。

以下はGroovyの例ですが、Javaにも同じことが当てはまります

def stream = ImageIO.createImageInputStream(newByteArrayInputStream(inputStream))
def formatReader = ImageIO.getImageWritersByFormatName(format).next() 
def reader = ImageIO.getImageReader(formatReader)
reader.setInput(stream, true)

println "width:reader.getWidth(0) -> height: reader.getHeight(0)"

パフォーマンスは、SimpleImageInfo Javaライブラリを使用した場合と同じでした。

https://github.com/cbeust/personal/blob/master/src/main/Java/com/beust/SimpleImageInfo.Java

4
argoden

ImageInfoの無料で利用可能なクラスを使用してみてください。同じ目的で使用しました。

http://linux.softpedia.com/get/Multimedia/Graphics/ImageInfo-19792.shtml

4
karim79

Toolkitを使用できます。ImageIOは不要です

Image image = Toolkit.getDefaultToolkit().getImage(file.getAbsolutePath());
int width = image.getWidth(null);
int height = image.getHeight(null);

画像の読み込みを処理したくない場合は

ImageIcon imageIcon = new ImageIcon(file.getAbsolutePath());
int height = imageIcon.getIconHeight();
int width = imageIcon.getIconWidth();
3
Karussell

ImageIO.readでバッファリングされたイメージを取得することは、メモリ内のイメージの完全な非圧縮コピーを作成するため、非常に重い方法です。 pngの場合、pngjとコードも使用できます。

if (png)
    PngReader pngr = new PngReader(file);
    width = pngr.imgInfo.cols;
    height = pngr.imgInfo.rows;
    pngr.close();
}
1
Jessi

Javaを使用してBufferedImageオブジェクトで画像の幅と高さを取得できます。

public void setWidthAndHeightImage(FileUploadEvent event){
    byte[] imageTest = event.getFile().getContents();
                baiStream = new ByteArrayInputStream(imageTest );
                BufferedImage bi = ImageIO.read(baiStream);
                //get width and height of image
                int imageWidth = bi.getWidth();
                int imageHeight = bi.getHeight();
    }
1
KIBOU Hassan