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

我正在寻找一种快速的方法来获取像素的高度和宽度的图像。 它应该至less处理JPG,PNG和TIFF,但越多越好。 我强调速度很快,因为我的图像相当大(高达250 MB),并且需要很长时间才能获得ImageMagick identify的大小,因为它显然首先读取图像。

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

我知道理论的东西(各种图像格式,他们的头和他们的差异,等等)。 的确,我要求一种能够以相当通用的方式解决我的问题的图书馆。

我刚刚发现http://imagesize.rubyforge.org看起来很有希望,尽pipe发展似乎已经死了。

  • file命令打印多个图像格式(例如PNG,GIF和JPEG,但不是PPM)的尺寸,并只读取标题。

  • 即使没有EXIF标题, exiv2提供JPEG和TIFF尺寸。 目前还不清楚它是否读取了整个数据。

  • head -n1会给你PPM,PGM格式的尺寸。

  • identify命令(来自ImageMagick)为各种图像打印大量图像信息。 它似乎限制自己阅读标题部分(见评论)。

我想你需要编写自己的脚本来组合/分析这些输出…

我不知道你有PHP安装,但这个PHP函数是非常方便的

  php -r "print_r(getimagesize('http://www.google.comhttp://img.dovov.comlogos/ps_logo2.png'));" 

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

这里有两种格式的PNG和JPG。

我的代码是从我devise的一个类来使用的,你可以根据你的需要进行编辑。

请使用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)); } 

使用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] 

您可以使用ImageMagick的识别function。 这里是你如何做bash(注意$ 0是图像的path):

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

这也隐藏了任何潜在的错误消息。 identify现代实现只读取头部,而不是整个图像,因此速度很快。 不知道如何比较其他方法。

这是你想要的像素尺寸(宽度和高度),我假设?

我认为大多数文件格式都有一些定义尺寸的标题信息,因此读取文件的软件可以知道在开始读取文件之前必须保留多less空间。 某些“原始”types的文件格式可能只是一个字节stream,在每个水平行像素的末端有一些“行尾”字节(在这种情况下,软件必须读取第一行并将字节stream的大小由行长来获得高度)。

我不认为你可以用任何“通用”的方式来做到这一点,因为你需要了解文件格式(或使用当然库),以了解如何阅读它。 你可能会发现一些代码在大多数情况下可以粗略地估计维度而不读取整个文件,但是我认为一些文件types可能会要求你阅读整个文件,以确定它的真实维度。 我期望大多数以网页为中心的图像格式都有一个包含这些信息的标题,这样浏览器就可以在整个图像加载之前创build盒子的尺寸。

我猜想一个好的库会有一些方法来获取它处理的文件的维度,并且这些方法将尽可能高效地实现。

更新 : imageinfo似乎是你想要的。 (没有testing过)

平台似乎是为此目的而引入的一个选项。

但是从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 

你能产生一个例子input图像,它仍然很慢?

如果您在图像中具有EXIF信息,则可以只读取EXIF标头。