快速获取图像尺寸的方法(不是文件大小)

dAn*_*jou 130 linux image

我正在寻找一种快速获取图像高度和宽度的方法.它应该至少处理JPG,PNG和TIFF,但越多越好.我强调快速,因为我的图像非常大(高达250 MB)并且使用ImageMagick获得大小需要太长时间,identify因为它显然首先将图像作为整体读取.

最好是,我寻找一种在Ruby中运行良好的方法,甚至在Rails 3中.

我知道理论的东西(各种图像格式,它们的标题和它们的差异,等等).实际上,我要求某种类型的库可以通过相当通用的方式解决我的问题.

我刚刚找到http://imagesize.rubyforge.org看起来很有希望虽然发展似乎已经死了.

ypn*_*nos 188

  • file命令打印多种图像格式的尺寸(例如PNG,GIF,JPEG;最新版本也是PPM,WEBP),并且只读取标题.

  • identify命令(来自ImageMagick)为各种图像打印大量图像信息.它似乎限制自己阅读标题部分(见评论).它也有一个统一的输出,file可悲的是缺乏.

  • exiv2为您提供多种格式的尺寸,包括JPEG,TIFF,PNG,GIF,WEBP,即使没有EXIF标题.目前还不清楚它是否读取了整个数据.有关所有支持的图像格式,请参阅exiv2的联机帮助页.

  • head -n1 将为您提供PPM,PGM格式的尺寸.

在网络上流行的格式,都exiv2identify会做的工作.根据用例,您可能需要编写自己的脚本来组合/解析多个工具的输出.

  • 我已经使用ImageMagick识别命令进行了一些测试,使用strace记录open/read/mmap/close调用,以查看从识别的图像中读取了多少数据.它确实依赖于文件类型和文件大小,但我通过"识别"读取了20-60 KB的5-335 MB图像(我还测试了"转换",显示所有字节都被读取).因此看起来"识别"在这里是一个不错的选择(因为它支持所有流行的格式并且只读取标题). (3认同)

ajr*_*eal 32

我不确定你是否安装了php,但这个PHP函数非常方便

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


Jam*_* L. 15

您可以使用ImageMagick的识别功能.这是你在bash中的表现(注意$ 0是图像的路径):

width=$(identify -format "%w" "$0")> /dev/null
height=$(identify -format "%h" "$0")> /dev/null
Run Code Online (Sandbox Code Playgroud)

这也隐藏了任何潜在的错误消息.现代实现identify只读取标题,而不是整个图像,所以它很快.不知道它与其他方法相比如何.

  • 我相信这样会更有效:`read width height <<(identify -format“%w%h”“ $ {1}”)` (2认同)

che*_*cho 5

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);
  }
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)

现在这些函数/方法使用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));
  }
Run Code Online (Sandbox Code Playgroud)

使用Java代码:

        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]
Run Code Online (Sandbox Code Playgroud)


小智 0

如果图像中有 EXIF 信息,则只需读取 EXIF 标头即可。

  • 您的图像中有多少*确实*包含该信息?也许如果其中 90% 具有 EXIF 数据,那么在另外 10% 上使用 ImageMagick 的缓慢程度是可以接受的。 (3认同)