Refactor PNG generation

private-asciicasts
Marcin Kulik 9 years ago
parent fc873a8371
commit b619302e3e

@ -33,7 +33,6 @@ gem 'rack-rewrite', '~> 1.5.0'
gem 'oj', '~> 2.11'
gem 'oj_mimic_json', '~> 1.0'
gem 'foreigner', '~> 1.7'
gem 'chunky_png', '~> 1.3'
group :development do
gem 'quiet_assets', '~> 1.0.1'
@ -65,6 +64,7 @@ group :test do
gem 'shoulda-matchers'
gem 'coveralls', require: false
gem 'rspec-activemodel-mocks'
gem 'chunky_png'
end
group :production do

@ -350,7 +350,7 @@ DEPENDENCIES
capistrano-ext (~> 1.2)
capybara (~> 2.4.1)
carrierwave (~> 0.8.0)
chunky_png (~> 1.3)
chunky_png
coffee-rails (~> 4.0.1)
coveralls
dalli (~> 2.6.2)

@ -1,25 +1,28 @@
class AsciicastImageUpdater
PIXEL_DENSITY = 2
attr_reader :png_generator
attr_reader :rasterizer, :image_inspector
def initialize(png_generator = PngGenerator.new)
@png_generator = png_generator
def initialize(rasterizer = Rasterizer.new, image_inspector = ImageInspector.new)
@rasterizer = rasterizer
@image_inspector = image_inspector
end
def update(asciicast, page_path)
Dir.mktmpdir do |dir|
png_path = "#{dir}/#{asciicast.image_filename}"
image_path = "#{dir}/#{asciicast.image_filename}"
png_generator.generate(page_path, png_path)
rasterizer.generate_image(page_path, image_path, 'png', '.asciinema-player', PIXEL_DENSITY)
File.open(png_path) do |f|
File.open(image_path) do |f|
asciicast.image = f
end
image = ChunkyPNG::Image.from_file(png_path)
# image has double density so "display" size is half the actual one
asciicast.image_width = image.width / 2
asciicast.image_height = image.height / 2
width, height = image_inspector.get_size(image_path)
# "display" size is 1/PIXEL_DENSITY of the actual one
asciicast.image_width = width / PIXEL_DENSITY
asciicast.image_height = height / PIXEL_DENSITY
asciicast.save!
end

@ -0,0 +1,15 @@
require 'open3'
class ImageInspector
def get_size(image_path)
o, e, t = Open3.capture3(%(identify -format "%[fx:w]x%[fx:h]" #{image_path}))
if t.exitstatus != 0
raise RuntimeError, "Couldn't inspect image #{image_path}:\n#{o}\n#{e}"
end
o.split('x').map(&:to_i)
end
end

@ -1,15 +0,0 @@
require 'open3'
class PngGenerator
BINARY_PATH = (Rails.root + "bin" + "asciicast2png").to_s
def generate(page_path, png_path)
o, e, t = Open3.capture3("#{BINARY_PATH} #{page_path} #{png_path}")
if t.exitstatus != 0
raise RuntimeError, "Couldn't generate PNG for #{page_path}:\n#{o}\n#{e}"
end
end
end

@ -0,0 +1,15 @@
require 'open3'
class Rasterizer
BINARY_PATH = (Rails.root + "bin" + "rasterize").to_s
def generate_image(page_path, image_path, format, selector, scale)
o, e, t = Open3.capture3("#{BINARY_PATH} #{page_path} #{image_path} #{format} #{selector} #{scale}")
if t.exitstatus != 0
raise RuntimeError, "Couldn't generate image from #{page_path}:\n#{o}\n#{e}"
end
end
end

@ -2,17 +2,26 @@
var system = require('system');
if (system.args.length < 3) {
console.log("usage: " + system.args[0] + " <url> <filename.png>");
if (system.args.length < 6) {
console.log("usage: " + system.args[0] + " <url> <filename> <format> <selector> <scale>");
console.log(" ex: " + system.args[0] + " page.html page.png png 'body > div' 2");
phantom.exit(1);
}
var url = system.args[1];
var filename = system.args[2];
var format = system.args[3];
var selector = system.args[4];
var scale = parseInt(system.args[5], 10);
var page = require('webpage').create();
page.viewportSize = { width: 9999, height: 9999 };
page.zoomFactor = 2;
page.zoomFactor = scale;
page.onConsoleMessage = function(msg) {
console.log('console.log: ' + msg);
};
page.onError = function(msg, trace) {
console.log('Script error: ' + msg);
@ -31,7 +40,7 @@ page.open(url, function(status) {
phantom.exit(1);
}
var size = page.evaluate(function() {
var rect = page.evaluate(function(selector) {
// Alternative to zoomFactor:
//
// /* scale the whole body */
@ -42,18 +51,27 @@ page.open(url, function(status) {
//
// It has small issue with letter spacing though.
var term = $('.asciinema-player');
return [term.width(), term.height()];
});
var elements = document.querySelectorAll(selector);
if (!size[0]) {
console.log("Couldn't get dimensions of the player");
if (elements.length > 0) {
return elements[0].getBoundingClientRect();
}
}, selector);
if (!rect) {
console.log("Couldn't get geometry of requested DOM element");
phantom.exit(1);
return;
}
page.clipRect = { left: 0, top: 0, width: size[0] * 2, height: size[1] * 2 };
page.render(filename, { format: 'png' });
page.clipRect = {
left: rect.left * scale,
top: rect.top * scale,
width: rect.width * scale,
height: rect.height * scale
};
page.render(filename, { format: format });
phantom.exit(0);
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

@ -0,0 +1,22 @@
require 'rails_helper'
describe ImageInspector do
let(:image_inspector) { ImageInspector.new }
describe '#get_size' do
it 'returns width and height of the image' do
w, h = image_inspector.get_size("#{Rails.root}/spec/fixtures/new-logo-bars.png")
expect(w).to eq(154)
expect(h).to eq(33)
end
context 'when file is not an image' do
it 'raises error' do
expect { image_inspector.get_size("#{Rails.root}/spec/fixtures/snapshot.json") }.to raise_error(RuntimeError)
end
end
end
end
Loading…
Cancel
Save