1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
# frozen_string_literal: true
require_relative 'shell_helper'
require 'nokogiri'
module Booru
module ImageProcessing
class SvgProcessor < Processor
DATA_URI_REGEX = /\Adata:(image\/png|image\/gif|image\/jpeg|image\/svg+xml);base64,/
include ShellHelper
def initialize(original_path, directory, metadata)
super(original_path, directory, metadata)
# We keep around a reference to the Tempfile object so that it doesn't get GC'd (and deleted) too early.
@rasterized_tempfile = Tempfile.new(%w[rendered .png]).tap(&:close)
@rasterized = @rasterized_tempfile.path
end
def pre_process
write_log 'pre_process'
# clean up SVG file to remove embedded scripts and remote references
svg = Nokogiri::XML(IO.read(@original_path))
# The magic.
svg.css('script').each(&:remove)
svg.css('image').reject { |x| x.attributes['href'].to_s =~ DATA_URI_REGEX }.each(&:remove)
File.open(@original_path, 'w') do |file|
file.write svg.to_xml
end
generate_rasterized
end
def generate_rasterized
# Is it OK to do this without scrubbing? - Yeah, that's the whole point of safe-rsvg-convert.
exec_new 'RSVG-CONVERT', ['safe-rsvg-convert', @original_path, @rasterized]
end
def generate_version(dimensions, destination_path)
write_log "generate_version #{dimensions} #{destination_path}"
width, height = dimensions
# resize rasterized version to desired size and optipng the resized version.
# (converting the original file is slower than resizing a rasterized version)
png = ::MiniMagick::Image.open(@rasterized)
png.resize("#{width}x#{height}")
png.write(destination_path)
# is this needed? they didn't used to do that, but I do now. (because I want to)
optipng(destination_path)
end
def generate_full_version(destination_path)
write_log 'generate_full_version'
# full.png -> rasterized
# full.svg -> svg
FileUtils.copy(@rasterized, destination_path)
platform_link(@original_path, File.join(File.dirname(destination_path), 'full.svg'))
end
def post_process
write_log 'post_process'
optipng(@rasterized)
end
end
end
end
|