В Японии огромная культура подарков, и каждый год нам приходится распечатывать тонны этих "ноши".Я сделал просто программу rails для добавления текста в пустое изображение noshi для добавления в нашу систему (уже встроенную в rails).
Для справки, в основном я хотел сделать открытую версию этого, которая не имеетводяной знак: www.noshi.jp
Вот как выглядит контроллер: def create @noshi = Noshi.new (noshi_params)
# Set up variables
ntype = @noshi.ntype
omote = @noshi.omotegaki
olength = omote.length
opsize = (168 - (olength * 12))
namae = @noshi.namae
namae2 = @noshi.namae2
# namae3 = @noshi.namae3
# namae4 = @noshi.namae4
# namae5 = @noshi.namae5
replacements = [ ["(株)", "㈱"], ["(有)", "㈲"] ]
replacements.each {|replacement| namae.gsub!(replacement[0], replacement[1])}
replacements.each {|replacement| namae2.gsub!(replacement[0], replacement[1])}
# replacements.each {|replacement| namae3.gsub!(replacement[0], replacement[1])}
# replacements.each {|replacement| namae4.gsub!(replacement[0], replacement[1])}
# replacements.each {|replacement| namae5.gsub!(replacement[0], replacement[1])}
names = []
names += [namae, namae2] # removed namae3, namae4, namae5 for the time being
longest = names.max_by(&:length)
nlength = longest.length
npsize = (144 - (nlength * 12))
i = 0
# Pull Noshi Type
noshi_img = MiniMagick::Image.open("#{ENV['GBUCKET_PREFIX']}noshi/noshi#{ntype}.jpg")
# Resize to A4 @ 300dpi
noshi_img.resize "2480x3508"
# Iterate through each character
omote.each_char do |c|
# Open new blank/transparent noshi
chars = MiniMagick::Image.open("#{ENV['GBUCKET_PREFIX']}noshi/noshi_blank.png")
chars.resize "2480x3508"
# Draw Each Omotegaki Character
chars.combine_options do |d|
d.gravity 'North'
# Placement based on point size
plcmnt = ((opsize / 12 * 12) + (opsize * i * 1.2))
d.draw "text 0,#{plcmnt} '#{c}'"
d.font 'TakaoPMincho'
d.pointsize opsize
d.fill("#000000")
i += 1
end
# Composite each letter as iterated
noshi_img = noshi_img.composite(chars) do |comp|
comp.compose "Over" # OverCompositeOp
comp.geometry "+0+0" # copy second_image onto first_image from (0, 0)
end
end
# Iterator Reset
i = 0
# Draw Name Text (Line 1)
namae.each_char do |c|
# Iterate through each character
# Open new blank/transparent noshi
chars = MiniMagick::Image.open("#{ENV['GBUCKET_PREFIX']}noshi/noshi_blank.png")
# Resize to a square so it's easy to flip
chars.resize "2480x3508"
chars.combine_options do |d|
# Middle position for first line so set to 0
xplcmnt = (npsize / 12) * 0
yplcmnt = (625 - npsize) - (npsize * i)
d.gravity 'south'
# Placement based on point size, fix for katakana dash
# positive x is
if c == 'ー'
yplcmnt += 15
d.draw "text 0,#{yplcmnt} '|'"
d.pointsize (npsize * 0.85)
else
d.draw "text 0,#{yplcmnt} '#{c}'"
d.pointsize npsize
end
d.font 'TakaoPMincho'
d.fill("#000000")
i += 1
end
# Composite each letter as iterated
noshi_img = noshi_img.composite(chars) do |comp|
comp.compose "Over" # OverCompositeOp
comp.geometry "+0+0" # copy second_image onto first_image from (0, 0)
end
end
# Iterator Reset
i = 0
# Draw Name Text (Line 2)
namae2.each_char do |c|
# Iterate through each character
# Open new blank/transparent noshi
chars = MiniMagick::Image.open("#{ENV['GBUCKET_PREFIX']}noshi/noshi_blank.png")
# Resize to a square so it's easy to flip
chars.resize "2480x3508"
chars.combine_options do |d|
# Next position for second line so set by font size
xplcmnt = (npsize / 6) - npsize * 1.45
yplcmnt = (625 - (npsize * 2)) - (npsize * i)
d.gravity 'south'
# Placement based on point size, fix for katakana dash
if c == 'ー'
yplcmnt += 15
d.draw "text #{xplcmnt},#{yplcmnt} '|'"
d.pointsize (npsize * 0.85)
else
d.draw "text #{xplcmnt},#{yplcmnt} '#{c}'"
d.pointsize npsize
end
d.font 'TakaoPMincho'
d.fill("#000000")
i += 1
end
# Composite each letter as iterated
noshi_img = noshi_img.composite(chars) do |comp|
comp.compose "Over" # OverCompositeOp
comp.geometry "+0+0" # copy second_image onto first_image from (0, 0)
end
end
# Setup and save the file
noshi_img.format "png"
fname = "#{@noshi.omotegaki}_#{@noshi.namae}"
dkey = Time.now.strftime('%Y%m%d%H%M%S')
ext = '.png'
finlname = fname + dkey + ext
noshi_img.write finlname
@noshi.image = File.open(finlname)
File.delete(finlname) if File.exist?(finlname)
respond_to do |format|
if @noshi.save
format.html { redirect_to @noshi, notice: '熨斗が作成されました。' }
format.json { render :show, status: :created, location: @noshi }
else
format.html { render :new }
format.json { render json: @noshi.errors, status: :unprocessable_entity }
end
end end
Как это работает.1. Пользователь рисует фон ноши, выбирает тип заголовка ноши (для お 歳 暮 или お 祝 い и т. Д.) И вводит имя 2. Затем приложение берет соответствующий файл из gCloud для фона ноши.3. Приложение берет каждую букву и вычисляет размер и расположение шрифта на основе количества букв и строк.4. Он берет пустой файл изображения и помещает каждую букву в свое собственное изображение, а затем объединяет их все в окончательное изображение.
ДА, необходимо создать новое изображение для каждой буквы, потому что, насколько яЯ могу сказать, что для ImageMagick нет вертикального текстового формата (в правой части вверх) (довольно важной функции для большой части планеты [Китай, Япония, Корея], поэтому я нахожу довольно удивительным, что ему этого не хватает).
Это отлично работает в разработке, и для наших целей я не против, чтобы это было медленно.Однако в Heroku это возвращает ошибку, если обработка занимает более 30 секунд, даже если noshi создается правильно каждый раз.
ВОПРОС:
Я прочитал, что «масштаб» вместо «изменение размера» может помочь, но, глядя на мой код, я чувствую, что должен быть более эффективный способ сделать то, что я »мы сделали здесьЯ пытался использовать базовые изображения с меньшими размерами файлов, это не очень помогло.
Есть ли более эффективный способ сделать это?
Если нет, есть ли способ отправить пользователя куда-нибудь, чтобы дождаться завершения ноши, чтобы он не возвращал ошибку каждый раз?
ОБНОВЛЕНИЕ:
Просто возвращаюсь, чтобы показать работающий контроллер Ruby on Rails, с которым я закончил:
def create
@noshi = Noshi.new(noshi_params)
# Set up variables
ntype = @noshi.ntype
omote = @noshi.omotegaki
omote_length = omote.length
omote_point_size = (168 - (omote_length * 12))
#make an array with each of the name lines entered
name_array = Array.new
name_array << @noshi.namae
name_array << @noshi.namae2
name_array << @noshi.namae3
name_array << @noshi.namae4
name_array << @noshi.namae5
#replace multi-character prefixes with their single charcter versions
#replace katakana dash with capital I
#insert line breaks after each letter for Japanese vertical type
name_array.each do |namae|
replacements = [ ["(株)", "㈱"], ["(有)", "㈲"], ["ー", "|"] ]
replacements.each {|replacement| namae.gsub!(replacement[0], replacement[1])}
end
def add_line_breaks(string)
string.scan(/.{1}/).join("\n")
end
name_array.map!{ |namae| add_line_breaks(namae)}
#add line breaks after each character for the omote as well
omote = add_line_breaks(omote)
#find the longest string (important: after the character concatenation) in the name array to calculate the point size for the names section
name_array_max_length = (name_array.map { |namae| namae.length }).max
name_point_size = (204 - (name_array_max_length * 10))
#max omote size is 156, and the name needs to be an order smaller than that by default.
if name_point_size > 108
name_point_size = 108
end
# Pull Noshi Type
noshi_img = MiniMagick::Image.open("#{ENV['GBUCKET_PREFIX']}noshi/noshi#{ntype}.jpg")
# Resize to A4 @ 300dpi
noshi_img.resize "2480x3508"
#create the overlay image
name_overlay = MiniMagick::Image.open("#{ENV['GBUCKET_PREFIX']}noshi/noshi_blank.png")
name_overlay.resize "2480x3508"
#first time for omote
name_overlay.combine_options do |image|
image.gravity 'North'
# Placement based on point size
omote_placement_y = (348 - (omote_length * (omote_point_size / 2)))
image.font 'TakaoPMincho'
image.pointsize omote_point_size
image.fill("#000000")
image.draw "text 0,#{omote_placement_y} '#{omote}'"
end
#count number of names in array, add a name for each time
name_array.count.times do |i|
name_overlay.combine_options do |image|
image.gravity 'North'
# Placement based on point size and iteration
name_placement_x = (0 - i * name_point_size)
name_placement_y = 1150 + ((i * name_point_size) - (name_point_size / 2))
image.font 'TakaoPMincho'
image.pointsize name_point_size
image.fill("#000000")
image.draw "text #{name_placement_x},#{name_placement_y} '#{name_array[i]}'"
end
end
noshi_img = noshi_img.composite(name_overlay) do |comp|
comp.compose "Over" #OverCompositeOp
comp.geometry "+0+0" #copy second_image onto first_image from (0, 0)
end
# Setup and save the file
noshi_img.format "png"
#name the file
fname = "#{@noshi.omotegaki}_#{@noshi.namae}"
dkey = Time.now.strftime('%Y%m%d%H%M%S')
ext = '.png'
final_name = fname + dkey + ext
#write a temporary version
noshi_img.write final_name
#write/stream the file to the uploader
@noshi.image = File.open(final_name)
#delete the original temporary
File.delete(final_name) if File.exist?(final_name)
respond_to do |format|
if @noshi.save
format.html { redirect_to @noshi, notice: '熨斗が作成されました。' }
format.json { render :show, status: :created, location: @noshi }
else
format.html { render :new }
format.json { render json: @noshi.errors, status: :unprocessable_entity }
end
end
end