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

이미지의 높이와 너비를 픽셀 단위로 얻는 빠른 방법을 찾고 있습니다. 최소한 JPG, PNG 및 TIFF를 처리해야하지만 더 좋습니다. 내 이미지가 매우 커서 (최대 250MB) 빠르고 ImageMagick을 사용하여 크기를 얻는 데 시간이 오래 걸리므 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]


답변

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

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

파일을 읽는 방법을 알기 위해 파일 형식을 이해하거나 라이브러리를 사용해야하기 때문에 “일반적인”방식으로 이것을 만들 수 있다고 생각하지 않습니다. 대부분의 경우 전체 파일을 읽지 않고도 대략적인 크기를 추정 할 수있는 코드를 찾을 수 있지만 일부 파일 형식을 사용하면 전체 파일을 읽어야 실제로 어떤 크기인지 확인할 수 있습니다. 대부분의 웹 중심 이미지 형식에는 이러한 정보가 포함 된 헤더가 있으므로 전체 이미지가로드되기 전에 브라우저가 상자 크기를 만들 수 있습니다.

좋은 라이브러리에는 처리하는 파일의 크기를 가져 오는 몇 가지 방법이 있으며 그 방법은 가능한 한 효율적으로 구현 될 것입니다.

업데이트 : imageinfo 는 원하는 것을하는 것처럼 보입니다. (테스트하지 않았습니다)


답변

이미지에 EXIF ​​정보가 있으면 EXIF ​​헤더를 읽을 수 있습니다.


답변

-ping 은 해당 목적을 위해 도입 된 것으로 보이는 옵션입니다.

그러나 ImageMagick 6.7.7부터 모든 큰 파일의 경우에도 속도 저하가 관찰되지 않습니다.

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

여전히 느린 입력 이미지 예를 만들 수 있습니까?