#!/usr/bin/ruby require "rfpdf" $stderr.puts "Usage #{__FILE__} orig.bmp" if ARGV.size < 1 then exit end MIN_PIXELS = 100 MARGIN = 100 H_GAP = 7 V_GAP = 8 BB_RADIUS = 3 $: << File::join([File::dirname(__FILE__), "..", "..", "common", "ruby"]) require "bitmap.rb" orig = Bitmap::read(open(ARGV.shift, 'r')) raise "cannot find orig.bmp" unless orig tiled = Bitmap::new aspect = (orig.width.to_f / orig.height) puts "Aspect => #{aspect}" if aspect >= 1 then tiled.height = MIN_PIXELS tiled.width = (tiled.height * aspect).to_i else tiled.width = MIN_PIXELS tiled.height = (tiled.width.to_f / aspect).to_i end puts "Width, Height => #{tiled.width}, #{tiled.height}" scale = orig.height.to_f / tiled.height tiled.bits = orig.bits tiled.pixels = [[0, 0, 0]] * tiled.height * tiled.width tiled.width.times{|i| tiled.height.times{|j| tiled[i, j] = orig[(i * scale).to_i, (j * scale).to_i] } } # BMP 出力 open("mod.bmp", "w"){|io| io.print tiled } # PDF 出力 tiled.flip_vertical! orientation = 'P' paper_short = paper_long = MARGIN * 2 paper_width = H_GAP * (tiled.width - 1) paper_height = V_GAP * (tiled.height - 1) if paper_width >= paper_height then orientation = 'L' paper_short += paper_height paper_long += paper_width else paper_short += paper_width paper_long += paper_height end pdf = FPDF::new(orientation, 'mm', [paper_short, paper_long]) pdf.AliasNbPages pdf.extend(PDF_Japanese) pdf.extend(RFPDF) pdf.AddSJISFont pdf.AddPage(orientation) pdf.SetFont('SJIS', '', 128) class Zlib::Deflate class << self alias :orig_deflate :deflate def deflate(s) return orig_deflate(s.kind_of?(StringIO) ? s.string : s) end end end require 'stringio' def pdf.out(s) @buffer = StringIO::new if @buffer.kind_of?(String) buf = @pages[@page] = StringIO::new(@pages[@page]) if @pages[@page].kind_of?(String) def buf.+(s); self << s; end def buf.gsub!(reg,rep); self.string.gsub!(reg,rep); end # Add a line to the document if @state == 2 @pages[@page] << s @pages[@page] << "\n" else @buffer << s.to_s << "\n" end end def pdf.Output(file=nil) # Output PDF to file or return as a string # Finish document if necessary self.Close if(@state<3) @buffer.rewind if file.nil? # Return as a string return @buffer.read else # Save file locally open(file,'wb') do |f| f.write(@buffer.read) end end end def pdf.Circle(mid_x, mid_y, radius, style='') mid_x *= @k mid_y = (@h-mid_y)*@k radius *= @k buf = StringIO::new buf << "q\n\n" # postscript content in pdf # init line type etc. with /GSD gs G g (grey) RG rg (RGB) w=line witdh etc. buf << "1 j\n\n" # line join # translate ("move") circle to mid_y, mid_y buf << "1 0 0 1 #{mid_x} #{mid_y} cm\n" unless (defined?(@radius_cache) || (@radius_cache == radius)) then @radius_cache = radius cache_buf = StringIO::new kappa = 0.5522847498307933984022516322796 # Quadrant 1 x_s = 0.0 # 12 o'clock y_s = 0.0 + radius x_e = 0.0 + radius # 3 o'clock y_e = 0.0 cache_buf << sprintf("%f %f m\n\n", x_s, y_s) # move to 12 o'clock # cubic bezier control point 1, start height and kappa * radius to the right bx_e1 = x_s + (radius * kappa) by_e1 = y_s # cubic bezier control point 2, end and kappa * radius above bx_e2 = x_e by_e2 = y_e + (radius * kappa) # draw cubic bezier from current point to x_e/y_e with bx_e1/by_e1 and bx_e2/by_e2 as bezier control points cache_buf << sprintf("%f %f %f %f %f %f c\n\n", bx_e1, by_e1, bx_e2, by_e2, x_e, y_e) # Quadrant 2 x_s = x_e y_s = y_e # 3 o'clock x_e = 0.0 y_e = 0.0 - radius # 6 o'clock bx_e1 = x_s # cubic bezier point 1 by_e1 = y_s - (radius * kappa) bx_e2 = x_e + (radius * kappa) # cubic bezier point 2 by_e2 = y_e cache_buf << sprintf("%f %f %f %f %f %f c\n\n", bx_e1, by_e1, bx_e2, by_e2, x_e, y_e) # Quadrant 3 x_s = x_e y_s = y_e # 6 o'clock x_e = 0.0 - radius y_e = 0.0 # 9 o'clock bx_e1 = x_s - (radius * kappa) # cubic bezier point 1 by_e1 = y_s bx_e2 = x_e # cubic bezier point 2 by_e2 = y_e - (radius * kappa) cache_buf << sprintf("%f %f %f %f %f %f c\n\n", bx_e1, by_e1, bx_e2, by_e2, x_e, y_e) # Quadrant 4 x_s = x_e y_s = y_e # 9 o'clock x_e = 0.0 y_e = 0.0 + radius # 12 o'clock bx_e1 = x_s # cubic bezier point 1 by_e1 = y_s + (radius * kappa) bx_e2 = x_e - (radius * kappa) # cubic bezier point 2 by_e2 = y_e cache_buf << sprintf("%f %f %f %f %f %f c\n\n", bx_e1, by_e1, bx_e2, by_e2, x_e, y_e) @radius_cache_buf = cache_buf.string end buf << @radius_cache_buf case style when 'F' then buf << 'f' when 'FD', 'DF' then buf << 'b' else buf << 's' end buf << "\n\n" # stroke circle, do not fill and close path # for filling etc. b, b*, f, f* buf << "Q\n" # finish postscript in PDF out(buf.string) end #pdf.Cell(0, 70, "日本語でOK", 0, 0, 'C') #pdf.Ln @color_cahce = nil pdf.SetLineWidth(0.1) pdf.set_draw_color([0x00, 0x00, 0x00]) tiled.width.times{|i| tiled.height.times{|j| sort_rgb = [2, 1, 0].zip(tiled[i, j]).sort{|a, b| b[1] <=> a[1]} color = [0x00, 0x00, 0x00] if sort_rgb[0][1] >= 0x80 then color[sort_rgb[0][0]] = 0xFF end if sort_rgb[2][1] >= 0x80 then color[sort_rgb[1][0]] = color[sort_rgb[2][0]] = 0xFF end #p tiled[i,j], color #pdf.draw_circle(MARGIN + (i * H_GAP), MARGIN + (j * V_GAP), BB_RADIUS, # :border => 1, :border_color => [0x00, 0x00, 0x00], :border_width => 0.1, # :fill => 1, :fill_color => color) pdf.SetFillColor(*color) unless color == @color_cahce @color_cahce = color pdf.Circle(MARGIN + (i * H_GAP), MARGIN + (j * V_GAP), BB_RADIUS, "DF") } p i } open('tiled.pdf', 'w') {|f| f.write(pdf.Output) }