118

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 のバグであると思われます。

4

13 に答える 13

316

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

BufferedImage bimg = ImageIO.read(new File(filename));
int width          = bimg.getWidth();
int height         = bimg.getHeight();
于 2012-01-31T17:17:39.340 に答える
81

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

/**
 * 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());
}

私の担当者は、私の入力が返信として価値があると見なされるほど高くないと思います.

于 2012-08-28T16:57:34.307 に答える
56

リストされているさまざまなアプローチのいくつかを使用して、パフォーマンスをテストしようとしました。多くの要因が結果に影響を与えるため、厳密なテストを行うことは困難です。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

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

このスレッドへの貢献に感謝します - とても役に立ちました。

于 2013-02-15T04:08:38.253 に答える
53

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

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 のパフォーマンスとの比較はありません。誰かがこれが役立つことを願っています。

于 2010-05-26T09:46:18.990 に答える
18

jpeg バイナリ データをファイルとして読み込み、jpeg ヘッダーを自分で解析できます。探しているのは、0xFFC0 またはフレーム開始ヘッダーです。

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 エントリをチェックするか、上記の情報をここで入手しました。

私は、太陽フォーラムのこの投稿から得た以下のコードと同様の方法を使用しました。

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])));
}

}

于 2009-03-28T01:59:39.970 に答える
10

簡単な方法:

BufferedImage readImage = null;

try {
    readImage = ImageIO.read(new File(your path);
    int h = readImage.getHeight();
    int w = readImage.getWidth();
} catch (Exception e) {
    readImage = null;
}
于 2012-02-17T06:02:24.273 に答える
4

ツールキットを使用できます。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();
于 2013-02-04T21:02:00.823 に答える
1

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

if (png)
    PngReader pngr = new PngReader(file);
    width = pngr.imgInfo.cols;
    height = pngr.imgInfo.rows;
    pngr.close();
}
于 2015-02-04T10:03:04.943 に答える
-2

EMF Image Reader を使用せずに emf ファイルのサイズを取得するには、次のコードを使用できます。

Dimension getImageDimForEmf(final String path) throws IOException {

    ImageInputStream inputStream = new FileImageInputStream(new File(path));

    inputStream.setByteOrder(ByteOrder.LITTLE_ENDIAN);

    // Skip magic number and file size
    inputStream.skipBytes(6*4);

    int left   = inputStream.readInt();
    int top    = inputStream.readInt();
    int right  = inputStream.readInt();
    int bottom = inputStream.readInt();

    // Skip other headers
    inputStream.skipBytes(30);

    int deviceSizeInPixelX = inputStream.readInt();
    int deviceSizeInPixelY = inputStream.readInt();

    int deviceSizeInMlmX = inputStream.readInt();
    int deviceSizeInMlmY = inputStream.readInt();

    int widthInPixel = (int) Math.round(0.5 + ((right - left + 1.0) * deviceSizeInPixelX / deviceSizeInMlmX) / 100.0);
    int heightInPixel = (int) Math.round(0.5 + ((bottom-top + 1.0) * deviceSizeInPixelY / deviceSizeInMlmY) / 100.0);

    inputStream.close();

    return new Dimension(widthInPixel, heightInPixel);
}
于 2015-11-23T09:56:15.557 に答える