Быстрый способ получить размеры изображения (не файлы)

Я ищу способ быстро, чтобы получить высоту и ширину изображения в пикселях. Он должен обрабатывать хотя бы JPG, PNG и TIFF, но чем больше, тем лучше. Я подчеркиваю быстро, потому что мои изображения довольно большие (до 250 Мбайт), и требуется много времени для получения размера с помощью ImageMagick identify, потому что он, очевидно, сначала читает изображения в целом.

Предпочтительно, я ищу способ, который хорошо работает в Ruby или даже в Rails 3.

Я знаю материал теории (различные форматы изображений, их заголовки и их отличия и т.д.). В самом деле, я прошу какую-то библиотеку, которая может решить мою проблему довольно обычным способом.

Я только что нашел http://imagesize.rubyforge.org, который выглядит многообещающим, хотя развитие кажется мертвым.

Ответ 1

  • Команда file печатает размеры для нескольких форматов изображений (например, PNG, GIF, JPEG; последние версии также PPM, WEBP) и читает только заголовок.

  • Команда identify (из ImageMagick) печатает много информации об изображении для самых разных изображений. Кажется, он ограничивается чтением заголовка (см. Комментарии). У этого также есть унифицированный вывод, которого, к сожалению, нет в file.

  • exiv2 дает вам размеры для многих форматов, включая JPEG, TIFF, PNG, GIF, WEBP, даже если заголовок EXIF отсутствует. Неясно, читает ли он все данные для этого все же. Смотрите man-страницу exiv2 для всех поддерживаемых форматов изображений.

  • head -n1 даст вам размеры для форматов PPM, PGM.

Для форматов популярных в Интернете, как exiv2 и identify будет делать эту работу. В зависимости от варианта использования вам может потребоваться написать собственный скрипт, который объединяет/анализирует выходные данные нескольких инструментов.

Ответ 2

Я не уверен, что у вас установлен php, но эта функция PHP довольно удобна

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

Ответ 3

Вы можете использовать функцию идентификации ImageMagick. Вот как вы это делаете в bash (примечание: $ 0 - путь к изображению):

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

И это также скрывает любые потенциальные сообщения об ошибках. Современные реализации identify только чтение заголовка, а не всего изображения, поэтому это быстро. Не уверен, как это по сравнению с другими методами, хотя.

Ответ 4

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

Здесь для двух форматов 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]

Ответ 5

Я думаю, размеры пикселя, которые вы хотите (ширина и высота),

Я думаю, что в большинстве форматов файлов есть информация заголовка, определяющая размеры, так что программное обеспечение, читающее файл, может знать, сколько места он должен зарезервировать, прежде чем начать читать файл. Некоторые форматы файлов типа "raw" могут быть просто потоком байтов с некоторым байтом конца строки в конце каждой горизонтальной строки пикселей (в этом случае программное обеспечение должно читать первую строку и делить размер байтового потока по длине линии, чтобы получить высоту).

Я не думаю, что вы можете сделать это любым "общим" способом, так как вам нужно понять формат файла (или использовать библиотеку, конечно), чтобы знать, как его читать. Вероятно, вы можете найти код, который в большинстве случаев будет давать приблизительную оценку размеров без чтения всего файла, но я думаю, что некоторые типы файлов могут потребовать, чтобы вы прочитали весь файл, чтобы убедиться, какие размеры он действительно имеет. Я ожидаю, что большинство веб-ориентированных форматов изображений имеют заголовок с такой информацией, чтобы браузер мог создавать размеры окна перед загрузкой всего изображения.

Я бы предположил, что у хорошей библиотеки будут какие-то методы для получения размеров файлов, которые она обрабатывает, и что эти методы будут реализованы как можно эффективнее.

Обновление: imageinfo кажется, что он делает то, что вы хотите. (Не проверял его)

Ответ 6

Если у вас есть информация EXIF ​​в изображениях, вы можете просто прочитать заголовок EXIF.

Ответ 7

-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

Можете ли вы создать примерное входное изображение, для которого оно все еще медленное?

Ответ 8

TL;DR: файл "imagename" подойдет

работает с webp, все форматы jpg (jpeg, jpg200,..),

Пример вывода выглядит как

Данные изображения JPEG, стандарт JFIF 1.02, формат изображения, плотность 1x1, длина сегмента 16, базовая линия, точность 8, 650x400, кадры 3

загрузить вывод файла в список Python и использовать 4-е поле в списке.

К вашему сведению, оптимизировали изображения 18000+ для сокращения сетевого трафика.