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).
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
.
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}"
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
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
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)
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]
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
Pour les PNG, j'ai obtenu cette version modifiée de la méthode de ChristopeD.
File.binread(path, 64)[0x10..0x18].unpack('NN')