Have Paperclip make raster thumbnails of vector images - ruby-on-rails

I'm working on a site that uses Paperclip to attach images to some records. Currently, all of the images are jpeg, and paperclip generates png thumbnails that appear in browser views.
We would like to add support for eps images as well. Without making any changes, uploading and downloading eps images already works, but the thumbnails are not generated. Paperclip does not log any errors, it just fails to generate a thumbnail.
has_attached_file :drawing, :styles => { :thumb => ["64x64#", :png] }, :convert_options => { :thumb => "-quality 75 -strip" }
validates_attachment :drawing
What needs to be added to generate thumbnails of eps files?

In my case it turned out to be a problem with the type spoofing detection. Paperclip seems to get confused when different sources of file type information disagree.
The solution in my case was to create file named config/initializers/paperclip.rb with this content:
Paperclip.options[:content_type_mappings] = {
eps: "application/octet-stream"
}
I also tried editing the model to add validates_attachment_content_type and validates_attachment_file_name, neither of which had any noticeable effect.
I would understand if Paperclip didn't trust that the attachment was an acceptable type and refused to attach it, I don't understand why it doesn't trust the type so it attaches the file but doesn't create the thumbnail.

Related

Rails: Paperclip produces different results for similar videos

I am using the Paperclip Gem to handle video uploads on my Rails app. I've followed the instructions in a few other stackoverflow questions and external tutorials to get video uploads working. However, currently there is a strange glitch with the system that I don't understand.
When uploading two different videos, the app will be able to show a thumbnail and no video for one upload, and no thumbnail but video for another one.
Both videos use the same codecs, are around the same length, but are a bit different in their dimensions & file size.
When I upload them, test1 has a thumbnail, but my browser will not load the video file. It exists in my file system but Chrome will not play it.
The opposite happens for test2. Its thumbnail in my file system is zero bytes, but the video loads fine in my browser.
Here are the paperclip upload parameters for my object:
has_attached_file :video, :styles => {
:medium => { :format => 'mp4' },
:thumb => { :geometry => "500x500#", :format => 'jpg', :time => 10 }
}, :processors => [:transcoder]
validates_attachment_presence :video
validates_attachment :video, content_type: { content_type: ["video/mp4", "video/mov", "video/wav", "video/wmv"] }
I've created a Github repo with an example app that reproduces the issue, at least on my system.
The issue is in: :time => 10 parameter
Change it on: :time => 1
This change means: create screenshot on 1st second instead of 10th second. Because the second movie has only 10 second length, during the first movie has 12 seconds length. Thus the first movie has screenshot, and second don't and uses previous one.
Wish it helped you!
I was able to play both files in multiple browsers without issue.
However, the reasons why test1.mp4 might not (seem) to work are:
test1.mp4 has the moov atom at the end of the file:
AtomicParsley test1.mp4 -T
Atom ftyp # 0 of size: 32, ends # 32
Atom free # 32 of size: 8, ends # 40
Atom mdat # 40 of size: 1310866, ends # 1310906
Atom moov # 1310906 of size: 9926, ends # 1320832
This means the browser must fully download the file before it can play it. If you're on a slow connection it might take a while and appear like it's not working.
test2.mp4 has the moov atom at the beginning of the file meaning it can be played back before the download finishes:
AtomicParsley test2.mp4 -T
Atom ftyp # 0 of size: 32, ends # 32
Atom moov # 32 of size: 7464, ends # 7496
You can move the moov atom to the beginning of the file using the ffmpeg movflags faststart option or with the qt-faststart tool.
It shouldn't be an issue if you're using your local file system, so see below.
test1.mp4 uses the Main H.264 profile while test2.mp4 uses the Constrained Baseline profile. This can be an issue on some mobile devices as the Baseline profile has the most support. However it shouldn't be an issue with newer devices.
You could try to re-encode it with the Baseline profile to see if this is the issue.
Please do follow this link https://github.com/thoughtbot/paperclip/wiki/Thumbnail-Generation
and i think validation for video can be done in this way:
validates_attachment :video, :presence => true
rather than doing with presence and again without it.
For image i followed :
validates_attachment :attachment, content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] }
Hope this will work for you :-)

Rails: Download images from S3, resize and upload back to S3

In my Rails 4 application I have large number of images stored on S3 using Paperclip. Image url looks like http://s3.amazonaws.com/bucketname/files/images/000/000/012/small/image.jpg?1366900621.
Given following attachment class:
How can I download images from S3 and store locally ?
Then how to resize that locally stored image
Upload resized image to another S3 bucket without Paperclip (at a path s3/newbucket/images/{:id}/{imagesize.jpg})
Attachment class:
class Image < ActiveRecord::Base
has_attached_file :file, styles: { thumbnail: '320x320', icon: '64x64', original: '1080x1080' }
validates_attachment :file, presence: true, content_type: { content_type: /\Aimage\/.*\Z/ }
end
The basic advice would be not to resize images on-the-fly as this may take a while and your users may experience a huge response times during this operation. In case you have some predefined set of styles it would be wise to generate them in advance and just return back when required.
Well, here is what you could do if there is no other option.
def download_from_s3 url_to_s3, filename
uri = URI(url_to_s3)
response = Net::HTTP.get_response(uri)
File.open(filename, 'wb'){|f| f.write(response.body)}
end
Here we basically downloaded an image located at a given URL and saved it as a file locally. Resizing may be done in a couple of different ways (it depends on whether you want to serve the downloaded file as a Paperclip attachment).
The most common approach here would be to use image-magick and its convert command-line script. Here is an example of resizing an image to width of 30:
convert -strip -geometry 30 -quality 100 -sharpen 1 '/photos/aws_images/000/000/015/original/index.jpg' '/photos/aws_images/000/000/015/original/S_30_WIDTH__q_100__index.jpg' 2>&1 > /dev/null
You can find documentation for convert here, it's suitable not only for image resizing, but also for converting between image formats, bluring, cropping and much more! Also you could be intrested in Attachment-on-the-Fly gem, which seems a little bit outdated, but has some insights of how to resize images using convert.
The last step is to upload resized image to some S3 bucket. I assume that you've already got aws-sdk gem and AWS::S3 instance (the docs can be found here).
def upload_to_s3 bucket_name, key, file
s3 = AWS::S3.new(:access_key_id => 'YOUR_ACCESS_KEY_ID', :secret_access_key => 'YOUR_SECRET_ACCESS_KEY')
bucket = s3.buckets[bucket_name]
obj = bucket.objects[key]
obj.write(File.open(file, 'rb'), :acl => :public_read)
end
So, here you obtain an AWS::S3 object to communicate with S3 server, provide your bucket name and desired key, and basically upload an image with an option to make it visible to everybody on the web. Note that there are lots of additional upload options (including file encryption, access permissions, metadata and much more).

Generate new style thumbnail based on existing style using Paperclip and aws-sdk

I have a Photo model that has 2 styles :original and :medium where :medium is a cropped version of the original. I would now like to add a :small style that's just a resized version of the :medium. For new images everything works: I just crop the original image twice, once for the :medium and once for the :small style. But I also have several thousand existing images that need to be reprocessed to have a :small thumb (all stored on AWS S3). Unfortunately, I can't just call .reprocess! :small since it will make small versions from the original, while I need small versions based on the cropped :medium version.
The medium versions have been cropped by users so I can't just reprocess the originals.
Is there an easy way to do this using Paperclip or do I have to write a script to pull the :medium version from S3, resize it locally and then ship it to the :small directory on S3?
UPDATE 1:
These are my styles
:original, { geometry: "1500x1500>", format: :jpg },
:medium, { geometry: "650x650#", processors: [:cropper], format: :jpg },
:small, { geometry: "262x262#", processors: [:cropper], format: :jpg }
Notice that I've already added the :small style, but I still need to generate :small thumbs for images that have been created before this addition.
UPDATE 2:
The way to do this it is probably using a rake task that would:
fetch a :medium image from S3 for each photo that was created before :small style has been added
resize it down to :small size
upload the resulting image to /some/path/to/small/image/ on S3
Just not sure where to start.
Looks like you could use a custom processor. In the past I've copied processors from paperclip and modified them to do what I need. For example if you take the thumbnail processor, modify it so that it crops your thumbnail and resizes it the way you want, and then save it as a custom processor (it should aotu-load if you put it in lib/paperclip).
Either way. Copy the file from https://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/thumbnail.rb
Edit the section:
def transformation_command
scale, crop = #current_geometry.transformation_to(#target_geometry, crop?)
trans = []
trans << "-coalesce" if animated?
trans << "-auto-orient" if auto_orient
trans << "-resize" << %["#{scale}"] unless scale.nil? || scale.empty?
trans << "-crop" << %["#{crop}"] << "+repage" if crop
trans << '-layers "optimize"' if animated?
trans
end
to crop the image before you resize it. My gess is that you'll have to swap the resize and crop commands, but I'm not sure. All paperclip does is run imagemagick commands so you might find some good documentation here: http://www.imagemagick.org/script/command-line-processing.php
Save this as a custom processor in the lib/paperclip/your_processor_name.rb, and make whatever style you need style like this:
:original, { geometry: "1500x1500>", format: :jpg },
:medium, { geometry: "650x650#", processors: [:your_processor_name], format: :jpg },
:small, { geometry: "262x262#", processors: [:your_processor_name], format: :jpg }
The bottom line is that you can only crop from an original, so if you need custom processing you have to build it. You'll have to play around with it, but this will get you on the right track.

How to use paperclip to upload files other than images ...like pdf,docs

I am using paperclip to upload resume in my applyforjobs.Its working fine,i mean i can get browse button to upload files.But when i show the view page its not showing the pdf file that i upload,instead its showing just the name of the file. I also checked that folder which gets generated by default and that folder contains the pdfs which i uploaded during create aaction,which means upload thing is working fine.but i am not able to show that pdf.
Following is the code in my applyforjob.rb model for paperclip attachment :
has_attached_file :resume,:styles => { :small => "150x150>" }
Following is the code of applyforjobs/form.html.haml for uploading file :
= f.label :resume, "Upload resume".html_safe
= f.file_field :resume
Following is the code of applyforjobs/show.html.haml for showing file :
= image_tag #appliedusers.resume.url(:small)
but its not showing that pdf file.What am i supposed to write to upload and show files like pdf or docs?
Since paperclip is a general purpose attachment uploading gem, as stated in it's Readme, it natively supports uploading files of any kind.
I suggest that you:
remove :styles => { :small => "150x150>" } parameter from the has_attached_file
write a paperclip callback which will generate a thumbnail image from pdf file
define a method in model, say resume_thumbnail, which will be returning a path to generated file
call the following in your view
= image_tag #appliedusers.resume_thumbnail
No wonder image_tag #appliedusers.resume.url(:small) doesn't work for you: paperclip knows nothing about PDFs. paperclip blindly sees PDF file as a common file, and thus unable to do any kind of processing applicable to images only.
# , After saving the pdf you need to create a image which convert pdf to image to show on browser
I did this like -
**self.save ##save pdf in paperclip
create_preview_image ##call this method
def create_preview_image
file_name = File.join(Rails.root, 'public', self.document.url.split('?')[0]) if self.document
return unless file_name.present?
pdf = Magick::ImageList.new(file_name)
return unless pdf.present?
png_file = Tempfile.new(["#{rand(9999).to_s}",'.png'])
pdf[0].write(png_file.path) do
self.quality = 100
end
self.preview = png_file
self.save
end**

Paperclip problem

I have the video upload applicaton. I am using thoughbot paperclip plugin for uploading video files and i convert the video files into "flv" format by using ffmpeg .
The problem is the users can also upload the "flv" video files, in this case the browser keeping of waiting, the bottom of the browser its shows "sending request to localhost:3000".
When i see the mongral log nothing happed, the server sits idle.
When i upload the other video file format its working fine .. i am not sure what is happening.
here is my model file coding :
has_attached_file :source,:styles => {:thumb => "137x85>" }
validates_attachment_content_type
:source,
:content_type => ['video/x-
msvideo','video/avi','video/quicktime','video/3gpp','video/x-ms-
wmv','video/mp4', 'flv-application/octet-stream','video/x-
flv','video/mpeg','video/mpeg4','video/x-la-asf','video/x-ms-asf'],
:message => "Only Video file at the moment"

Resources