Cloudinary Blog
Learn More

Archive for August 2012

How to quickly build a stock photo site using Cloudinary

Aug 30, 2012 by Tal Lev-Ami
Different web applications have very different requirements when images are involved. A dating website will focus its image-related attention on normalizing and delivering his user uploaded snapshots. A pinterest style service is focused on retrieving external images from around the web and fitting them to its cool layout. An eCommerce website is focused on the effective delivery of the many product thumbnails it depicts.
 
While every website has different image related needs, they all share many commonalities. At Cloudinary we strive to coalesce all of our customers' image requirements into a single coherent image pipeline management service.
 
In the past several months we were repeatedly asked about private images and strict transformations. These two features are now available through Cloudinary, and what better way to tell you about them then showing you how these work in a real-world use-case - building a stock photo site.
 

Stock Photo Service - Requirements

So what does building a stock photo service entails?
 
Our photos website’s content manager will want to upload the original hi-resolution images to the cloud for safe storage. These are our most prized assets and will need to be protected from prying eyes (and clicks). We will want to publicly display smaller, low resolution thumbnails of our photos for potential buyers to browse. We'll also want to add watermarks to all of our images to prevent copying, and deliver these many images through a fast CDN for quick browsing. Finally, after a purchase was made, we'll want to allow our buyer (and only him) access to his purchased hi-resolution photo.
 
If you are familiar with Cloudinary, you already know that we make it quite simple to upload images to the cloud, generate thumbnails, add watermarks and deliver the resulting images through a fast CDN. Today we wanted to introduce our latest two features - uploading private, authenticated images and strict transformations.
 
To make this post shorter, most of the examples below are for Ruby-on-Rails. The same can be easily accomplished with any one of our client libraries, or by directly using our URL-based APIs.
 

Uploading Private Images to the Cloud

When uploading images to Cloudinary, both the original images and their transformed versions are publicly available through a CDN. Our default randomly generated public IDs will prevent users from guessing your URLs.
 
This is all very nice for the majority of websites out there, but simply won't do for our stock photo site. Here, we'll want a far more secured approach, and this is where private uploads comes in.
 
Starting today, you can upload private images to Cloudinary. Simply set the type parameter to 'private' (instead of the default 'upload' type). For example, the following Ruby code uploads a private image to Cloudinary:
Cloudinary::Uploader.upload("sheep.jpg", :public_id => "sheep", :type => :private)
 
Same in PHP, Python and Node.js:
\Cloudinary\Uploader::upload("sheep.jpg", "public_id" => "sheep", "type" => "private")
cloudinary.uploader.upload("sheep.jpg", public_id = "sheep", type = "private")
cloudinary.uploader.upload("sheep.jpg", function(result) { }, 
                           {public_id: 'sheep', type: "private"})
If you use CarrierWave in your Ruby project, simply add 'make_private' to your uploader class. In the example below we also request to eagerly generate a 164 by 164 thumbnail on upload, and store it in JPG format with 80% quality:
class PictureUploader < CarrierWave::Uploader::Base  
    include Cloudinary::CarrierWave  
    make_private
    eager

    version :medium do    
      process :resize_to_fill => [164, 164, 'North']
      process :convert => 'jpg'
      cloudinary_transformation :quality => 80
    end
  end
Trying to publicly access the uploaded image is not possible:
 

Strict transformations

One of Cloudinary's more powerful features is the ability to dynamically transform images on-the-fly. However, in some cases, like our stock photo site example, you might prefer to prevent your users from accessing just any type of image transformation. You want to strictly define the transformations you allow.

Starting today, you can switch your account to a strict transformations mode by enabling the new "Strict Transformations" setting in your Cloudinary management console's settings page:

When strict transformations are enabled, users can publicly access only images created through named transformations or dynamic transformations that you personally marked as allowed. In addition, incoming or eager transformations generated using an authenticated request to our API, are also allowed.

To mark a transformation as allowed or disallowed, head to the "Transformations" section of the Management Console. Near each transformation, you’ll find a green / red icon. Click it to allow or disallow the transformation. You can also pre-allow dynamic transformations when Strict Transformations are still disabled - can be useful when you're in development mode.

 

Trying to generate and access an allowed transformation will work fine:

http://res.cloudinary.com/private-demo/image/private/w_300,h_200,c_fill,r_20/sheep.jpg

 

Trying to access any other transformation, either disallowed or non-existing, will simply fail. As you can see below, you can always check the X-Cld-Error response header for finding out the reason of non-delivered images.

http://res.cloudinary.com/private-demo/image/private/c_fill,h_200,w_320/sheep.jpg

http://res.cloudinary.com/private-demo/image/private/w_1.0,r_20/sheep.jpg

Status Code: 401 Unauthorized
X-Cld-Error: Transformation w_1.0,r_20 is not allowed

Back to our stock photo site - we can't just allow anyone to dynamically create hi-res transformations of our originals, can we? We will be better off allowing only low resolution transformations that add a watermark to all images:

.../image/private/w_200,h_150,c_fill/l_watermark,w_200,h_150/sheep.jpg

 

Private download URLs

Privately uploading images together with strict transformations allow safe, cloud-based storage for images that are inaccessible to your users, side-by-side with publicly available scaled down versions of these same images.

This is a great start for our stock photo site, but one crucial feature still remains. Assume that a buyer purchases a photo, how can we deliver the original image to him (and only to him) while our originals are inaccessible to anyone but us?

For that, you (and only you) can generate a unique, signed URL, based on your account's API Key and Secret. Anyone you share this URL with will have temporary access to download the original, high-resolution image. This URL will automatically expire after one hour.

For example, generating such a URL in Rails is done by simply calling the cl_private_download_url view helper method (or Cloudinary::Utils.private_download_url from your model or controller):

<%= link_to("Download", cl_private_download_url("sheep", :jpg)) %>

This will generate a link similar to the following (this one has already expired...):

https://api.cloudinary.com/v1_1/private-demo/image/download?api_key=824698761754661&format=jpg&public_id=sheep&signature=d994c2b972c30d84d33fde684aa377fc17878be6&timestamp=1346076992

This method delivers the original images through a secure authenticated API request and not through the faster CDN. Therefore, this method is most appropriate when the original images are not accessed very frequently.

Note - We've recently added a more advanced solution that allows delivering private (authenticated) images to your users through a CDN by generating a signed URL on your side using your own private key. This alternative solution utilizes Amazon CloudFront signed URLs. It is already available for our Advanced, and higher plans. Please contact us if this interests you.

 

Summary

Uploading private and authenticated content were features frequently requested by many of Cloudinary's customers. Supporting these now, opens a wide range of new image management streamlining use-cases that Cloudinary can cover, such as our imaginary new stock photo site.

Strict transformations and private uploading are available to all of our plans, free and paid. As mentioned above, authenticated image delivery through a CDN is available for the Advanced plan or higher (contact us for details).

The stock photo example is a very cool use case. There are plenty of other use cases that these features are relevant for. Do you have such an interesting use-case you can share? Tell us about it and we will be happy to share it with our community.

Direct image uploads from the browser to the cloud with jQuery

Aug 28, 2012 by Nadav Soferman
Where do you host all of your website's assets - still on your own web servers? 
 
In modern websites, images alone contribute to more than 50% of a website’s load time, and recent studies show that even a 1 second delay in a page's load speed can result in more than 5% loss in conversion. The impact of correctly delivering your website's images to your viewers is staggering. Luckily, Cloudinary offers a simple way to offload your website's images to the cloud, automatically transform them according to your needs and deliver them optimized through a fast CDN employing industry best practices.
 
In recent posts we've covered how to simply move your website's assets, either static or dynamic to Cloudinary. In this post, we wanted to detail how you can upload photos to Cloudinary directly from your users' browsers, without going through your own servers in the process. Below you will find a general explanation of our direct uploading solution, detailed integration examples and advanced tips.
 

Uploading images directly to the cloud

The common way of uploading images from your web application to the cloud involves a form in your application that uploads an image to your server that in turn uploads the same image to the cloud. 
 
While this approach works, you might want to consider a more direct approach - delivering images directly from your users' browser to the cloud without going through your intermediary server.
 
This approach is faster as it eliminates redundant uploads, it reduces load on your servers and it bypasses common limitations of shared web hosting (e.g. maximum size of allowed uploaded data, maximum number of concurrent requests to your application, etc.). In addition, the approach we detail below is simple to integrate with modern web browsers and includes many modern uploading UI elements such as drag & drop support, showing uploading progress, multiple file uploads support and more.
 

Direct uploading to Cloudinary

Cloudinary's service supports direct uploading to the cloud out-of-the-box.

The process is based on Cloudinary's jQuery plugin which in turn includes upload support based on jQuery File Upload Plugin, one of todays leading file upload solutions. Direct uploading is done using modern HTML5 cross origin resource sharing (CORS) and gracefully degrades to a seamless iframe based solution for older browsers.

To get the Cloudinary upload solution working, we will go through the following steps (detailed more granularly later on):

  • Generate an authentication signature on your server side, in your web development framework of choice.
  • Include Cloudinary's jQuery plugin.
  • Add Cloudinary’s special attributes to your file input tag in your HTML image upload form.

That’s basically it. Your visitors will now be able to upload images using drag-and-drop support (or regular browsing) and images will be uploaded directly to Cloudinary with a progress bar support.

When the upload is complete, your image's Cloudinary public ID will be added to your original form and submitted to your server. Use this public ID when you want to access the uploaded image in the future, either in its original form or after using Cloudinary's on-demand image transformations. You can also get the plugin to call a Javascript callback routine when uploading to Cloudinary is completed.

With our client libraries, setting up direct image uploads to Cloudinary is even simpler. Below are integration instructions for Ruby on Rails, Python / Django and other web dev platforms.

 

Ruby on Rails Integration

Setting up direct uploads from your Rails application is quite simple. Here is a detailed explanation: 

1. Make sure you use the latest version of Cloudinary’s Ruby GEM.

2. Place cloudinary_cors.html in the public folder of your Rails app. The file is available in the vendor/assets/html folder of the Ruby GEM.

3. Make sure to include the relevant jQuery plugins in your view. They are located in the vendor/assets/javascripts folder of the Ruby GEM.

<%= javascript_include_tag "jquery.ui.widget", "jquery.iframe-transport", 
                           "jquery.fileupload", "jquery.cloudinary" %>

Alternatively, If you use Asset Pipeline,  simply edit your application.js and add the following line:

//= require cloudinary 

4. Add the Cloudinary configuration parameters to your view:

<%= cloudinary_js_config %> 

5. Add cl_image_upload_tag to a form in your view. This tag adds a file input element that is already configured to use direct uploading. In this example, we also perform an incoming transformation (limit to 1000x1000) and add a custom class to the HTML element:

<%= form_tag(some_path, :method => :post) do  %>
  <%= cl_image_upload_tag(:image_id, :crop => :limit, :width => 1000, :height => 1000, 
                          :html => {:class => "image_upload"}) %>
    ...
<%= end %>

This is it if you use CarrierWave for managing your image uploads in your Rails application, together with Clodinary’s plugin for CarrierWave (recommended).

Another great option is to use the Attachinary GEM developed by Milovan Zogovic. Direct uploading to Cloudinary comes out of the box with Attachinary.

If you use uploading without CarrierWave or Attachinary, one last step is required - extracting the public ID and version of the uploaded image when the form is submitted to your controller:

  if @params[:image_id].present?
     preloaded = Cloudinary::PreloadedFile.new(params[:image_id])
     # Verify signature by calling preloaded.valid?
     @model.image_id = preloaded.identifier
  end

Having stored the image_id, you can now display a directly uploaded image in the same way your display any other Cloudinary hosted image:

<%= cl_image_tag(@model.image_id, :crop => :fill, :width => 120, :height => 80) %>

 

Python & Django Integration

Setting up direct uploads from your Django application is quite similar to the RoR approach. Here is a detailed explanation:

1. Make sure you use Cloudnary’s latest Python library.

2. In your Django template, load Cloudinary and include jQuery and all relevant jQuery plugins:

{% load cloudinary %}
{% load staticfiles %}
<script src="{% static "js/jquery.js" %}" type="text/javascript"></script>
{% cloudinary_includes %} 

3. Add a file uploading tag to your form:

<form action="/posts/save" method="post">
  {% csrf_token %}
  {{ form.image }}
  <input type="submit" value="Submit" />
</form> 

4. Edit your views.py and define the image form field as a CloudinaryJsFileField instance. This class does all the behind-the-scenes magic for you. In the example below, the dummy save action receives the uploaded image.

from django import forms
import cloudinary, cloudinary.uploader, cloudinary.forms

class UploadFileForm(forms.Form):
    image  = cloudinary.forms.CloudinaryJsFileField()

def save(request):
    form = UploadFileForm(request.POST)
    cloudinary.forms.cl_init_js_callbacks(form, request)
    if request.method == 'POST':
        if form.is_valid():
            image = form.cleaned_data['image']
            return HttpResponseRedirect(image.url())
    return render_to_response('posts/upload.html', 
                              RequestContext(request, {'form': form, 'post': p}))

 

Other development frameworks and advanced usage

In the examples above, we've shown detailed integration instructions based on Cloudinary’s Ruby and Python client libraries. The same integration concept can be used together with our PHP library using the cloudinary_js_config and cl_image_upload_tag methods.

We will soon enhance our documentation to include detailed instructions for direct Cloudinary uploads using all of our other client libraries.  

In the meantime, following are detailed instructions on how to use direct uploading in your development environment without our client libraries, using Cloudinary’s jQuery plugin directly.

1. Include jQuery and the following jQuery plugins in your HTML page:

jquery.js, jquery.ui.widget.js, jquery.iframe-transport.js, jquery.fileupload.js, jquery.cloudinary.js 

2. Define your account’s Cloudinary configuration. Note that only public parameters are included (secrets must not be included in public HTML pages or client-side Javascript code):

<script type="text/javascript">
   $.cloudinary.config({"api_key":"1234567890","cloud_name":"demo"});
</script> 

3. Add a file input field to your HTML form. 

  • Set the class name to 'cloudinary-fileupload' (alternatively, selection of input fields can be done programmatically). 
  • Set data-cloudinary-field to the name of the input field that should contain the upload reference.
  • Set data-form-data to be JSON representation of the upload API params. The mandatory fields are api_key, timestamp, signature and callback. Any additional incoming or eager transformation parameters can be specified.
    • The signature needs to be generated on the server-side for correct authentication.
    • The callback should point to a public URL of your web application that has the cloudinary_cors.html file. It is included in our jQuery plugin package and is required for iframe fallback upload.

For example:

<input name="file" type="file" 
       class="cloudinary-fileupload" data-cloudinary-field="image_upload" 
       data-form-data=" ... html-escaped JSON data ... " ></input>

The unescaped JSON content of data-form-data is:

{ "timestamp":  1345719094, 
  "callback": "https://www.example.com/cloudinary_cors.html",
  "signature": "7ac8c757e940d95f95495aa0f1cba89ef1a8aa7a", 
  "api_key": "1234567890" }

That's it. Image uploads by either browsing or drag-and-drop will head straight to the Cloudinary service. When done, the reference (public ID, version and signature) will be saved in the field you requested, for storing in your model at the server side. 

You can also listen to various events in your Javascript code. For example:

  • fileuploadstart - useful for showing a progress indicator when the upload starts.
  • fileuploadfail - listen to this event if you want to show an error message if an upload fails.
  • cloudinarydone - sent when upload completes. Following is a code example that displays a Cloudinary dynamically generated thumbnail of the previously uploaded image:
$('.cloudinary-fileupload').bind('cloudinarydone', function(e, data) {  $('.preview').html(
       $.cloudinary.image(data.result.public_id, 
           { format: data.result.format, version: data.result.version, 
             crop: 'scale', width: 200 }));    
       $('.image_public_id').val(data.result.public_id);    
  return true;
});

 

Fancy upload UI

Modern websites frequently use fancy upload widgets that include progress bars, live previews, multiple file uploads and more. The approach we’'e shown above can be easily customized and extended to feature all of these advanced capabilities. Together with Cloudinary's jQuery plugin, these great looking file upload widgets can upload your user's photos directly to Cloudinary, generate preview thumbnails on-the-fly and deliver the resulting photos from a fast CDN.

Direct uploading is a powerful feature that many of our readers requested. Try it out and tell us what you think?

If you have a cool code sample in any development framework with or without a fancy UI, share it with our community and we will give you a generous one year discount for any of Cloudinary’s paid plans.

Generating video thumbnails from YouTube and other video sites

Aug 08, 2012 by Nadav Soferman

Websites, blogs and web applications regularly embed video content from various video service providers such as YouTube and Vimeo. Videos are usually depicted using image thumbnails, tweaked to fit the graphics design of the website. When a video thumbnail is clicked, the actual video content starts playing.
 
In this post we wanted to explain how Cloudinary can help you to easily generate thumbnails from public videos. These thumbnails can be generated while applying any required image transformation in order to match your graphic design requirements.
   
 

Generating a Thumbnail from a YouTube Video

Let’s assume that we want to display the thumbnail of the following YouTube video:
 
This can be easily accomplished by adding the video ID to the URL. 'o-urnlaJpOA' in this example:


Cloudinary retrieves this image on the fly, caches it and deliver it through a fast CDN.
 
The example above made use of Cloudinary’s URL-based API. You can also accomplish the same functionality using any one of our client libraries, for example:
 
Ruby on Rails: 
<%= cl_image_tag("o-urnlaJpOA.jpg", :type => :youtube) %>
PHP: 
<?php echo cl_image_tag("o-urnlaJpOA.jpg", array("type" => "youtube")) ?>
Django: 
{% cloudinary "o-urnlaJpOA.jpg" type="youtube" %}
Node.js: 
cloudinary.image("o-urnlaJpOA.jpg", { type: "youtube" })
 

Supported Video Providers

In addition to YouTube, you can generate, transform and deliver thumbnails of videos from Hulu, Vimeo, Animoto and DailyMotion. Simply set the type parameter to youtube, hulu, vimeo, animoto or dailymotion.
 
For example, to embed a thumbnail of the following Vimeo video: http://vimeo.com/39482584
 
Simply add the Vimeo video URL or ID:
 

 

Applying Image Transformations on Video Thumbnails

Cloudinary makes it very easy to apply a custom transformation on video thumbnails. 
 
The following example generates a 200x110 thumbnail from a YouTube video while adding the olympic games logo as a watermark in the image’s south east corner.
 
 
 
Below is another example, this time generating a 200x120 thumbnail of a different YouTube video while rotating the image by 5 degrees.
 
 
 
Here’s the same example using our client libraries:
 
Ruby on Rails: 
<%= cl_image_tag("aNwnPElsJGE", :type => :youtube, :angle => 5, 
                 :transformation => { :width => 200, :height => 120, :crop => :fill }) %>
PHP: 
<?php echo cl_image_tag("aNwnPElsJGE", array("type" => "youtube", "angle => 5", "transformation" => array("width" => 200, "height" => 120, "crop" => "fill"))) ?>
Python: 
cloudinary.utils.cloudinary_url("aNwnPElsJGE", type="youtube", angle = 5, 
                          transformation = { width: 200, height: 120, crop: "fill" } )
Node.js: 
cloudinary.image("o-urnlaJpOA.jpg", { type: "youtube", angle: 5, 
                 transformation: { width: 200, height: 120, crop: "fill" }})
In this last example, we improve on George Clooney’s Vimeo thumbnail above by generating a 200x220 face detection based thumbnail. In addition, corners are rounded, format is converted to a transparent-background PNG and saturation is reduced by 70%
 

 

Additional Notes 

If you wish, you can also pass the full URLs of the videos instead of just their IDs. The following  example delivers a thumbnail of a YouTube video based on a full video URL.
 
 
 
Note - if the URL includes special characters like '?', they should escaped. If you use our client libraries, no escaping is required.
 

Summing it Up

Do you display video thumbnails in your website, app or blog? if so, you really need to give Cloudinary a spin. As you can see, Cloudinary makes it dead simple to generate thumbnails in any size with any effect, and deliver the resulting thumbnail from a fast CDN using smart caching.
 
Make sure you upgrade your Cloudinary client library to the latest version, try it out and tell us what you think?