我正在寻找一种快速的方法来获取图像的高度和宽度(以像素为单位)。它应至少处理JPG,PNG和TIFF,但越好。我强调快速是因为我的图像很大(最大为250 MB),并且用ImageMagick的尺寸获取图像的时间太长了,identify
因为它显然首先读取了整个图像。
最好,我正在寻找一种在Ruby甚至Rails 3中都能正常工作的方法。
我知道一些理论知识(各种图像格式,它们的标题和它们的区别,等等)。确实,我要求一种可以以相当通用的方式解决我的问题的库。
我正在寻找一种快速的方法来获取图像的高度和宽度(以像素为单位)。它应至少处理JPG,PNG和TIFF,但越好。我强调快速是因为我的图像很大(最大为250 MB),并且用ImageMagick的尺寸获取图像的时间太长了,identify
因为它显然首先读取了整个图像。
最好,我正在寻找一种在Ruby甚至Rails 3中都能正常工作的方法。
我知道一些理论知识(各种图像格式,它们的标题和它们的区别,等等)。确实,我要求一种可以以相当通用的方式解决我的问题的库。
Answers:
该file
命令将打印几种图像格式(例如PNG,GIF,JPEG;最新版本也为PPM,WEBP)的尺寸,并且仅读取标头。
该identify
命令(来自ImageMagick)可打印大量图像信息,以显示各种图像。似乎只能阅读标题部分(请参见注释)。file
可悲的是,它还具有统一的输出。
exiv2
即使没有EXIF标头,也可以为您提供多种格式的尺寸,包括JPEG,TIFF,PNG,GIF,WEBP。目前尚不清楚是否读取全部数据。有关所有受支持的图像格式,请参见exiv2的手册页。
head -n1
将为您提供PPM,PGM格式的尺寸。
对于网络上流行的格式,两者exiv2
和identify
都会起作用。根据用例,您可能需要编写自己的脚本,以结合/解析多个工具的输出。
这里有两种格式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));
}
使用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]
ref
/ out
参数-这被认为是最佳实践吗?
我想这是您想要的像素尺寸(宽度和高度)吗?
我认为大多数文件格式都有一些定义尺寸的标头信息,以便读取文件的软件可以知道在开始读取文件之前必须保留多少空间。某些“原始”类型的文件格式可能只是字节流,而每个水平像素行的末尾都有一些“行尾”字节(在这种情况下,软件必须读取第一行并划分字节流的大小通过线长来获得高度)。
我认为您无法以任何“通用”方式实现此目的,因为您需要了解文件格式(或者当然要使用库)才能知道如何读取它。您可能会找到一些代码,这些代码在大多数情况下不会读取整个文件就能粗略估计尺寸,但是我认为某些文件类型可能需要您读取整个文件才能确定其真正具有的尺寸。我希望大多数以Web为中心的图像格式都具有带有此类信息的标头,以便浏览器可以在加载整个图像之前创建框尺寸。
我猜一个好的库将提供一些方法来获取其处理的文件的尺寸,并且这些方法将尽可能高效地实现。
如果图像中有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
您能否生成示例输入图像,但该图像仍然很慢?