I try find way write Paperclip processor which generate image based on other style.
I need generate style with size "54x54" and then generate another style with size 120x120 based on "54x54" style (background + small image).
Model:
class Medal < ActiveRecord::Base
has_attached_file :icon,
styles: {
:'48' => ['48', :png],
:'54' => ['54', :png],
:'120' => ['120', :png],
:'fb' => { geometry: '120', format: :png, processors: [ :fb_medal_icon ] },
}
end
Processor:
module Paperclip
class FbMedalIcon < Processor
def initialize(file, options = {}, attachment = nil)
super
#whiny = options[:whiny].nil? ? true : options[:whiny]
#format = File.extname(#file.path)
#basename = File.basename(#file.path, #format)
end
def make
src = #file
dst = Tempfile.new([#basename, #format].compact.join("."))
dst.binmode
begin
arguments = '-gravity center :icon :background :dest'
options = {
icon: icon_path,
background: "#{File.expand_path(src.path)}[0]",
dest: File.expand_path(dst.path)
}
composite(arguments, options)
rescue Cocaine::ExitStatusError
raise Paperclip::Error, "There was an error processing the icon for #{#basename}" if #whiny
rescue Cocaine::CommandNotFoundError
raise Paperclip::Errors::CommandNotFoundError.new("Could not run the `composite` command. Please install ImageMagick.")
end
dst
end
def composite(arguments = "", local_options = {})
Paperclip.run('composite', arguments, local_options)
end
private
def icon_path
style = :'54'
icon = #attachment.instance.icon
if icon.queued_for_write[style].present?
icon.queued_for_write[style].path
else
Paperclip.io_adapters.for(icon.styles[style]).path
end
end
end
end
But I get error "NoMethodError: undefined method `path' for nil:NilClass"
from ruby-1.9.3-p484/gems/paperclip-4.1.1/lib/paperclip/attachment.rb:174:in `staged_path'
from ruby-1.9.3-p484/gems/paperclip-4.1.1/lib/paperclip/io_adapters/attachment_adapter.rb:25:in `copy_to_tempfile'
from ruby-1.9.3-p484/gems/paperclip-4.1.1/lib/paperclip/io_adapters/attachment_adapter.rb:19:in `cache_current_values'
from ruby-1.9.3-p484/gems/paperclip-4.1.1/lib/paperclip/io_adapters/attachment_adapter.rb:11:in `initialize'
from ruby-1.9.3-p484/gems/paperclip-4.1.1/lib/paperclip/io_adapters/registry.rb:31:in `new'
from ruby-1.9.3-p484/gems/paperclip-4.1.1/lib/paperclip/io_adapters/registry.rb:31:in `for'
from /my_projects/MyApp/lib/paperclip_processors/fb_medal_icon.rb:63:in `icon_path'
from /my_projects/MyApp/lib/paperclip_processors/fb_medal_icon.rb:24:in `make'
Any idea how right handle this case?
You've not mentioned why you've used your own processor, but I'd highly recommend using ImageMagick to handle the styling
If you install ImageMagick (it can be a problem on Windows), you'll be able to get your styles without using the custom processor. I have code if you'd like to see
Related
Using Paperclip for file upload in my Rails app and I need to convert images into separate PDFs before uploading to Amazon S3 servers. I know I can use Prawn for the image to PDF conversion and I can intercept the file using the answer to this stack overflow question
In the model:
has_attached_file :file
before_file_post_process :convert_images
...
def convert_images
if file_content_type == 'image/png' || file_content_type == 'image/jpeg'
original_file = file.queued_for_write[:original]
filename = original_file.path.to_s
pdf = Prawn::Document.new
pdf.image open(filename), :scale => 1.0, position: :center
file = pdf.render
end
end
However I'm unable to actually convert the image that is stored on S3. Any ideas what I'm missing?
Edit: Adding a save! call results in validations failing that weren't doing so before.
Was able to figure it out.
changed:
before_file_post_process :convert_images
to:
before_save :convert_images
and changed my convert_images method to:
def convert_images
if file_content_type == 'image/png' || file_content_type == 'image/jpeg'
file_path = file.queued_for_write[:original].path.to_s
temp_file_name = file_file_name.split('.')[0] + '.pdf'
pdf = Prawn::Document.new(:page_size => "LETTER", :page_layout => :portrait)
pdf.image File.open("#{file_path}"), :fit => [612, 792], position: :center
pdf.render_file temp_file_name
file_content_type = 'application/pdf'
self.file = File.open(temp_file_name)
File.delete(temp_file_name)
end
end
I am trying to add text on my image with RMagick. This is my code:
version :thumb do
process :resize_to_limit => [400, 300]
process :addt
end
def addt
manipulate! do |img|
title = Magick::Draw.new
img = title.annotate(img, 0,0,0,40, 'test') {
self.font_family = 'Helvetica'
self.fill = 'white'
self.stroke = 'transparent'
self.pointsize = 32
self.font_weight = Magick::BoldWeight
self.gravity = Magick::CenterGravity
}
end
end
The problem with this code is that it totally blocks my application. I can't open any other part of my site and can't turn off my server process. I need to kill server process completely to start the application again.
What could be a problem?
just try this, i cant solve your code . but hope this one can help you with that.
1st install this gem
Source: https://github.com/rmagick/rmagick
next
To start playing with RMagick, you can stick this in one of your controllers:
require ‘RMagick’
include Magick
def addt
img = ImageList.new(‘Your image path eg.public/computer-cat.jpg’)
txt = Draw.new
img.annotate(txt, 0,0,0,0, “The text you want to add in the image”){
txt.gravity = Magick::SouthGravity
txt.pointsize = 25
txt.stroke = ‘#000000′
txt.fill = ‘#ffffff’
txt.font_weight = Magick::BoldWeight
}
img.format = ‘jpeg’
send_data img.to_blob, :stream => ‘false’, :filename => ‘test.jpg’, :type => ‘image/jpeg’, :disposition => ‘inline’
end
hope this one help you..
if you cant understand ..click this http://mikewilliamson.wordpress.com/2010/04/29/adding-text-to-pictures-with-rmagick-and-rails/
I'm working on an app that allows users to create custom watermarks for documents. I'd like to store the watermark images using carrierwave.
So far, the image is being created, but the model.image attribute is not getting created/saved with carrierwave. Help?
class Watermark < ActiveRecord::Base
mount_uploader :image, MarkImageUploader
before_save :textToImage
def textToImage
img = MiniMagick::Image.open("#{Rails.root}/public/images/blank.png")
img.combine_options do |c|
c.gravity 'Center'
c.draw "rotate 315 text 50,-375 '#{self.text}'"
c.font '-*-helvetica-*-r-*-*-125-*-*-*-*-*-*-2'
c.fill("#dddddd")
end
self.image = img
end
end
Turns out you can assign the file to the carrierwave column in the controller:
#watermark.image = File.open("#{Rails.root}/public/images/blank.png")
and then handle the addition of text in the uploader:
process :addText
def addText
t = model.text
manipulate! do |img|
img.combine_options do |cmd|
cmd.gravity 'Center'
cmd.fill("lightgray")
cmd.draw "rotate 325 text 85,-30 '#{t.upcase}'"
cmd.font "#{Rails.root}/public/images/fonts/Vera.ttf"
cmd.pointsize '60'
end
result = img
end
end
How can I get the width and height of the current instance of carrierwave?
Something like this:
car_images.each do | image|
image_tag( image.photo_url, :width => image.photo_width, :height => image.photo_height)
end
Unfortunately image.photo_width and image.photo_height are not working.
I need to specify the width and height of the images, it is required on the jquery plugin I'm using.
Combine https://github.com/jnicklas/carrierwave/wiki/How-to:-Get-version-image-dimensions and https://github.com/jnicklas/carrierwave/wiki/How-to:-Store-the-uploaded-file-size-and-content-type and you get:
class Image
before_save :update_image_attributes
private
def update_image_attributes
if image.present?
self.content_type = image.file.content_type
self.file_size = image.file.size
self.width, self.height = `identify -format "%wx%h" #{image.file.path}`.split(/x/)
# if you also need to store the original filename:
# self.original_filename = image.file.filename
end
end
end
You can save the height and width as attributes with your model quite easily if using Rmagick. In the Carrierwave uploader:
class ArtworkUploader < CarrierWave::Uploader::Base
def geometry
#geometry ||= get_geometry
end
def get_geometry
if #file
img = ::Magick::Image::read(#file.file).first
geometry = { width: img.columns, height: img.rows }
end
end
end
And in your model:
class Artwork < ActiveRecord::Base
mount_uploader :image, ArtworkUploader
before_save :save_image_dimensions
private
def save_image_dimensions
if image_changed?
self.image_width = image.geometry[:width]
self.image_height = image.geometry[:height]
end
end
end
Or just use FastImage. This makes it much easier to measure attachments retroactively.
#JamieD's answer worked for me, with one exception. I was using MiniMagick.
So I added something like this to my uploader.
def geometry
#geometry ||= get_geometry
end
def get_geometry
if #file
img = ::Magick::Image::read(#file.file).first
geometry = { width: img.columns, height: img.rows }
end
end
I always want square images of 100x100 but i dont want to scale.
If the it is an image of 100X80 i want it vertical aligned with 10 white pixels on top and 10 white pixels on bottm.
Is there an easy way to handle this?
Using Rails 2.1 with paperclip 2.3.0
Might not be appropriate, however you can use CSS to easily acchieve this:
html:
<div class="paperclip-holder">
<%= your_paperclip_image_tag %>
</div>
css:
.paperclip-holder{
width: 100px;
height: 100px;
background: #ffffff;
vertical-align: center;
text-align: center;
}
Ok i finally managed it.
i used this script to crop the image the way i want.
http://www.fmwconcepts.com/imagemagick/squareup/index.php
I made a new Paperclip processor and named CropFile. I copy pasted the Thumbnail processor from paper clip and added some lines to run the squareup script.
in my model:
has_attached_file :widget_image, :styles => { :square_60 => ["60x60", :png], :square_100 => ["100x100", :png] }, :processors => [:crop_file]
I added paperclip_postprocess.rb in initializers
#paperclip_postprocess.rb
module Paperclip
# Handles thumbnailing images that are uploaded.
class CropFile < Processor
attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options, :source_file_options
# Creates a Thumbnail object set to work on the +file+ given. It
# will attempt to transform the image into one defined by +target_geometry+
# which is a "WxH"-style string. +format+ will be inferred from the +file+
# unless specified. Thumbnail creation will raise no errors unless
# +whiny+ is true (which it is, by default. If +convert_options+ is
# set, the options will be appended to the convert command upon image conversion
def initialize file, options = {}, attachment = nil
super
geometry = options[:geometry]
#file = file
#crop = geometry[-1,1] == '#'
#target_geometry = Geometry.parse geometry
#current_geometry = Geometry.from_file #file
#source_file_options = options[:source_file_options]
#convert_options = options[:convert_options]
#whiny = options[:whiny].nil? ? true : options[:whiny]
#format = options[:format]
#path = options[:path]
#source_file_options = #source_file_options.split(/\s+/) if #source_file_options.respond_to?(:split)
#convert_options = #convert_options.split(/\s+/) if #convert_options.respond_to?(:split)
#current_format = File.extname(#file.path)
#basename = File.basename(#file.path, #current_format)
# reg exp to get the with and the height
geometry.match(/(\d+)(#|>|<)?x/)
#width = $1
#height = $3
end
# Returns true if the +target_geometry+ is meant to crop.
def crop?
#crop
end
# Returns true if the image is meant to make use of additional convert options.
def convert_options?
!#convert_options.nil? && !#convert_options.empty?
end
# Performs the conversion of the +file+ into a thumbnail. Returns the Tempfile
# that contains the new image.
def make
src = #file
dst = Tempfile.new(['bla', ".png"])
dst.binmode
begin
parameters = []
parameters << source_file_options
parameters << ":source"
parameters << transformation_command
parameters << convert_options
parameters << ":dest"
parameters = parameters.flatten.compact.join(" ").strip.squeeze(" ")
Paperclip.run("convert", parameters, :source => "#{File.expand_path(src.path)}[0]", :dest => File.expand_path(dst.path))
# Cropping it with vertical and horizontal aligning
`#{Rails.root}/public/scripts/squareup.sh -c trans -s #{#width} #{File.expand_path(src.path)} #{File.expand_path(dst.path)}`
rescue PaperclipCommandLineError => e
raise PaperclipError, "There was an error processing the thumbnail for #{#basename}" if #whiny
end
dst
end
# Returns the command ImageMagick's +convert+ needs to transform the image
# into the thumbnail.
def transformation_command
scale, crop = #current_geometry.transformation_to(#target_geometry, crop?)
trans = []
trans << "-resize" << %["#{scale}"] unless scale.nil? || scale.empty?
trans << "-crop" << %["#{crop}"] << "+repage" if crop
trans
end
end
end
I added the following line to crop the images after paperclip has converted them
# Cropping it with vertical and horizontal aligning
`#{Rails.root}/public/scripts/squareup.sh -c trans -s #{#width} #{File.expand_path(src.path)} #{File.expand_path(dst.path)}`
If somebody gets a better idea, please give it to me :)
Thanks