Streamlining the Process of Product Image Creation

Whether you've just launched a Shopify site for your latest product, or you're a multibillion dollar retailer with expansive design teams, you probably have significant room to improve and make more efficient the process of how raw photographs are transformed into compelling images on your website’s product pages.

You'll want to create product shots that are:

  • Focused on the product, eliminating any distracting surrounding images
  • Standardized to a width and height for your site
  • Trimmed and padded to take up as much of the space as they can but not touching the edges
  • Colored with a background that matches your brand
  • Optimized and compressed for speedy delivery
  • Flexible, so they an adjust to fit a site redesign or an expansion to other marketplaces
  • Stored in a friendly way so you can avoid having to manage and maintain images across multiple platforms

The process is fairly straightforward and can be customized to fit whatever your needs might be:

  • Upload the original, high-resolution photo to Cloudinary in any image format
  • Cut the product from the background
  • Scale the image to a standard size and add in padding as needed
  • Optimize quality and format - and you're done!

Let's start with an image (click to view the original):

Ruby:
cl_image_tag("wood_chair_orig.jpg")
PHP:
cl_image_tag("wood_chair_orig.jpg")
Python:
CloudinaryImage("wood_chair_orig.jpg").image()
Node.js:
cloudinary.image("wood_chair_orig.jpg")
Java:
cloudinary.url().imageTag("wood_chair_orig.jpg");
JS:
cloudinary.imageTag('wood_chair_orig.jpg').toHtml();
jQuery:
$.cloudinary.image("wood_chair_orig.jpg")
React:
<Image publicId="wood_chair_orig.jpg" >

</Image>
Angular:
<cl-image public-id="wood_chair_orig.jpg" >

</cl-image>
.Net:
cloudinary.Api.UrlImgUp.BuildImageTag("wood_chair_orig.jpg")
Android:
MediaManager.get().url().generate("wood_chair_orig.jpg");
iOS:
imageView.cldSetImage(cloudinary.createUrl().generate("wood_chair_orig.jpg")!, cloudinary: cloudinary)
Photo with Background Removed

First, when uploading, send Cloudinary both the original, as well as a second version that uses the add-on effect of Remove-The-Background, which is powered by the folks over at Pixelz. Pixelz is fast, fairly economical (it includes a number of free images each month), and it produces great work. In a few hours, you'll have the second asset replaced in the account with the altered version (as a PNG typically).

Ruby:
cl_image_tag("wood_chair.png")
PHP:
cl_image_tag("wood_chair.png")
Python:
CloudinaryImage("wood_chair.png").image()
Node.js:
cloudinary.image("wood_chair.png")
Java:
cloudinary.url().imageTag("wood_chair.png");
JS:
cloudinary.imageTag('wood_chair.png').toHtml();
jQuery:
$.cloudinary.image("wood_chair.png")
React:
<Image publicId="wood_chair.png" >

</Image>
Angular:
<cl-image public-id="wood_chair.png" >

</cl-image>
.Net:
cloudinary.Api.UrlImgUp.BuildImageTag("wood_chair.png")
Android:
MediaManager.get().url().generate("wood_chair.png");
iOS:
imageView.cldSetImage(cloudinary.createUrl().generate("wood_chair.png")!, cloudinary: cloudinary)
Photo with Background Removed

Next, we'll get the product image into a set of standard dimensions. In this case, let's say that we want all of our images to be 500x500 squares. Here are the next steps:

  • Dynamic Variables: Set the $imgwidth and $imgheight variables in the beginning of the string for easy reference
  • Trim Effect: Cut out the excess padding that was left from the background removal so that the product touches each edge of the image
  • Conditional Resizing: Based on the height and width variables that were defined, reduce the border width
  • Border: Add in a border around the product to offset from the edge of the image
  • Padding: Perform a crop and resize to the preferred width and height dimensions of the final product (500 x 500)
  • Background Color: Select the color for the background of the entire image (in this example, eggshell white)
  • Optimize the final image for delivery with auto quality and auto formatting

Ruby:
cl_image_tag("wood_chair.png", :variables=>[["$imgwidth", "500"], ["$imgheight", "500"], ["$border", "10"]], :transformation=>[
  {:effect=>"trim"},
  {:if=>"w_gte_h", :width=>"$imgwidth - $border * 2", :crop=>"scale"},
  {:if=>"else", :height=>"$imgheight - $border * 2", :crop=>"scale"},
  {:border=>"10px_solid_rgb:ffffff00"},
  {:width=>"$imgwidth", :height=>"$imgheight", :background=>"#f0ead6", :crop=>"pad"},
  {:quality=>"auto", :fetch_format=>:auto}
  ])
PHP:
cl_image_tag("wood_chair.png", array("variables"=>array("$imgwidth"=>"500", "$imgheight"=>"500", "$border"=>"10"), "transformation"=>array(
  array("effect"=>"trim"),
  array("if"=>"w_gte_h", "width"=>"$imgwidth - $border * 2", "crop"=>"scale"),
  array("if"=>"else", "height"=>"$imgheight - $border * 2", "crop"=>"scale"),
  array("border"=>"10px_solid_rgb:ffffff00"),
  array("width"=>"$imgwidth", "height"=>"$imgheight", "background"=>"#f0ead6", "crop"=>"pad"),
  array("quality"=>"auto", "fetch_format"=>"auto")
  )))
Python:
CloudinaryImage("wood_chair.png").image(variables={"$imgwidth": "500", "$imgheight": "500", "$border": "10"}, transformation=[
  {'effect': "trim"},
  {'if': "w_gte_h", 'width': "$imgwidth - $border * 2", 'crop': "scale"},
  {'if': "else", 'height': "$imgheight - $border * 2", 'crop': "scale"},
  {'border': "10px_solid_rgb:ffffff00"},
  {'width': "$imgwidth", 'height': "$imgheight", 'background': "#f0ead6", 'crop': "pad"},
  {'quality': "auto", 'fetch_format': "auto"}
  ])
Node.js:
cloudinary.image("wood_chair.png", {variables: [["$imgwidth", "500"], ["$imgheight", "500"], ["$border", "10"]], transformation: [
  {effect: "trim"},
  {if: "w_gte_h", width: "$imgwidth - $border * 2", crop: "scale"},
  {if: "else", height: "$imgheight - $border * 2", crop: "scale"},
  {border: "10px_solid_rgb:ffffff00"},
  {width: "$imgwidth", height: "$imgheight", background: "#f0ead6", crop: "pad"},
  {quality: "auto", fetch_format: "auto"}
  ]})
Java:
cloudinary.url().transformation(new Transformation()
.variables(variable("$imgwidth","500"),variable("$imgheight","500"),variable("$border","10")).chain()
  .effect("trim").chain()
  .if("w_gte_h").width("$imgwidth - $border * 2").crop("scale").chain()
  .if("else").height("$imgheight - $border * 2").crop("scale").chain()
  .border("10px_solid_rgb:ffffff00").chain()
  .width("$imgwidth").height("$imgheight").background("#f0ead6").crop("pad").chain()
  .quality("auto").fetchFormat("auto")).imageTag("wood_chair.png");
JS:
cloudinary.imageTag('wood_chair.png', {variables: [["$imgwidth", "500"], ["$imgheight", "500"], ["$border", "10"]], transformation: [
  {effect: "trim"},
  {if: "w_gte_h", width: "$imgwidth - $border * 2", crop: "scale"},
  {if: "else", height: "$imgheight - $border * 2", crop: "scale"},
  {border: "10px_solid_rgb:ffffff00"},
  {width: "$imgwidth", height: "$imgheight", background: "#f0ead6", crop: "pad"},
  {quality: "auto", fetchFormat: "auto"}
  ]}).toHtml();
jQuery:
$.cloudinary.image("wood_chair.png", {variables: [["$imgwidth", "500"], ["$imgheight", "500"], ["$border", "10"]], transformation: [
  {effect: "trim"},
  {if: "w_gte_h", width: "$imgwidth - $border * 2", crop: "scale"},
  {if: "else", height: "$imgheight - $border * 2", crop: "scale"},
  {border: "10px_solid_rgb:ffffff00"},
  {width: "$imgwidth", height: "$imgheight", background: "#f0ead6", crop: "pad"},
  {quality: "auto", fetch_format: "auto"}
  ]})
React:
<Image publicId="wood_chair.png" >
  <Transformation effect="trim" />
  <Transformation if="w_gte_h" width="$imgwidth - $border * 2" crop="scale" />
  <Transformation if="else" height="$imgheight - $border * 2" crop="scale" />
  <Transformation border="10px_solid_rgb:ffffff00" />
  <Transformation width="$imgwidth" height="$imgheight" background="#f0ead6" crop="pad" />
  <Transformation quality="auto" fetchFormat="auto" />
</Image>
Angular:
<cl-image public-id="wood_chair.png" >
  <cl-transformation effect="trim">
  </cl-transformation>
  <cl-transformation if="w_gte_h" width="$imgwidth - $border * 2" crop="scale">
  </cl-transformation>
  <cl-transformation if="else" height="$imgheight - $border * 2" crop="scale">
  </cl-transformation>
  <cl-transformation border="10px_solid_rgb:ffffff00">
  </cl-transformation>
  <cl-transformation width="$imgwidth" height="$imgheight" background="#f0ead6" crop="pad">
  </cl-transformation>
  <cl-transformation quality="auto" fetch-format="auto">
  </cl-transformation>
</cl-image>
.Net:
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Effect("trim").Chain()
  .If("w_gte_h").Width("$imgwidth - $border * 2").Crop("scale").Chain()
  .If("else").Height("$imgheight - $border * 2").Crop("scale").Chain()
  .Border("10px_solid_rgb:ffffff00").Chain()
  .Width("$imgwidth").Height("$imgheight").Background("#f0ead6").Crop("pad").Chain()
  .Quality("auto").FetchFormat("auto")).BuildImageTag("wood_chair.png")
Android:
MediaManager.get().url().transformation(new Transformation()
.variables(variable("$imgwidth","500"),variable("$imgheight","500"),variable("$border","10")).chain()
  .effect("trim").chain()
  .if("w_gte_h").width("$imgwidth - $border * 2").crop("scale").chain()
  .if("else").height("$imgheight - $border * 2").crop("scale").chain()
  .border("10px_solid_rgb:ffffff00").chain()
  .width("$imgwidth").height("$imgheight").background("#f0ead6").crop("pad").chain()
  .quality("auto").fetchFormat("auto")).generate("wood_chair.png");
iOS:
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setEffect("trim").chain()
  .setIf("w_gte_h").setWidth("$imgwidth - $border * 2").setCrop("scale").chain()
  .setIf("else").setHeight("$imgheight - $border * 2").setCrop("scale").chain()
  .setBorder("10px_solid_rgb:ffffff00").chain()
  .setWidth("$imgwidth").setHeight("$imgheight").setBackground("#f0ead6").setCrop("pad").chain()
  .setQuality("auto").setFetchFormat("auto")).generate("wood_chair.png")!, cloudinary: cloudinary)
Processed Product Photo

And you're done! With Cloudinary, you now can manage your original and altered digital assets all in one place. You also can quickly make other versions of the processed photo as needed. For example, you can:

  • Change the background to white for listing on Amazon
  • Include various sizes of images for your product pages - thumbnails, standard shots, and zoomed-in views
  • Use a different aspect ratio if/when you redesign the website
  • Replace the photo with an updated shot if your product line evolves over time
by Josh Slivken