web-dev-qa-db-fra.com

Moyen rapide d'obtenir les dimensions de l'image (pas la taille du fichier)

Je cherche un moyen rapide pour obtenir la hauteur et la largeur d'une image en pixels. Il devrait au moins gérer les formats JPG, PNG et TIFF, mais le plus sera le mieux. Je souligne rapide parce que mes images sont assez grandes (jusqu’à 250 Mo) et qu’il faut beaucoup de temps pour obtenir la taille de la variable identify d’ImageMagick, qui lit évidemment les images dans leur ensemble.

De préférence, je cherche un moyen qui fonctionne bien dans Ruby, ou même dans Rails 3.

Je connais la théorie (différents formats d’image, leurs en-têtes et leurs différences, etc.). En effet, je demande une sorte de bibliothèque capable de résoudre mon problème de manière assez générique.

Je viens de trouver http://imagesize.rubyforge.org qui semble prometteur bien que le développement semble être mort.

117
dAnjou
  • La commande file imprime les dimensions de plusieurs formats d'image (par exemple, PNG, GIF, JPEG; les versions récentes ainsi que PPM, WEBP) et ne lit que l'en-tête.

  • La commande identify(à partir d'ImageMagick) imprime de nombreuses informations sur les images pour une grande variété d'images. Il semble se limiter à la lecture de la partie en-tête (voir les commentaires). Il a également une sortie unifiée dont file manque cruellement.

  • exiv2 vous donne les dimensions pour de nombreux formats, y compris JPEG, TIFF, PNG, GIF, WEBP, même si aucun en-tête EXIF ​​n’est présent. On ne sait pas s'il lit toutes les données pour cela. Voir la page de manuel de exiv2 pour tous les formats d'image pris en charge.

  • head -n1 vous donnera les dimensions pour les formats PPM, PGM.

Pour les formats populaires sur le Web, exiv2 et identify feront l'affaire . Selon le cas d'utilisation, vous devrez peut-être écrire votre propre script combinant/analysant les sorties de plusieurs outils.

176
ypnos

Je ne sais pas si vous avez installé php, mais cette fonction PHP est très pratique

 php -r "print_r(getimagesize('http://www.google.com/images/logos/ps_logo2.png'));"
28
ajreal

Vous pouvez utiliser la fonction identifier de ImageMagick. Voici comment procéder en bash (la note $ 0 correspond au chemin de l'image):

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

Et cela cache également les éventuels messages d'erreur. Les implémentations modernes de identify ne lisent que l'en-tête, pas l'image entière, donc c'est rapide. Pas sûr de savoir comment il se compare à d'autres méthodes cependant.

12
James L.

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

Ici pour deux formats PNG et JPG.

Mon code est d'une classe conçue pour mon usage, vous pouvez modifier selon vos besoins.

Veuillez vérifier ces fonctions/méthodes en utilisant 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);
  }

Utilisation du 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

Maintenant, ces fonctions/méthodes utilisant 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));
  }

En utilisant le 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]
5
chepe lucho

Ce sont les dimensions en pixels que vous voulez (largeur et hauteur), je suppose?

Je pense que la plupart des formats de fichiers ont des informations d’en-tête définissant les dimensions, de sorte que le logiciel qui lit le fichier puisse savoir combien d’espace il doit réserver avant de commencer à lire le fichier. Certains formats de fichier de type "brut" pourraient simplement être un flux d'octets avec un octet "fin de ligne" à la fin de chaque rangée horizontale de pixels (auquel cas le logiciel doit lire la première ligne et diviser la taille du flux d'octets par la longueur de la ligne pour obtenir la hauteur).

Je ne pense pas que vous puissiez faire cela de manière "générique", car vous devez comprendre le format du fichier (ou utiliser une bibliothèque bien sûr) pour savoir comment le lire. Vous pouvez probablement trouver du code qui, dans la plupart des cas, donnera une estimation approximative des dimensions sans lire le fichier en entier, mais je pense que certains types de fichiers peuvent vous obliger à lire le fichier en entier pour être sûr de ses dimensions réelles. Je m'attends à ce que la plupart des formats d'image centrés sur le Web aient un en-tête avec de telles informations, de sorte que le navigateur puisse créer les dimensions de la boîte avant que l'image entière ne soit chargée.

J'imagine qu'une bonne bibliothèque disposerait de certaines méthodes pour obtenir les dimensions des fichiers qu'elle manipule, et que ces méthodes seraient mises en œuvre de la manière la plus efficace possible.

Update: imageinfo semble que cela fait ce que vous voulez. (Je ne l'ai pas testé)

1
Stein G. Strindhaug

tldr: le fichier "imagename" fera l'affaire

fonctionne avec webp, tous les formats jpg (jpeg, jpg200, ..), 

Exemple de sortie ressemble à 

Données d'image JPEG, norme JFIF 1.02, rapport de format, densité 1x1, longueur de segment 16, ligne de base, précision 8, 650x400, images 3

charge la sortie du fichier dans une liste python et utilise le 4ème champ de la liste.

Pour votre information, environ 18 000 images et plus ont été optimisées pour réduire le trafic sur le réseau.

0
mj-ek

Si vous avez des informations EXIF ​​dans les images, vous pouvez simplement lire l’en-tête EXIF.

0
Georgi

-ping est une option qui semble avoir été introduite à cette fin.

Cependant, à partir de ImageMagick 6.7.7, je n’observe aucun ralentissement, même pour tous les gros fichiers,

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

Pouvez-vous produire un exemple d’image d’entrée pour laquelle elle est encore lente?