画像の高さと幅をピクセル単位で取得するfast方法を探しています。少なくともJPG、PNG、およびTIFFを処理する必要がありますが、より優れている必要があります。私の画像は非常に大きい(250 MBまで)ため、fastを強調し、ImageMagickのidentify
でサイズを取得するには明らかに時間がかかるため、明らかに最初に全体。
できれば、Ruby、またはRails 3でもうまく機能する方法を探します。
私は理論的なものを知っています(さまざまな画像形式、それらのヘッダーとそれらの違いなど)。確かに、かなり一般的な方法で私の問題を解決できる何らかの種類のライブラリを求めています。
imagesize が見つかりましたが、これは有望に見えますが、開発は死んでいるようです。
file
コマンドは、いくつかの画像形式(PNG、GIF、JPEGなど、最近のバージョンはPPM、WEBPも)の寸法を印刷し、ヘッダーのみを読み取ります。
identify
コマンド(ImageMagickから)さまざまな画像の多くの画像情報を印刷します。ヘッダー部分の読み取りは制限されているようです(コメントを参照)。 file
悲しいことに欠けている統一された出力もあります。
exiv2
は、EXIFヘッダーが存在しない場合でも、JPEG、TIFF、PNG、GIF、WEBPなどの多くの形式のディメンションを提供します。ただし、そのためにデータ全体を読み取るかどうかは不明です。サポートされているすべての画像形式については、exiv2のマンページを参照してください。
head -n1
は、PPM、PGM形式のディメンションを提供します。
Webで一般的な形式の場合、exiv2
とidentify
の両方が機能します。ユースケースによっては、いくつかのツールの出力を結合/解析する独自のスクリプトを作成する必要がある場合があります。
PHPがインストールされているかどうかはわかりませんが、このPHP関数はかなり便利です
php -r "print_r(getimagesize('http://www.google.com/images/logos/ps_logo2.png'));"
ImageMagickの identify 関数を使用できます。 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の2つの形式について説明します。
私のコードは、私が使用するために設計されたクラスのものであり、必要に応じて編集できます。
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]
それはあなたが望むピクセルの大きさ(幅と高さ)だと思いますか?
ほとんどのファイル形式には、寸法を定義するヘッダー情報があるため、ファイルを読み取るソフトウェアは、ファイルの読み取りを開始する前に予約する必要がある領域を知ることができます。一部の「生」タイプのファイル形式は、各水平ピクセル行の最後に「行末」バイトを持つバイトストリームである場合があります(この場合、ソフトウェアは最初の行を読み取ってバイトストリームのサイズを分割する必要があります)行の長さで高さを取得します)。
ファイル形式を理解する(またはもちろんライブラリを使用する)必要があるため、「一般的な」方法でこれを作成することはできないと思います。ほとんどの場合、ファイル全体を読み取らずに寸法の大まかな見積もりを提供するコードを見つけることができますが、一部のファイルタイプでは、実際にどのような寸法であるかを確認するためにファイル全体を読み取る必要があります。ほとんどのウェブ中心の画像フォーマットには、画像全体が読み込まれる前にブラウザがボックスの寸法を作成できるように、そのような情報を含むヘッダーがあると思います。
優れたライブラリには、処理するファイルのサイズを取得するメソッドがいくつかあり、それらのメソッドは可能な限り効率的に実装されると思います。
Update: imageinfo はあなたが望むことをするようです。 (テストしていません)
tldr:ファイル「imagename」は行います
webp、すべてのjpg形式(jpeg、jpg200、..)、
サンプル出力は次のようになります
JPEG画像データ、JFIF標準1.02、アスペクト比、密度1x1、セグメント長16、ベースライン、精度8、650x400、フレーム3
ファイルの出力をpythonリストにロードし、リストの4番目のフィールドを使用します。
参考までに、ネットワークトラフィックを削減するために約18000以上の画像を最適化しました。
画像に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
まだ遅いサンプル入力画像を作成できますか?