Fast way to get image dimensions (not filesize)

前端 未结 8 1666
独厮守ぢ
独厮守ぢ 2021-01-29 23:03

I\'m looking for a fast way 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

相关标签:
8条回答
  • 2021-01-29 23:04

    You can use ImageMagick's identify function. Here's how you do it in bash (Note $0 is the image's path):

    width=$(identify -format "%w" "$0")> /dev/null
    height=$(identify -format "%h" "$0")> /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.

    0 讨论(0)
  • 2021-01-29 23:04

    If you have EXIF information in the images, you can just read the EXIF header.

    0 讨论(0)
  • 2021-01-29 23:09

    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: imageinfo seems like it does what you want. (Have not tested it)

    0 讨论(0)
  • 2021-01-29 23:11

    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.

    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:

      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:

          $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:

      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:

            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]
    
    0 讨论(0)
  • 2021-01-29 23:11

    tldr: file "imagename" will do

    works with webp, all jpg formats (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

    load the output of file to a python list & use the 4'th field in the list.

    FYI, did optimize around 18000+ images to cut down network traffic.

    0 讨论(0)
  • 2021-01-29 23:18

    Imagemagick -ping option

    It seems to have been introduced for that purpose.

    However as of ImageMagick 6.7.7 I don't observe slowdown even for every large files, e.g.:

    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
    

    Can you produce an example input image for which it is still slow?

    See also: Can ImageMagick return the image size?

    0 讨论(0)
提交回复
热议问题