Any method to generate a small thumbnail for a 3d model? - ruby-on-rails

To get this out of the way: I have little to no experience dealing with 3D aspects of web development. It's also worth noting that I'm relatively inexperienced with Ruby/Ruby on Rails. In my Ruby on Rails app, I want to add the ability for an administrator to upload a 3D Model to the site for others to view; For the most part, I've got this mostly covered, I just need to generate a thumbnail for the uploaded 3D model (Either an FBX or OBJ file to be specific) before the uploading process finishes. I'm currently using carrierwave to handle the uploading process.
My controller function where I'm uploading the file:
def createItem
#newItem = Item.new(params.permit(:title, :description, :price, :stock, :categoryId))
if (!params[:modelPath])
render :json => {"status": false, "message": "You need to upload something!"}
return
end
#itemUploader = ItemUploader.new
#uploadedItem
begin
#uploadedItem = #itemUploader.store!(params[:modelPath]) # This is all im doing in order to store the item; Don't know if I need to anything more advanced than this.
rescue => exception
render :json => {"status": false, "message": exception}
return;
end
#newFileName = #itemUploader.filename
# Probably where I want to put the thumbnail generation method.
if !#newItem.save
render :json => {"status": false, "message": #newItem.errors.objects.first.full_message}
return
end
if (params[:isLimited] == "on")
#newItem.limited = true
#newItem.save
end
#newItem.modelPath = #itemUploader
#newItem.save
render :json => {"status": "good", "item": #newItem}
end
So, as you can see, I'm just using the store function in order to place the 3D model into a temp folder; Is there a way for carrierwave to generate a small PNG image of the 3D model? Is it even possible for this to happen on Ruby/Ruby on Rails? I've searched this on google, and all I can see is methods for generating thumbnails for other images.
Is there any method I can use in order to accomplish this effect? Or am I going to have to use an outside source in order to generate thumbnails? If you need any more information for this, I'll be happy to give it! Thank you in all in advance.

Related

How do can I show image files from outside the public directory?

It's pretty trivial to use the image_tag method to serve an image in the public directory, but what about images that I don't want to be publicly accessible, images for admins only, maybe.
How should my controller and view look so that an image_tag method serves an image from root/private/images rather than root/public. Also, that would be completely secure, right? If I had private images, and wanted to serve them only to admins, a simple if statement to check if the user is an admin and then using an image_tag to serve them the private image from outside the public folder would be secure?
I'd be interested in how to do this without paperclip. (paperclip not even mentioned so it's not a duplicate)
Assuming the image is related to a model such as one with paperclip attached, you could do this. (And I'd really recommend this).
def show
#image = Image.find(params[:id])
published_image = #image.published_image
respond_to do |format|
format.all {
if published_image
send_file published_image.attached_image.path, :type=> published_image.attached_image_content_type
else
raise ActionController::RoutingError.new('Not Found')
end
}
end
end
Assuming you have another way to tell this, you could have all routes beginning with /admin/image route to a controller action, and then there call render file on the rest of the path. Example:
routes.rb
get 'admin/photo/*other', to: 'admin#photos'
admin.controller.rb
def photos
if current_user.admin?
render file: Rails.root.join("private","admin","images",request.path.gsub("/admin/photo/","")
else
render :file => "public/401.html", :status => :unauthorized
end
end
view
image_tag "/admin/photos/id.jpg"
This would in theory work, but it might be more complicated than i'm thinking
Images here would be hosted in public/admin/images, but linked to as /admin/photos/id
I'm not sure how you are handling authentication for admins but assuming you have a separate login.
Store your images as BLOB in MySQL.
Return the requested image files using send_data in rails controller with authentication
This link have an example

How to upload an image to S3 using paperclip gem

For the life of my I can't understand how the basic paperclip example works. There's only one line included in the controller, and that's
#user = User.create( params[:user] )
I simply don't understand how that's all that is needed to upload an image to s3. I've changed the example quite a bit because i wanted to use jquery file uploader rather than the default rails form helper, so I'm at the point where an image is being POSTed to my controller, but I can't figure out how I'm supposed to take the image from the params and assign it as an attachment. Here's what I'm seeing the logs:
Parameters: {"files"=>[#<ActionDispatch::Http::UploadedFile:0x132263b98 #tempfile=#<File:/var/folders/5d/6r3qnvmx0754lr5t13_y1vd80000gn/T/RackMultipart20120329-71039-1b1ewde-0>, #headers="Content-Disposition: form-data; name=\"files[]\"; filename=\"background.png\"\r\nContent-Type: image/png\r\n", #content_type="image/png", #original_filename="background.png">], "id"=>"385"}
My JS is very simple:
` $('#fileupload').fileupload({
dataType: 'json',
url: '/my_url',
done: function (e, data) {
console.log('done');
}
});`
What would be helpful for me to know is how I can strip the file data from the POSTed parameters given above and pass it to paperclip. I'm sure that I'll have to assign the attachment attribute a value of File.open(...), but I dont know what source of my file is.
I've spent a ridiculous amount of time trying to figure this out and I can't seem to get it. I've tried uploading directly to s3, but the chain of events was terribly confusing, so I want to get this simple pass-through example completed first. Thanks so much for any help you cna give!
You need a few more pieces and it will help if you can show the exact code you're using.
Paperclip can post to S3 by using:
http://rubydoc.info/gems/paperclip/Paperclip/Storage/S3
When your controller creates a User model, it is sending along all the params. This is called "mass assignment" (be sure to read about attr_accessible).
When your model receives the params, it uses the Paperclip AWS processor, which uploads it.
You need the AWS gem, a valid bucket on S3, and a config file.
Try this blog post and let us know if it helps you:
http://blog.trydionel.com/2009/11/08/using-paperclip-with-amazon-s3/
UPDATE 2013-04-03: Pleases see Chloe's comment below-- you may need an additional parameter, and the blog post may be outdated.
If you want to do it manually, approach it like this:
# In order to get contents of the POST request with the photo,
# you need to read contents of request
upload = params[:file].is_a(String)
file_name = upload ? params[:file] : params[:file].original_filename
extension = file_name.split('.').last
# We have to create a temp file which is going to be used by Paperclip for
# its upload
tmp_file = "#{Rails.root}/tmp/file.#{extension}"
file_id = 0
# Check if file with the name exists and generate unique path
while File.exists?(tmp_file) do
tmp_file_path = "#{Rails.root}/tmp/file#{file_id}.#{extension}"
id += 1
end
# Let's write the file from post request to unique location
File.open(tmp_file_path, 'wb') do |f|
if upload
f.write request.body.read
else
f.write params[:file].read
end
end
# Now that file is saved in temp location, we can use Paperclip to mimic one file
# upload
#photo = Photo.new :photo => File.open(tmp_file_path)
# We'll return javascript to say that the file is uploaded and put its thumbnail in
# HTML or whatever else you wanted to do with it
respond_to do |format|
if #photo.save
render :text => "Success"
else
render :text => #photo.errors
end
end
You can rewrite your create or whatever you use as the url to which you are POSTing the form.
This bit:
"files"=>[#<ActionDispatch::Http::UploadedFile:0x132263b98 #tempfile=# <File:/var/folders/5d/6r3qnvmx0754lr5t13_y1vd80000gn/T/RackMultipart20120329-71039-1b1ewde-0>
is the part (I think) that holds the file contents that are posted in the form.
In Rails, the User model will have a helper: has_attached_file
Passing the [:params] to the User.create method allows that helper to pick up the file contents, do any processing on them (eg resizing etc based on attributes supplied to the helper) and then push the image(s) to your storage (eg S3 or whatever - S3 credentials are passed to the helper).
Hopefully that explains the 'how does it do it?' question
re the jQuery bit.. not sure what the code should be there, but why not use the Rails form with :remote => true and handle the response in jquery?

Sending an image through JSON data

noobie here hope you guys don't mind! Im trying to query my user/id/pictures.json but all it returns are attributes cus i did a generic format.json {render :json => #photo.to_json()}. My question is how can i create and encapsulate the actual data from the images, so my client can turn that data in to an image? And also what do i need to create(attribute wise) besides the path of image(say you only had useless attributes eg: height content_type, description, thumbnail file_name)?
this is what im trying in my index.json.erb so far
}
<% #photos.each do |photo|%>
data: <%= StringIO.new(Base64.encode64(photo.public_filename(:large))) %>
<%end%>
}
i am getting back
{
data: #<StringIO:0x1058a6cd0>
}
which is not the IMGdata im looking for
looking for
Have a look at Data-URIs.
They essentially are Base64-encoded entities (documents) formatted as a URI
[{ "name":"red dot", "data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="}, ...]
[UPDATE]
You need to read the file and encode it as Base64 (you also need to strip the newlines away in rails 2.3.x)
data = ActiveSupport::Base64.encode64(File.read("/images/image1.png")).gsub("\n", '')
uri = "data:image/png;base64,#{data}"
I think you are using Ruby on Rails, aren't you?
Then there are some steps needed to download an image (e.g. a png):
Create a mime type
Go to config/initializers/mime_types.rb and insert Mime::Type.register "image/png", :png at the end.
Create an image
For example, you could use the gem Chunky_PNG to create an image, see at http://rubygems.org/gems/chunky_png and https://github.com/wvanbergen/chunky_png/wiki
Prepare your controller
You have to tell your controller, that it can accept pngs. Modify your controller the following way
class UsersController < ApplicationController
respond_to :json, :png
def show
# your own stuff
# ...
respond_with(response) do |format|
format.json
format.png do
send_data ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT), :type =>"image/png", :disposition => 'inline'
end
end
end
end
This will create a fully transparent image. If you want to draw something in this, look at the Chunky PNG docs.
It's up to the client how to render it really. This works for me, maybe worth a try.
render json: #thumbnail, type: :jpeg, content_type: 'image/jpeg'

Paperclip & Rails Api

I have a photo rails app using paperclip. My model called photo and the request parameter also photo.So when i am trying to upload via curl i use : curl -F "photo[photo]=#/pics/pic.jpg" http://something/photos.xml .
That's works fine! How can i change the photo[photo] parameter to "photo" or "media" or something else? How can i change the endpoint url? (ex. http//something/upload.xml)
thanx!
any help will be highly appreciated, :-)
What you could do is setup another controller and work with it. What paperclip does is just setup an extra "photo" attribute and methods, thus reusing Rails .new and .update_attributes own methods. That way, when you call /photos.xml with that info, what you are doing is just a regular post photo action, with the added benefit of setting up it's picture.
When you do Object.photo = YOUR_PHOTO, you are actually using Paperclip code.
So, you could work with something like:
class ApplicationController < ActiveController::Base
def upload
photo = Photo.new
photo.photo = params[:photo]
# ... extra code
photo.save
render :text => "Ok"
end
end
And add a route like:
map.upload "/upload(.:format)", :controller => "application", :action => "upload"
(or it's Rails3 equivalent if you are using it)
That way, when you do 'curl -F "photo=#/pics/pic.jpg" http://something/upload.xml', you will invoke the upload action and create a photo using the 'photo' parameter. The photo = params[:photo] will take the tempfile you've uploaded and continue with the usual paperclip tasks :)

How to save a rendered view as a static file?

My Rails 2.3 app generates a page in HTML/CSS or as a word doc. I'd like to save that html file to the filesystem as a static file (ie. filename.html or filename.doc). I plan to have a preview action w/ the fully rendered page and a 'save report' button. Our users will access those static files later. (I'll save the path to the db.)
Any suggestions for how to do this?
I'm as far as creating a file and saving it, but I'm not sure how to get my rendered view into it. Bonus points if anyone knows how to save it up to S3! Many thanks!
render_to_string is your friend. One you have it in a string, burn it to file in the usual way.
class FooController
def save_foo_to_disk
data = render_to_string( :action => :index )
File.open(file_path, "w"){|f| f << data }
flash[:notice] = "saved to #{file_path}"
end
end
As far as S3 goes, see the aws-s3 gem. It seem to do what you are after. Usage is a little like this.
AWS::S3::Base.establish_connection!(
:access_key_id => 'abc',
:secret_access_key => '123'
)
S3Object.store(file_name, data, 'bucket-name')
Have fun, and don't run with scissors.
Another way is adding an after_action to the controller, and in that action using response.body to access rendered content. In this way, your controller can respond to client as normal, save rendered content to database in meanwhile.

Resources