获取图像尺寸(不是文件大小)的快速方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4670013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Fast way to get image dimensions (not filesize)
提问by dAnjou
I'm looking for a fastway to get the height and width of an image in pixels. It should handle at least JPG, PNG and TIFF, but the more the better. I emphasize fastbecause my images are quite big (up to 250 MB) and it takes soooo long to get the size with ImageMagick's identify
because it obviously reads the images as a whole first.
我正在寻找一种以像素为单位获取图像高度和宽度的快速方法。它至少应该处理 JPG、PNG 和 TIFF,但越多越好。我强调快速,因为我的图像非常大(高达 250 MB)并且使用 ImageMagick 获得大小需要很长时间,identify
因为它显然首先读取整个图像。
Preferably, I look for a way that works well in Ruby, or even in Rails 3.
最好,我寻找一种在 Ruby 甚至 Rails 3 中运行良好的方法。
I know the theory stuff (various image formats, their headers and their differences, and so on). Indeed, I ask for some kind of library that can resolve my issue in a fairly generic way.
我知道理论的东西(各种图像格式,它们的标题和它们的区别等等)。确实,我要求某种可以以相当通用的方式解决我的问题的库。
I just found imagesizewhich looks promising although development seems to be dead.
我刚刚发现imagesize看起来很有希望,尽管开发似乎已经死了。
回答by Georgi
If you have EXIF information in the images, you can just read the EXIF header.
如果图像中有 EXIF 信息,则只需读取 EXIF 标头即可。
回答by ajreal
I not sure you have php installed, but this PHP function is pretty handy
我不确定你是否安装了 php,但是这个 PHP 函数非常方便
php -r "print_r(getimagesize('http://www.google.com/images/logos/ps_logo2.png'));"
回答by Stein G. Strindhaug
It's the pixel dimensions you want (width and height), I assume?
这是您想要的像素尺寸(宽度和高度),我假设?
I'd think that most file formats have some header info defining the dimensions, so that the software reading the file can know how much room it must reserve before starting to read the file. Some "raw" type file formats might just be a stream of bytes with some "end of line" byte at the end of each horizontal row of pixels (in which case the software must read the first line and divide the size of the byte stream by the line length to get the height).
我认为大多数文件格式都有一些定义尺寸的标题信息,以便读取文件的软件可以在开始读取文件之前知道它必须保留多少空间。一些“原始”类型的文件格式可能只是一个字节流,在每个水平像素行的末尾有一些“行尾”字节(在这种情况下,软件必须读取第一行并划分字节流的大小通过线长得到高度)。
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: imageinfoseems like it does what you want. (Have not tested it)
回答by ypnos
The
file
command prints the dimensions for several image formats (e.g. PNG, GIF, JPEG; recent versions also PPM, WEBP), and does only read the header.The
identify
command(from ImageMagick) prints lots of image information for a wide variety of images. It seems to restrain itself to reading the header portion (see comments). It also has a unified output whichfile
sadly lacks.exiv2
gives you dimensions for many formats, including JPEG, TIFF, PNG, GIF, WEBP, even if no EXIF header present. It is unclear if it reads the whole data for that though. See the manpage of exiv2 for all supported image formats.head -n1
will give you the dimensions for PPM, PGM formats.
该
file
命令打印多种图像格式(例如 PNG、GIF、JPEG;最近版本还有 PPM、WEBP)的尺寸,并且只读取标题。该
identify
命令(来自 ImageMagick)为各种图像打印大量图像信息。它似乎限制自己阅读标题部分(见评论)。它也有一个统一的输出,file
遗憾的是缺乏。exiv2
为您提供多种格式的尺寸,包括 JPEG、TIFF、PNG、GIF、WEBP,即使不存在 EXIF 标头。目前尚不清楚它是否会为此读取整个数据。有关所有支持的图像格式,请参阅 exiv2 的联机帮助页。head -n1
将为您提供 PPM、PGM 格式的尺寸。
For formats popular on the web, both exiv2
and identify
will do the job.
Depending on the use-case you may need to write your own script that combines/parses outputs of several tools.
对于流行的格式在网络上,都exiv2
和identify
会做的工作。根据用例,您可能需要编写自己的脚本来组合/解析多个工具的输出。
回答by joseluisbz
https://joseluisbz.wordpress.com/2013/08/06/obtaining-size-or-dimension-of-images/(BMP, PNG, GIF, JPG, TIF or WMF)
Here for two formats PNG and JPG.
这里有两种格式 PNG 和 JPG。
My code is from a class designed to my use, you can to edit according to your needs.
我的代码来自一个专为我使用而设计的类,您可以根据需要进行编辑。
Please check these functions/method using PHP:
请使用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);
}
Using the PHP Code:
使用 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
Now these functions/method using JAVA:
现在这些函数/方法使用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));
}
Using the Java code:
使用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]
回答by James L.
You can use ImageMagick's identifyfunction. Here's how you do it in bash (Note $0 is the image's path):
您可以使用 ImageMagick 的识别功能。以下是您在 bash 中的操作方法(注意 $0 是图像的路径):
width=$(identify -format "%w" "##代码##")> /dev/null
height=$(identify -format "%h" "##代码##")> /dev/null
And this also hides any potential error messages. Modern implementations of identify
only read the header, not the whole image, so it is fast. Not sure how it compares to other methods though.
这也隐藏了任何潜在的错误消息。现代实现identify
只读取标题,而不是整个图像,所以速度很快。不知道它与其他方法相比如何。
回答by mj-ek
tldr: file "imagename" will do
tldr:文件“imagename”就可以了
works with webp, all jpg formats (jpeg,jpg200,..),
适用于 webp、所有 jpg 格式(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
JPEG 图像数据,JFIF 标准 1.02,纵横比,密度 1x1,段长 16,基线,精度 8,650x400,帧 3
load the output of file to a python list & use the 4'th field in the list.
将文件的输出加载到 python 列表并使用列表中的第 4 个字段。
FYI, did optimize around 18000+ images to cut down network traffic.
仅供参考,确实优化了大约 18000 多个图像以减少网络流量。