lib/frameit/editor.rb in frameit-2.2.1 vs lib/frameit/editor.rb in frameit-2.2.2
- old
+ new
@@ -31,275 +31,277 @@
def prepare_image
@image = MiniMagick::Image.open(screenshot.path)
end
-
private
- def store_result
- output_path = screenshot.path.gsub('.png', '_framed.png').gsub('.PNG', '_framed.png')
- image.format "png"
- image.write output_path
- Helper.log.info "Added frame: '#{File.expand_path(output_path)}'".green
- end
- # puts the screenshot into the frame
- def put_into_frame
- @image = frame.composite(image, "png") do |c|
- c.compose "Over"
- c.geometry offset['offset']
- end
- end
+ def store_result
+ output_path = screenshot.path.gsub('.png', '_framed.png').gsub('.PNG', '_framed.png')
+ image.format "png"
+ image.write output_path
+ Helper.log.info "Added frame: '#{File.expand_path(output_path)}'".green
+ end
- def offset
- return @offset_information if @offset_information
-
- @offset_information = fetch_config['offset'] || Offsets.image_offset(screenshot)
-
- if @offset_information and (@offset_information['offset'] or @offset_information['offset'])
- return @offset_information
- end
- raise "Could not find offset_information for '#{screenshot}'"
+ # puts the screenshot into the frame
+ def put_into_frame
+ @image = frame.composite(image, "png") do |c|
+ c.compose "Over"
+ c.geometry offset['offset']
end
+ end
- #########################################################################################
- # Everything below is related to title, background, etc. and is not used in the easy mode
- #########################################################################################
+ def offset
+ return @offset_information if @offset_information
- # this is used to correct the 1:1 offset information
- # the offset information is stored to work for the template images
- # since we resize the template images to have higher quality screenshots
- # we need to modify the offset information by a certain factor
- def modify_offset(multiplicator)
- # Format: "+133+50"
- hash = offset['offset']
- x = hash.split("+")[1].to_f * multiplicator
- y = hash.split("+")[2].to_f * multiplicator
- new_offset = "+#{x.round}+#{y.round}"
- @offset_information['offset'] = new_offset
- end
+ @offset_information = fetch_config['offset'] || Offsets.image_offset(screenshot)
- # Do we add a background and title as well?
- def should_add_title?
- return (fetch_config['background'] and (fetch_config['title'] or fetch_config['keyword']))
+ if @offset_information and (@offset_information['offset'] or @offset_information['offset'])
+ return @offset_information
end
+ raise "Could not find offset_information for '#{screenshot}'"
+ end
- # more complex mode: background, frame and title
- def complex_framing
- background = generate_background
-
- if self.frame # we have no frame on le mac
- resize_frame!
- @image = put_into_frame
+ #########################################################################################
+ # Everything below is related to title, background, etc. and is not used in the easy mode
+ #########################################################################################
- # Decrease the size of the framed screenshot to fit into the defined padding + background
- frame_width = background.width - frame_padding * 2
- image.resize "#{frame_width}x"
- end
+ # this is used to correct the 1:1 offset information
+ # the offset information is stored to work for the template images
+ # since we resize the template images to have higher quality screenshots
+ # we need to modify the offset information by a certain factor
+ def modify_offset(multiplicator)
+ # Format: "+133+50"
+ hash = offset['offset']
+ x = hash.split("+")[1].to_f * multiplicator
+ y = hash.split("+")[2].to_f * multiplicator
+ new_offset = "+#{x.round}+#{y.round}"
+ @offset_information['offset'] = new_offset
+ end
- @image = put_device_into_background(background)
+ # Do we add a background and title as well?
+ def should_add_title?
+ return (fetch_config['background'] and (fetch_config['title'] or fetch_config['keyword']))
+ end
- if fetch_config['title']
- @image = add_title
- end
+ # more complex mode: background, frame and title
+ def complex_framing
+ background = generate_background
- image
- end
+ if self.frame # we have no frame on le mac
+ resize_frame!
+ @image = put_into_frame
- # Padding around the frames
- def frame_padding
- multi = 1.0
- multi = 1.7 if self.screenshot.is_triple_density?
- return fetch_config['padding'] * multi
+ # Decrease the size of the framed screenshot to fit into the defined padding + background
+ frame_width = background.width - frame_padding * 2
+ image.resize "#{frame_width}x"
end
- # Returns a correctly sized background image
- def generate_background
- background = MiniMagick::Image.open(fetch_config['background'])
+ @image = put_device_into_background(background)
- if background.height != screenshot.size[1]
- background.resize "#{screenshot.size[0]}x#{screenshot.size[1]}!" # `!` says it should ignore the ratio
- end
- background
+ if fetch_config['title']
+ @image = add_title
end
- def put_device_into_background(background)
- left_space = (background.width / 2.0 - image.width / 2.0).round
- bottom_space = -(image.height / 10).round # to be just a bit below the image bottom
- bottom_space -= 40 if screenshot.is_portrait? # even more for portrait mode
+ image
+ end
- if screenshot.is_mini?
- # Such small devices need special treatment
- bottom_space -= 50 if screenshot.is_portrait?
- bottom_space += 65 unless screenshot.is_portrait?
- end
+ # Padding around the frames
+ def frame_padding
+ multi = 1.0
+ multi = 1.7 if self.screenshot.triple_density?
+ return fetch_config['padding'] * multi
+ end
- self.top_space_above_device = background.height - image.height - bottom_space
+ # Returns a correctly sized background image
+ def generate_background
+ background = MiniMagick::Image.open(fetch_config['background'])
- @image = background.composite(image, "png") do |c|
- c.compose "Over"
- c.geometry "+#{left_space}+#{top_space_above_device}"
- end
+ if background.height != screenshot.size[1]
+ background.resize "#{screenshot.size[0]}x#{screenshot.size[1]}!" # `!` says it should ignore the ratio
+ end
+ background
+ end
- return image
+ def put_device_into_background(background)
+ left_space = (background.width / 2.0 - image.width / 2.0).round
+ bottom_space = -(image.height / 10).round # to be just a bit below the image bottom
+ bottom_space -= 40 if screenshot.portrait? # even more for portrait mode
+
+ if screenshot.mini?
+ # Such small devices need special treatment
+ bottom_space -= 50 if screenshot.portrait?
+ bottom_space += 65 unless screenshot.portrait?
end
- # Resize the frame as it's too low quality by default
- def resize_frame!
- multiplicator = (screenshot.size[0].to_f / offset['width'].to_f) # by how much do we have to change this?
- new_frame_width = multiplicator * frame.width # the new width for the frame
- frame.resize "#{new_frame_width.round}x" # resize it to the calculated witdth
- modify_offset(multiplicator) # modify the offset to properly insert the screenshot into the frame later
+ self.top_space_above_device = background.height - image.height - bottom_space
+
+ @image = background.composite(image, "png") do |c|
+ c.compose "Over"
+ c.geometry "+#{left_space}+#{top_space_above_device}"
end
- # Add the title above the device
- def add_title
- title_images = build_title_images(image.width)
- keyword = title_images[:keyword]
- title = title_images[:title]
+ return image
+ end
- # sum_width: the width of both labels together including the space inbetween
- # is used to calculate the ratio
- sum_width = title.width
- sum_width += keyword.width + keyword_padding if keyword
+ # Resize the frame as it's too low quality by default
+ def resize_frame!
+ multiplicator = (screenshot.size[0].to_f / offset['width'].to_f) # by how much do we have to change this?
+ new_frame_width = multiplicator * frame.width # the new width for the frame
+ frame.resize "#{new_frame_width.round}x" # resize it to the calculated witdth
+ modify_offset(multiplicator) # modify the offset to properly insert the screenshot into the frame later
+ end
- # Resize the 2 labels if necessary
- smaller = 1.0 # default
- ratio = (sum_width + keyword_padding * 2) / image.width.to_f
- if ratio > 1.0
- # too large - resizing now
- smaller = (1.0 / ratio)
+ # Add the title above the device
+ # rubocop:disable Metrics/AbcSize
+ def add_title
+ title_images = build_title_images(image.width)
+ keyword = title_images[:keyword]
+ title = title_images[:title]
- Helper.log.debug "Text for image #{self.screenshot.path} is quite long, reducing font size by #{(ratio - 1.0).round(2)}" if $verbose
+ # sum_width: the width of both labels together including the space inbetween
+ # is used to calculate the ratio
+ sum_width = title.width
+ sum_width += keyword.width + keyword_padding if keyword
- title.resize"#{(smaller * title.width).round}x"
- keyword.resize"#{(smaller * keyword.width).round}x" if keyword
- sum_width *= smaller
- end
+ # Resize the 2 labels if necessary
+ smaller = 1.0 # default
+ ratio = (sum_width + keyword_padding * 2) / image.width.to_f
+ if ratio > 1.0
+ # too large - resizing now
+ smaller = (1.0 / ratio)
- top_space = (top_space_above_device / 2.0 - (actual_font_size / 2.0 * smaller)).round # centered
- left_space = (image.width / 2.0 - sum_width / 2.0).round
+ Helper.log.debug "Text for image #{self.screenshot.path} is quite long, reducing font size by #{(ratio - 1.0).round(2)}" if $verbose
- # First, put the keyword on top of the screenshot, if we have one
- if keyword
- @image = image.composite(keyword, "png") do |c|
- c.compose "Over"
- c.geometry "+#{left_space}+#{top_space}"
- end
+ title.resize "#{(smaller * title.width).round}x"
+ keyword.resize "#{(smaller * keyword.width).round}x" if keyword
+ sum_width *= smaller
+ end
- left_space += keyword.width + (keyword_padding * smaller)
- end
-
- # Then, put the title on top of the screenshot next to the keyword
- @image = image.composite(title, "png") do |c|
+ top_space = (top_space_above_device / 2.0 - (actual_font_size / 2.0 * smaller)).round # centered
+ left_space = (image.width / 2.0 - sum_width / 2.0).round
+
+ # First, put the keyword on top of the screenshot, if we have one
+ if keyword
+ @image = image.composite(keyword, "png") do |c|
c.compose "Over"
c.geometry "+#{left_space}+#{top_space}"
end
- image
- end
- def actual_font_size
- [top_space_above_device / 3.0, @image.width / 30.0].max.round
+ left_space += keyword.width + (keyword_padding * smaller)
end
- # The space between the keyword and the title
- def keyword_padding
- (actual_font_size / 2.0).round
+ # Then, put the title on top of the screenshot next to the keyword
+ @image = image.composite(title, "png") do |c|
+ c.compose "Over"
+ c.geometry "+#{left_space}+#{top_space}"
end
+ image
+ end
+ # rubocop:enable Metrics/AbcSize
- # This will build 2 individual images with the title, which will then be added to the real image
- def build_title_images(max_width)
- words = [:keyword, :title].keep_if{ |a| fetch_text(a) } # optional keyword/title
- results = {}
- words.each do |key|
- # Create empty background
- empty_path = File.join(Helper.gem_path('frameit'), "lib/assets/empty.png")
- title_image = MiniMagick::Image.open(empty_path)
- image_height = actual_font_size * 2 # gets trimmed afterwards anyway, and on the iPad the `y` would get cut
- title_image.combine_options do |i|
- # * 2.0 as the text might be larger than the actual image. We're trimming afterwards anyway
- i.resize "#{max_width * 2.0}x#{image_height}!" # `!` says it should ignore the ratio
- end
+ def actual_font_size
+ [top_space_above_device / 3.0, @image.width / 30.0].max.round
+ end
- current_font = font(key)
- text = fetch_text(key)
- Helper.log.debug "Using #{current_font} as font the #{key} of #{screenshot.path}" if $verbose and current_font
- Helper.log.debug "Adding text '#{fetch_text(key)}'"if $verbose
+ # The space between the keyword and the title
+ def keyword_padding
+ (actual_font_size / 2.0).round
+ end
- # Add the actual title
- title_image.combine_options do |i|
- i.font current_font if current_font
- i.gravity "Center"
- i.pointsize actual_font_size
- i.draw "text 0,0 '#{fetch_text(key)}'"
- i.fill fetch_config[key.to_s]['color']
- end
- title_image.trim # remove white space
-
- results[key] = title_image
+ # This will build 2 individual images with the title, which will then be added to the real image
+ def build_title_images(max_width)
+ words = [:keyword, :title].keep_if { |a| fetch_text(a) } # optional keyword/title
+ results = {}
+ words.each do |key|
+ # Create empty background
+ empty_path = File.join(Helper.gem_path('frameit'), "lib/assets/empty.png")
+ title_image = MiniMagick::Image.open(empty_path)
+ image_height = actual_font_size * 2 # gets trimmed afterwards anyway, and on the iPad the `y` would get cut
+ title_image.combine_options do |i|
+ # * 2.0 as the text might be larger than the actual image. We're trimming afterwards anyway
+ i.resize "#{max_width * 2.0}x#{image_height}!" # `!` says it should ignore the ratio
end
- results
- end
- # Loads the config (colors, background, texts, etc.)
- # Don't use this method to access the actual text and use `fetch_texts` instead
- def fetch_config
- return @config if @config
+ current_font = font(key)
+ text = fetch_text(key)
+ Helper.log.debug "Using #{current_font} as font the #{key} of #{screenshot.path}" if $verbose and current_font
+ Helper.log.debug "Adding text '#{text}'" if $verbose
- config_path = File.join(File.expand_path("..", screenshot.path), "Framefile.json")
- config_path = File.join(File.expand_path("../..", screenshot.path), "Framefile.json") unless File.exists?config_path
- file = ConfigParser.new.load(config_path)
- return {} unless file # no config file at all
- @config = file.fetch_value(screenshot.path)
+ # Add the actual title
+ title_image.combine_options do |i|
+ i.font current_font if current_font
+ i.gravity "Center"
+ i.pointsize actual_font_size
+ i.draw "text 0,0 '#{text}'"
+ i.fill fetch_config[key.to_s]['color']
+ end
+ title_image.trim # remove white space
+
+ results[key] = title_image
end
+ results
+ end
- # Fetches the title + keyword for this particular screenshot
- def fetch_text(type)
- raise "Valid parameters :keyword, :title" unless [:keyword, :title].include?type
+ # Loads the config (colors, background, texts, etc.)
+ # Don't use this method to access the actual text and use `fetch_texts` instead
+ def fetch_config
+ return @config if @config
- # Try to get it from a keyword.strings or title.strings file
- strings_path = File.join(File.expand_path("..", screenshot.path), "#{type.to_s}.strings")
- if File.exists?strings_path
- parsed = StringsParser.parse(strings_path)
- result = parsed.find { |k, v| screenshot.path.include?k }
- return result.last if result
- end
+ config_path = File.join(File.expand_path("..", screenshot.path), "Framefile.json")
+ config_path = File.join(File.expand_path("../..", screenshot.path), "Framefile.json") unless File.exist? config_path
+ file = ConfigParser.new.load(config_path)
+ return {} unless file # no config file at all
+ @config = file.fetch_value(screenshot.path)
+ end
- # No string files, fallback to Framefile config
- result = fetch_config[type.to_s]['text']
- Helper.log.debug "Falling back to default text as there was nothing specified in the .strings file" if $verbose
+ # Fetches the title + keyword for this particular screenshot
+ def fetch_text(type)
+ raise "Valid parameters :keyword, :title" unless [:keyword, :title].include? type
- if !result and type == :title
- # title is mandatory
- raise "Could not get title for screenshot #{screenshot.path}. Please provide one in your Framefile.json".red
- end
+ # Try to get it from a keyword.strings or title.strings file
+ strings_path = File.join(File.expand_path("..", screenshot.path), "#{type}.strings")
+ if File.exist? strings_path
+ parsed = StringsParser.parse(strings_path)
+ result = parsed.find { |k, v| screenshot.path.include? k }
+ return result.last if result
+ end
- return result
+ # No string files, fallback to Framefile config
+ result = fetch_config[type.to_s]['text']
+ Helper.log.debug "Falling back to default text as there was nothing specified in the .strings file" if $verbose
+
+ if !result and type == :title
+ # title is mandatory
+ raise "Could not get title for screenshot #{screenshot.path}. Please provide one in your Framefile.json".red
end
- # The font we want to use
- def font(key)
- single_font = fetch_config[key.to_s]['font']
- return single_font if single_font
+ return result
+ end
- fonts = fetch_config[key.to_s]['fonts']
- if fonts
- fonts.each do |font|
- if font['supported']
- font['supported'].each do |language|
- if screenshot.path.include?language
- return font["font"]
- end
+ # The font we want to use
+ def font(key)
+ single_font = fetch_config[key.to_s]['font']
+ return single_font if single_font
+
+ fonts = fetch_config[key.to_s]['fonts']
+ if fonts
+ fonts.each do |font|
+ if font['supported']
+ font['supported'].each do |language|
+ if screenshot.path.include? language
+ return font["font"]
end
- else
- # No `supported` array, this will always be true
- Helper.log.debug "Found a font with no list of supported languages, using this now" if $verbose
- return font["font"]
end
+ else
+ # No `supported` array, this will always be true
+ Helper.log.debug "Found a font with no list of supported languages, using this now" if $verbose
+ return font["font"]
end
end
-
- Helper.log.debug "No custom font specified for #{screenshot}, using the default one" if $verbose
- return nil
end
+
+ Helper.log.debug "No custom font specified for #{screenshot}, using the default one" if $verbose
+ return nil
+ end
end
end