Programing

이미지 크기를 얻는 빠른 방법 (파일 크기가 아님)

crosscheck 2020. 7. 2. 07:54
반응형

이미지 크기를 얻는 빠른 방법 (파일 크기가 아님)


이미지의 높이와 너비를 픽셀 단위로 얻는 빠른 방법을 찾고 있습니다. 최소한 JPG, PNG 및 TIFF를 처리해야하지만 더 좋습니다. 내가 강조 빨리 내 이미지 (최대 250MB) 상당히 큰이기 때문에 그것은 ImageMagick과의와 크기를 얻을 수 soooo는 오래 걸립니다 identify그것은 분명히 전체 첫번째로 이미지를 읽기 때문에.

가급적이면 Ruby 나 Rails 3에서 잘 작동하는 방식을 찾습니다.

나는 이론적 인 것들 (다양한 이미지 형식, 헤더 및 차이점 등)을 알고 있습니다. 사실, 상당히 일반적인 방식으로 문제를 해결할 수있는 일종의 라이브러리를 요청합니다.

난 그냥 발견 imagesize 개발이 죽은 것 같다하지만 약속 보인다.


  • file명령은 여러 이미지 형식 (예 : PNG, GIF, JPEG; 최신 버전도 PPM, WEBP)의 치수를 인쇄하고 헤더 만 읽습니다.

  • identifyImageMagick 명령 은 다양한 이미지에 대한 많은 이미지 정보를 인쇄합니다. 헤더 부분을 읽는 데 자제하는 것처럼 보입니다 (주석 참조). 또한 file슬프게도 부족한 통합 출력 이 있습니다.

  • exiv2EXIF 헤더가없는 경우에도 JPEG, TIFF, PNG, GIF, WEBP 등 다양한 형식의 치수를 제공합니다. 그래도 전체 데이터를 읽는지 확실하지 않습니다. 지원되는 모든 이미지 형식은 exiv2 맨 페이지를 참조하십시오.

  • head -n1 PPM, PGM 형식의 크기를 알려줍니다.

형식을 웹에 인기, 모두 exiv2identify일을 할 것입니다. 사용 사례에 따라 여러 도구의 출력을 결합 / 파싱하는 자체 스크립트를 작성해야 할 수도 있습니다.


PHP가 설치되어 있는지 확실하지 않지만이 PHP 기능은 매우 편리합니다.

 php -r "print_r(getimagesize('http://www.google.com/images/logos/ps_logo2.png'));"

ImageMagick의 식별 기능을 사용할 수 있습니다 . bash에서 수행하는 방법은 다음과 같습니다 (참고 $ 0는 이미지의 경로입니다).

width=$(identify -format "%w" "$0")> /dev/null
height=$(identify -format "%h" "$0")> /dev/null

그리고 이것은 잠재적 인 오류 메시지도 숨 깁니다. 현대적인 구현은 identify전체 이미지가 아닌 헤더 만 읽으므로 빠릅니다. 그래도 다른 방법과 비교하여 확실하지 않습니다.


https://joseluisbz.wordpress.com/2013/08/06/obtaining-size-or-dimension-of-images/ (BMP, PNG, GIF, JPG, TIF 또는 WMF)

PNG와 JPG의 두 가지 형식이 있습니다.

내 코드는 내가 사용하도록 설계된 클래스에서 가져온 것이므로 필요에 따라 편집 할 수 있습니다.

PHP를 사용하여 이러한 기능 / 방법을 확인하십시오 .

  public function ByteStreamImageString($ByteStream,&$Formato,&$Alto,&$Ancho) {
    $Alto = 0;
    $Ancho = 0;
    $Formato = -1;
    $this->HexImageString = "Error";
    if (ord($ByteStream[0])==137 && ord($ByteStream[1])==80 && ord($ByteStream[2])==78){
      $Formato = 1; //PNG
      $Alto = $this->Byte2PosInt($ByteStream[22],$ByteStream[23]);
      $Ancho = $this->Byte2PosInt($ByteStream[18],$ByteStream[19]);
    }
    if (ord($ByteStream[0])==255 && ord($ByteStream[1])==216
        && ord($ByteStream[2])==255 && ord($ByteStream[3])==224){
      $Formato = 2; //JPG
      $PosJPG = 2;
      while ($PosJPG<strlen($ByteStream)){
        if (sprintf("%02X%02X", ord($ByteStream[$PosJPG+0]),ord($ByteStream[$PosJPG+1]))=="FFC0"){
          $Alto = $this->Byte2PosInt($ByteStream[$PosJPG+5],$ByteStream[$PosJPG+6]);
          $Ancho = $this->Byte2PosInt($ByteStream[$PosJPG+7],$ByteStream[$PosJPG+8]);
        }
        $PosJPG = $PosJPG+2+$this->Byte2PosInt($ByteStream[$PosJPG+2],$ByteStream[$PosJPG+3]);
      }
    }
    if ($Formato > 0){
      $this->HexImageString = "";
      $Salto = 0;
      for ($i=0;$i < strlen($ByteStream); $i++){
        $Salto++;
        $this->HexImageString .= sprintf("%02x", ord($ByteStream[$i]));
        if ($Salto==64){
          $this->HexImageString .= "\n";
          $Salto = 0;
        }
      }
    }
  }


  private function Byte2PosInt($Byte08,$Byte00) {
    return ((ord($Byte08) & 0xFF) << 8)|((ord($Byte00) & 0xFF) << 0);
  }

PHP 코드 사용하기 :

      $iFormato = NULL;//Format PNG or JPG
      $iAlto = NULL; //High
      $iAncho = NULL;//Wide
      ByteStreamImageString($ImageJPG,$iFormato,$iAlto,$iAncho);//The Dimensions will stored in  iFormato,iAlto,iAncho

이제 JAVA를 사용하는 이러한 함수 / 방법 :

  private void ByteStreamImageString(byte[] ByteStream,int[] Frmt,int[] High,int[] Wide) {
    High[0] = 0;
    Wide[0] = 0;
    Frmt[0] = -1;
    this.HexImageString = "Error";
    if ((int)(ByteStream[0]&0xFF)==137 && (int)(ByteStream[1]&0xFF)==80 &&(int)(ByteStream[2]&0xFF)==78){
      Frmt[0] = 1; //PNG
      High[0] = this.Byte2PosInt(ByteStream[22],ByteStream[23]);
      Wide[0] = this.Byte2PosInt(ByteStream[18],ByteStream[19]);
    }
    if ((int)(ByteStream[0]&0xFF)==255 && (int)(ByteStream[1]&0xFF)==216
        &&(int)(ByteStream[2]&0xFF)==255 && (int)(ByteStream[3]&0xFF)==224){
      Frmt[0] = 2; //JPG
      int PosJPG = 2;
      while (PosJPG<ByteStream.length){
        if (String.format("%02X%02X", ByteStream[PosJPG+0],ByteStream[PosJPG+1]).equals("FFC0")){
          High[0] = this.Byte2PosInt(ByteStream[PosJPG+5],ByteStream[PosJPG+6]);
          Wide[0] = this.Byte2PosInt(ByteStream[PosJPG+7],ByteStream[PosJPG+8]);
        }
        PosJPG = PosJPG+2+this.Byte2PosInt(ByteStream[PosJPG+2],ByteStream[PosJPG+3]);
      }
    }
    if (Frmt[0] > 0){
      this.HexImageString = "";
      int Salto = 0;
      for (int i=0;i < ByteStream.length; i++){
        Salto++;
        this.HexImageString += String.format("%02x", ByteStream[i]);
        if (Salto==64){
          this.HexImageString += "\n";
          Salto = 0;
        }
      }
    }
  }


  private Integer Byte2PosInt(byte Byte08, byte Byte00) {
    return new Integer (((Byte08 & 0xFF) << 8)|((Byte00 & 0xFF) << 0));
  }

자바 코드 사용하기 :

        int[] iFormato = new int[1]; //Format PNG or JPG
        int[] iAlto = new int[1]; //High
        int[] iAncho = new int[1]; //Wide
        ByteStreamImageString(ImageJPG,iFormato,iAlto,iAncho); //The Dimensions will stored in  iFormato[0],iAlto[0],iAncho[0]

원하는 픽셀 크기 (너비와 높이)입니다.

대부분의 파일 형식에는 크기를 정의하는 헤더 정보가 있으므로 파일을 읽는 소프트웨어가 파일을 읽기 전에 예약해야 할 공간을 알 수 있다고 생각합니다. 일부 "원시"형식 파일 형식은 각 수평 행 픽셀 끝에 "줄 끝"바이트가있는 바이트 스트림 일 수 있습니다 (이 경우 소프트웨어는 첫 번째 행을 읽고 바이트 스트림의 크기를 나누어야합니다) 높이를 얻으려면 줄 길이로).

I don't think you can make this in any "generic" way, as you need to understand the file format (or use a library of course) in order to know how to read it. You can probably find some code that will in most cases give a rough estimate of the dimensions without reading the whole file, but I think some filetypes may require you to read the whole file to be sure what dimensions it really have. I expect that most web centric image formats have a header with such info so that the browser can create the box dimensions before the whole image is loaded.

I'd guess a good library would have some methods to get the dimensions of the files it handles, and that those methods would be implemented as efficient as possible.

Update: imageinfo seems like it does what you want. (Have not tested it)


If you have EXIF information in the images, you can just read the EXIF header.


-ping is an option that seems to have introduce for that purpose.

However as of ImageMagick 6.7.7 I don't observe slowdown even for every large files, e.g.:

head -c 100000000 /dev/urandom > f.gray
# I don't recommend that you run this command as it eats a lot of memory.
convert -depth 8 -size 20000x10000 f.gray f.png
identify f.png

Can you produce an example input image for which it is still slow?


tldr: file "imagename" will do

works with webp, all jpg formats (jpeg,jpg200,..),

Sample output looks like

JPEG image data, JFIF standard 1.02, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 650x400, frames 3

load the output of file to a python list & use the 4'th field in the list.

FYI, did optimize around 18000+ images to cut down network traffic.

참고URL : https://stackoverflow.com/questions/4670013/fast-way-to-get-image-dimensions-not-filesize

반응형