Ich bin auf der Suche nach einem einfachen Weg, um Breiten- und Höhenmaße für Bilddateien in Ruby zu ermitteln, ohne ImageMagick oder Image Science (mit Snow Leopard) verwenden zu müssen.
libimage-size ist eine Ruby-Bibliothek zur Berechnung von Bildgrößen für eine Vielzahl von Grafikformaten. Ein Juwel ist verfügbar, oder Sie können den Quell-Tarball herunterladen und die image_size.rb
-Datei extrahieren.
Ab Juni 2012 ist FastImage eine gute Option, mit der "die Größe oder der Typ eines Bilds anhand seiner Uri ermittelt wird, indem so wenig wie nötig abgerufen wird". Es funktioniert mit lokalen Images und solchen auf Remote-Servern.
Ein IRB-Beispiel aus der Readme:
require 'fastimage'
FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
=> [266, 56] # width, height
Standard-Array-Zuordnung in einem Skript:
require 'fastimage'
size_array = FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
puts "Width: #{size_array[0]}"
puts "Height: #{size_array[1]}"
Oder verwenden Sie mehrere Zuweisungen in einem Skript:
require 'fastimage'
width, height = FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
puts "Width: #{width}"
puts "Height: #{height}"
Sie könnten dies versuchen (ungetestet):
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
Es gibt auch eine neue Bibliothek (Juli 2011), die zu dem Zeitpunkt, als die Frage ursprünglich gestellt wurde, noch nicht verfügbar war: das Dimensions Rubygem (das anscheinend von demselben Sam Stephenson verfasst wurde, der auch für die vorgeschlagenen Byte-Manipulationstechniken verantwortlich ist Hier.)
Unten ein Codebeispiel aus der README-Datei des Projekts
require 'dimensions'
Dimensions.dimensions("upload_bird.jpg") # => [300, 225]
Dimensions.width("upload_bird.jpg") # => 300
Dimensions.height("upload_bird.jpg") # => 225
Es gibt eine praktische Methode in der Büroklammer:
>> Paperclip::Geometry.from_file("/path/to/image.jpg")
=> 180x180
Dies funktioniert nur, wenn identify
installiert ist. Wenn dies nicht der Fall ist und PHP installiert ist, können Sie Folgendes tun:
system(%{php -r '$w = getimagesize("#{path}"); echo("${w[0]}x${w[1]}");'})
# eg returns "200x100" (width x height)
Ich habe endlich einen netten schnellen Weg gefunden, um Dimensionen eines Bildes zu erhalten. Sie solltenMiniMagickverwenden.
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]
Hier ist eine Version der JPEG-Klasse aus ChristopheDs Antwort, die sowohl in Ruby 1.8.7 als auch in Ruby 1.9 funktioniert. Auf diese Weise können Sie die Breite und Höhe einer JPEG-Bilddatei (.jpg) ermitteln, indem Sie die Bits direkt betrachten. (Alternativ können Sie auch den Dimensions-Edelstein verwenden, wie in einer anderen Antwort vorgeschlagen.)
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
Für PNGs habe ich diese modifizierte Version der ChristopeD-Methode zum Laufen gebracht.
File.binread(path, 64)[0x10..0x18].unpack('NN')