Last active
August 29, 2015 14:18
-
-
Save doraTeX/854c7b2169ff8f023f74 to your computer and use it in GitHub Desktop.
「ことばのおもみ」自動測定スクリプト http://doratex.hatenablog.jp/entry/20150331/1427755389
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby -W0 | |
# coding: utf-8 | |
# | |
# This software is derived from bmp.rb provided by Yoichi Yokogawa. | |
# https://github.com/yoyoichi/bmp-ruby | |
# | |
# This software is released under the MIT License. | |
# http://opensource.org/licenses/mit-license.php | |
### BitMap class | |
class BitMap | |
def initialize(width, height, dpi = 96) | |
@width = width | |
@height = height | |
@line_size = width * 3 + (4 - (width * 3) % 4) % 4 | |
@buf_size = @line_size * height | |
@buf = ("\000" * @buf_size).encode('BINARY') | |
@bit_count = 24 | |
@compression = 0 | |
@size_image = 0 | |
@x_pix_per_meter = (39.375 * dpi).round | |
@y_pix_per_meter = (39.375 * dpi).round | |
@clr_used = 0 | |
@cir_important = 0 | |
@black_count = -1 | |
@black_ratio = -1 | |
end | |
attr_writer :buf | |
attr_reader :width, :height | |
def BitMap.read(filename) | |
buf = nil | |
open(filename, "rb") do |f| | |
buf = f.read | |
end | |
if buf[0] != ?B or buf[1] != ?M | |
raise '[Error] read: Invalid Header' | |
end | |
real_buf_size = buf.size | |
buf_size = (buf[2, 4].unpack("l*"))[0] | |
if buf_size > real_buf_size | |
raise '[Error] read: Invalid Buffer Size' | |
end | |
data_offset = (buf[10, 4].unpack("l*"))[0] | |
if data_offset != 54 | |
raise '[Error] read: Invalid Data Offset' | |
end | |
width = (buf[18, 4].unpack("l*"))[0] | |
height = (buf[22, 4].unpack("l*"))[0] | |
bit_count = (buf[28, 2].unpack("s*"))[0] | |
if bit_count != 24 | |
raise '[Error] read: Unsupported Color Depth' | |
end | |
compression = (buf[30, 4].unpack("l*"))[0] | |
if compression != 0 | |
raise '[Error] read: Compression Not Supported' | |
end | |
pix_per_meter = (buf[38, 4].unpack("l*"))[0] | |
dpi = pix_per_meter / 39.375 | |
image_buf = buf[54, buf_size] | |
image = BitMap.new(width, height, dpi) | |
image.buf = image_buf | |
return image | |
end | |
def pget(x, y) | |
x = 0 if x < 0 | |
x = @width - 1 if x >= @width | |
y = 0 if y < 0 | |
y = @height - 1 if y >= @height | |
addr = (@height - 1 - y) * @line_size + x * 3 | |
b = @buf[addr ].ord | |
g = @buf[addr + 1].ord | |
r = @buf[addr + 2].ord | |
return [r, g, b] | |
end | |
def blackPixelCount | |
return @black_count if @black_count >= 0 | |
count = 0 | |
(0...@width).each{|x| | |
(0...@height).each{|y| | |
count +=1 if pget(x, y) == [0, 0, 0] | |
} | |
} | |
@black_count = count | |
end | |
def blackPixelRatio | |
return @black_ratio if @black_ratio >= 0 | |
@black_ratio = blackPixelCount.to_f / (@width*@height) | |
end | |
end | |
### main | |
require 'fileutils' | |
require 'optparse' | |
SCRIPT = $0 | |
TEMPNAME = "wordweight" | |
$texfile = "#{TEMPNAME}.tex" | |
$bmpfile = "#{TEMPNAME}.bmp" | |
def usage | |
puts "Usage : #{File.basename(SCRIPT)} [\e[1m-s\e[0m \e[4msize\e[0m] [\e[1m-r\e[0m \e[4mresolution\e[0m] [\e[1m-d\e[0m] \e[4mfontname\e[0m \e[4mwords...\e[0m " | |
puts "Options:" | |
puts " \e[1m-s\e[0m \e[4msize\e[0m : set font size (pt) (default: 100)" | |
puts " \e[1m-r\e[0m \e[4mresolution\e[0m : set resoluion for font rendering (default: 600)" | |
puts " \e[1m-d\e[0m : do not delete temporary files for debug" | |
exit | |
end | |
def clean | |
FileUtils.rm_rf([$texfile, "#{TEMPNAME}.aux", "#{TEMPNAME}.log", "#{TEMPNAME}.pdf", $bmpfile]) | |
end | |
def measure(word) | |
clean | |
zw = $fontsize.to_f | |
ht = 0.88*zw | |
dp = 0.12*zw | |
open($texfile, "w") {|f| f.write <<EOS | |
\\documentclass{article} | |
\\usepackage{fontspec} | |
\\newfontfamily\\theFont{#{$fontname}} | |
\\pagestyle{empty} | |
\\usepackage[tightpage,active]{preview} | |
\\PreviewEnvironment{minipage} | |
\\parindent=0pt | |
\\begin{document} | |
\\setbox0=\\hbox{\\theFont\\fontsize{#{$fontsize}pt}{0pt}\\selectfont #{word}}% | |
\\ht0=#{ht}pt | |
\\dp0=#{dp}pt | |
\\begin{minipage}{\\wd0}\\box0\\end{minipage} | |
\\end{document} | |
EOS | |
} | |
system("xelatex -no-shell-escape -interaction=batchmode #{TEMPNAME} > /dev/null") | |
system("gs -sDEVICE=bmp16m -dNOPAUSE -dBATCH -sOutputFile=#{$bmpfile} -r#{$resolution} #{TEMPNAME}.pdf > /dev/null") if $? == 0 | |
if $? == 0 && File.exist?($bmpfile) | |
bmp = BitMap.read($bmpfile) | |
puts "Font name : #{$fontname}" | |
puts "Font size : #{$fontsize}pt" | |
puts "Word : #{word}" | |
puts "Resolution : #{$resolution}dpi" | |
puts "Total pixels : #{bmp.width * bmp.height}" | |
puts "Black pixels : #{bmp.blackPixelCount}" | |
puts "Ratio : #{sprintf("%.2f%%", 100*bmp.blackPixelRatio)}" | |
else | |
puts "ERROR" | |
end | |
clean unless $debug | |
end | |
opt = OptionParser.new | |
$fontsize = 100 | |
$resolution = 600 | |
$debug = false | |
begin | |
opt.on('-s VAL') {|v| | |
$fontsize = v.to_i | |
usage unless $fontsize > 0 | |
} | |
opt.on('-r VAL') {|v| | |
$resolution = v.to_i | |
usage unless $resolution > 0 | |
} | |
opt.on('-d') { $debug = true } | |
opt.parse!(ARGV) | |
usage unless ARGV.length >= 2 | |
$fontname = ARGV.shift | |
words = ARGV | |
rescue | |
usage | |
end | |
words.each{|w| measure(w)} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment