IMGKit
Create JPGs using plain old HTML+CSS. Uses wkhtmltoimage on the backend which renders HTML using Webkit.
Heavily based on PDFKit.
Install
IMGKit
gem install imgkit
wkhtmltoimage
- Use the
wkhtmltoimage-binary
gem (mac + linux)
gem install wkhtmltoimage-binary
- Install by hand: http://wkhtmltopdf.org/downloads.html
- Use installer:
sudo imgkit --install-wkhtmltoimage
install latest version into /usr/local/bin (overwrite defaults with e.g. ARCHITECTURE=amd64 TO=/home/foo/bin)
Usage
# IMGKit.new takes the HTML and any options for wkhtmltoimage
# run `wkhtmltoimage --extended-help` for a full list of options
kit = IMGKit.new(html, :quality => 50)
kit.stylesheets << '/path/to/css/file'
kit.javascripts << '/path/to/js/file'
# Get the image BLOB
img = kit.to_img
# New in 1.3!
img = kit.to_img(:jpg) #default
img = kit.to_img(:jpeg)
img = kit.to_img(:png)
# Save the image to a file
file = kit.to_file('/path/to/save/file.jpg')
file = kit.to_file('/path/to/save/file.png')
# IMGKit.new can optionally accept a URL or a File.
# Stylesheets nor Javascripts can not be added when source is provided as a URL of File.
kit = IMGKit.new('http://google.com')
kit = IMGKit.new(File.new('/path/to/html'))
# Add any kind of option through meta tags
IMGKit.new('<html><head><meta name="imgkit-quality" content="75"...
# Format shortcuts - New in 1.3!
IMGKit.new("hello").to_jpg
IMGKit.new("hello").to_jpeg
IMGKit.new("hello").to_png
Note: Ruby's buffered I/O means that if you want to write the string data to a file or tempfile make sure to call `#flush` to ensure the contents don't get stuck in the buffer.
Configuration
wkhtmltoimage
binary location
If you're on Windows or you installed wkhtmltoimage
by hand to a location other than /usr/local/bin
you will need to tell IMGKit where the binary is. You can configure IMGKit like so:
# config/initializers/imgkit.rb
IMGKit.configure do |config|
config.wkhtmltoimage = '/path/to/wkhtmltoimage'
end
You could put the binaries in your bin/ folder and load the correct one depending on the platform and CPU type:
# config/initializers/imgkit.rb
IMGKit.configure do |config|
if OS.linux? && OS.host_cpu == "x86_64"
config.wkhtmltoimage =
Rails.root.join("bin", "wkhtmltoimage-linux-amd64").to_s
elsif OS.mac? && OS.host_cpu == "x86_64"
config.wkhtmltoimage =
Rails.root.join("bin", "wkhtmltoimage-macos-amd64").to_s
else
puts OS.report
abort "You need to add a binary for wkhtmltoimage for your OS and CPU"
end
end
To get wkhtmltoimage-linux-amd64
you can get the latest .deb
(if you are targeting ubuntu) from https://github.com/wkhtmltopdf/packaging/releases
docker run -it -v $(pwd):/data ubuntu:latest /bin/bash
# or with fish
# docker run -it -v (pwd):/data ubuntu:latest /bin/bash
cd data
dpkg -x wkhtmltox_0.12.6-1.focal_amd64.deb out
exit
cp out/usr/local/bin/wkhtmltoimage bin/wkhtmltoimage-linux-amd64
And for wkhtmltoimage-macos-amd64
you can download the .pkg
from https://github.com/wkhtmltopdf/packaging/releases,
install it, then:
mv /usr/local/bin/wkhtmltoimage bin/wkhtmltoimage-macos-amd64
Default image format
May be set to one of IMGKit::KNOWN_FORMATS = [:jpg, :jpeg, :png]
config.default_format = :png
<meta>
tag options (see Usage) :
Prefix for May be changed from its default (imgkit-
):
config.meta_tag_prefix = 'imgkit-option'
Additional default options
Any flag accepted by wkhtmltoimage
may be set thus:
config.default_options = {
:quality => 60
}
For a flag which takes no parameters, use true
for the value:
'no-images' => true
For flags with multiple parameters, use an array:
:cookie => ['my_session', '123BADBEEF456']
Overriding options
When initializing an IMGKit
options may be may be set for the life time of the IMGKit
object:
IMGKit.new('http://example.com/form', :post => ['my_field', 'my_unique_value'])
Heroku
get a version of wkhtmltoimage
as an amd64 binary and commit it
to your git repo. I like to put mine in "./bin/wkhtmltoimage-amd64"
assuming its in that location you can just do:
IMGKit.configure do |config|
config.wkhtmltoimage = Rails.root.join('bin', 'wkhtmltoimage-amd64').to_s if ENV['RACK_ENV'] == 'production'
end
If you're not using Rails just replace Rails.root with the root dir of your app.
Rails
Mime Types
register a .jpg mime type in:
#config/initializers/mime_type.rb
Mime::Type.register "image/jpeg", :jpg
register a .png mime type in:
#config/initializers/mime_type.rb
Mime::Type.register "image/png", :png
Controller Actions
You can respond in a controller with:
@kit = IMGKit.new(render_to_string)
format.jpg do
send_data(@kit.to_jpg, :type => "image/jpeg", :disposition => 'inline')
end
- or -
format.png do
send_data(@kit.to_png, :type => "image/png", :disposition => 'inline')
end
- or -
respond_to do |format|
send_data(@kit.to_img(format.to_sym),
:type => "image/#{format}", :disposition => 'inline')
end
This allows you to take advantage of rails page caching so you only generate the image when you need to.
--user-style-sheet workaround
To overcome the lack of support for --user-style-sheet option by wkhtmltoimage 0.10.0 rc2 as reported here http://code.google.com/p/wkhtmltopdf/issues/detail?id=387
require 'imgkit'
require 'restclient'
require 'stringio'
url = 'http://domain/path/to/stylesheet.css'
css = StringIO.new( RestClient.get(url) )
kit = IMGKit.new(<<EOD)
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>coolest converter</title>
</head>
<body>
<div class="cool">image kit</div>
</body>
</html>
EOD
kit.stylesheets << css
Paperclip Example
Model:
class Model < ActiveRecord::Base
# attr_accessible :title, :body
has_attached_file :snapshot, :storage => :s3,
:s3_credentials => "#{Rails.root}/config/s3.yml"
end
Controller:
def upload_image
model = Model.find(params[:id])
html = render_to_string
kit = IMGKit.new(html)
img = kit.to_img(:png)
file = Tempfile.new(["template_#{model.id}", 'png'], 'tmp',
:encoding => 'ascii-8bit')
file.write(img)
file.flush
model.snapshot = file
model.save
file.unlink
end
CarrierWave Workaround
Contributed by @ticktricktrack
class MyClass < ActiveRecord::Base
mount_uploader :snapshot, SnapshotUploader
after_create :take_snapshot
# private
def take_snapshot
file = Tempfile.new(["template_#{self.id.to_s}", '.jpg'], 'tmp', :encoding => 'ascii-8bit')
file.write(IMGKit.new(self.html_body, quality: 50, width: 600).to_jpg)
file.flush
self.snapshot = file
self.save
file.unlink
end
end
Note on Patches/Pull Requests
- Fork the project.
- Setup your development environment with: gem install bundler; bundle install
- Make your feature addition or bug fix.
- Add tests for it. This is important so I don't break it in a future version unintentionally.
- Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
- Send me a pull request. Bonus points for topic branches.
Testing
Travis.yml is configured for multiple rubies, so I would just test a 2.1.x version and let travis handle the rest.
Copyright
Copyright (c) 2010 Chris Continanza Based on work by Jared Pace See LICENSE for details.