web-dev-qa-db-fra.com

Existe-t-il un moyen simple d'obtenir les dimensions d'une image dans Ruby?

Je cherche un moyen simple d'obtenir les dimensions de largeur et de hauteur des fichiers image dans Ruby sans avoir à utiliser ImageMagick ou Image Science (sous Snow Leopard).

30
gruner

libimage-size est une bibliothèque Ruby permettant de calculer la taille des images pour une grande variété de formats graphiques. Une gemme est disponible, ou vous pouvez télécharger l'archive source et extraire le fichier image_size.rb.

4
bta

Depuis juin 2012, FastImage qui "trouve la taille ou le type d'une image en fonction de son uri en recherchant le moins possible" est une bonne option. Cela fonctionne avec des images locales et celles sur des serveurs distants.

Un exemple IRB du readme:

require 'fastimage'

FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
=> [266, 56]  # width, height

Affectation de tableau standard dans un script:

require 'fastimage'

size_array = FastImage.size("http://stephensykes.com/images/ss.com_x.gif")

puts "Width: #{size_array[0]}"
puts "Height: #{size_array[1]}"

Ou, en utilisant plusieurs affectations dans un script:

require 'fastimage'

width, height = FastImage.size("http://stephensykes.com/images/ss.com_x.gif")

puts "Width: #{width}"
puts "Height: #{height}"
43
Alan W. Smith

Vous pouvez essayer ceux-ci (non testés):

http://snippets.dzone.com/posts/show/805

PNG:

IO.read('image.png')[0x10..0x18].unpack('NN')
=> [713, 54]

GIF:

IO.read('image.gif')[6..10].unpack('SS')
=> [130, 50]

BMP:

d = IO.read('image.bmp')[14..28]
d[0] == 40 ? d[4..-1].unpack('LL') : d[4..8].unpack('SS')

JPG:

class JPEG
  attr_reader :width, :height, :bits

  def initialize(file)
    if file.kind_of? IO
      examine(file)
    else
      File.open(file, 'rb') { |io| examine(io) }
    end
  end

private
  def examine(io)
    raise 'malformed JPEG' unless io.getc == 0xFF && io.getc == 0xD8 # SOI

    class << io
      def readint; (readchar << 8) + readchar; end
      def readframe; read(readint - 2); end
      def readsof; [readint, readchar, readint, readint, readchar]; end
      def next
        c = readchar while c != 0xFF
        c = readchar while c == 0xFF
        c
      end
    end

    while marker = io.next
      case marker
        when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers
          length, @bits, @height, @width, components = io.readsof
          raise 'malformed JPEG' unless length == 8 + components * 3
        when 0xD9, 0xDA:  break # EOI, SOS
        when 0xFE:        @comment = io.readframe # COM
        when 0xE1:        io.readframe # APP1, contains EXIF tag
        else              io.readframe # ignore frame
      end
    end
  end
end
31
ChristopheD

Il y a aussi une nouvelle bibliothèque (juillet 2011) qui n'existait pas au moment où la question avait été posée à l'origine: les Dimensions rubygem (qui semble être écrit par le même Sam Stephenson, responsable des techniques de manipulation des octets, également suggéré ici.)

Exemple de code ci-dessous du fichier README du projet

require 'dimensions'

Dimensions.dimensions("upload_bird.jpg")  # => [300, 225]
Dimensions.width("upload_bird.jpg")       # => 300
Dimensions.height("upload_bird.jpg")      # => 225
29
hopper

Il existe une méthode pratique dans la gemme Paperclip:

>> Paperclip::Geometry.from_file("/path/to/image.jpg")
=> 180x180

Cela ne fonctionne que si identify est installé. Si ce n'est pas le cas, si PHP est installé, vous pouvez faire quelque chose comme ceci:

system(%{php -r '$w = getimagesize("#{path}"); echo("${w[0]}x${w[1]}");'})
# eg returns "200x100" (width x height)
14
Zubin

J'ai enfin trouvé un moyen rapide et agréable d'obtenir les dimensions d'une image. Vous devriez utiliserMiniMagick.

require 'mini_magick'

image = MiniMagick::Image.open('http://www.thetvdb.com/banners/fanart/original/81189-43.jpg')
assert_equal 1920, image[:width]
assert_equal 1080, image[:height]
8
Adam Harte

Voici une version de la classe JPEG issue de la réponse de ChristopheD qui fonctionne à la fois en Ruby 1.8.7 et en Ruby 1.9. Cela vous permet d'obtenir la largeur et la hauteur d'un fichier image JPEG (.jpg) en regardant directement les bits. (Vous pouvez également utiliser la gemme Dimensions, comme suggéré dans une autre réponse.)

class JPEG
  attr_reader :width, :height, :bits
  def initialize(file)
    if file.kind_of? IO
      examine(file)
    else
      File.open(file, 'rb') { |io| examine(io) }
    end
  end
private
  def examine(io)
    if Ruby_VERSION >= "1.9"
      class << io
        def getc; super.bytes.first; end
        def readchar; super.bytes.first; end
      end
    end
    class << io
      def readint; (readchar << 8) + readchar; end
      def readframe; read(readint - 2); end
      def readsof; [readint, readchar, readint, readint, readchar]; end
      def next
        c = readchar while c != 0xFF
        c = readchar while c == 0xFF
        c
      end
    end
    raise 'malformed JPEG' unless io.getc == 0xFF && io.getc == 0xD8 # SOI
    while marker = io.next
      case marker
        when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers
          length, @bits, @height, @width, components = io.readsof
          raise 'malformed JPEG' unless length == 8 + components * 3
        # colons not allowed in 1.9, change to "then"
        when 0xD9, 0xDA then  break # EOI, SOS
        when 0xFE then        @comment = io.readframe # COM
        when 0xE1 then        io.readframe # APP1, contains EXIF tag
        else                  io.readframe # ignore frame
      end
    end
  end
end
3
matt

Pour les PNG, j'ai obtenu cette version modifiée de la méthode de ChristopeD.

File.binread(path, 64)[0x10..0x18].unpack('NN')
0
Eneroth3