dimensions
dimensions copied to clipboard
WebP support
WebP is really cool format with support in Chrome, Opera and planning to support in Firefox.
Now we can send special CSS only for this browsers and reduce image size to 25 %.
Yes. Please do implement this and send a pull request. ;)
I made a quick hackish solution which you could improve and send a pull request. It uses webp-ffi gem.
require 'dimensions/jpeg_scanner'
module Dimensions
class Reader
GIF_HEADER = [0x47, 0x49, 0x46, 0x38]
PNG_HEADER = [0x89, 0x50, 0x4E, 0x47]
JPEG_HEADER = [0xFF, 0xD8, 0xFF]
TIFF_HEADER_I = [0x49, 0x49, 0x2A, 0x00]
TIFF_HEADER_M = [0x4D, 0x4D, 0x00, 0x2A]
RIFF_HEADER = [0x52, 0x49, 0x46, 0x46]
WEBP_HEADER = [0x57, 0x45, 0x42, 0x50]
attr_reader :type, :width, :height, :angle
def initialize
@process = :determine_type
@type = nil
@width = nil
@height = nil
@angle = nil
@size = 0
@data = ""
@data.force_encoding("BINARY") if @data.respond_to?(:force_encoding)
end
def <<(data)
if @process
@data << data
@size = @data.length
process
end
end
def process(process = @process)
send(@process) if @process = process
end
def determine_type
if @size >= 4
bytes = @data.unpack("C4")
if match_header(GIF_HEADER, bytes)
@type = :gif
elsif match_header(PNG_HEADER, bytes)
@type = :png
elsif match_header(JPEG_HEADER, bytes)
@type = :jpeg
elsif match_header(TIFF_HEADER_I, bytes) || match_header(TIFF_HEADER_M, bytes)
@type = :tiff
elsif match_header(RIFF_HEADER, bytes)
bytes = @data.unpack("C12")[8..-1]
if match_header(WEBP_HEADER, bytes)
@type = :webp
end
end
process @type ? :"extract_#{type}_dimensions" : nil
end
end
def extract_gif_dimensions
if @size >= 10
@width, @height = @data.unpack("x6v2")
process nil
end
end
def extract_png_dimensions
if @size >= 24
@width, @height = @data.unpack("x16N2")
process nil
end
end
def extract_jpeg_dimensions
scanner = JpegScanner.new(@data)
if scanner.scan
@width = scanner.width
@height = scanner.height
@angle = scanner.angle
if @angle == 90 || @angle == 270
@width, @height = @height, @width
end
process nil
end
rescue JpegScanner::ScanError
end
def extract_tiff_dimensions
scanner = TiffScanner.new(@data)
if scanner.scan
@width = scanner.width
@height = scanner.height
process nil
end
rescue TiffScanner::ScanError
end
def extract_webp_dimensions
@width, @height = WebP.webp_size(@data)
process nil
end
def match_header(header, bytes)
bytes[0, header.length] == header
end
end
end
The purpose of dimensions library was originally to be pure-Ruby and without dependencies. I think that adding a WebP dependency is unnacceptabie, especially because it has native extensions.
It would be great if you sent a PR for WebP support, but it would have to be implemented manually.