Withgoods
BUILDING A PRINT-ON-DEMAND WEBSITE
01 Image generator
CHALLENGE
Generating life-like product images is our core feature both for the artists and the customers. If something feels wrong (i.e. too pixelated, too flat, bad lightning) the illusion is broken. To advocate high quality, induce sales and promote our brand it is critical that we generate the best images we can.
SOLUTION
To create a product image we need 4 different things. The artwork (e.g. some characters on a beach), the product image (e.g. a mug cup), a clipping mask (e.g. a mug-shaped rectangle) and an overlay (e.g. some light beams).
Image Generation can be resumed in 6 steps: 1) Editing Using our custom photoshop-like editor, you can edit your artwork inside a live preview of the product. You can move, scale and rotate both images and texts until it suits you. When done, the result is uploaded as an image and the generation starts. 2) Cropping Here we crop the part of the artwork we need and place it according to the product template. For example, the left part of the template will be the front of the mug; the right part being the back. 3) Mask Clipping By applying a clipping mask we obtain an exact shape with all its irregularities. For a clock the mask will be a circle. 4) Curving Here we displace the pixels according to a predefined curve (i.e. Bezier curve). This will create the illusion of a round object and give it a 3D effect. 5) Merging We merge the transformed artwork image on top of the product item image to create our custom product image. 6) Overlay Finally, we merge the overlay image on top. Overlay includes reflection and light rays to create the illusion of a reflective texture, thus reinforcing the 3D and realistic effect.
Considering the artist picks 20 items and each item needs 3 images (e.g. left, front and right view), we need to generate 60 images at once. Image generation is a heavy process; running it all at once would overload and slow down our main server.
This feature is independent from our main server and is infinitely scalable
For that reason, the image generation process has been moved from our main server to a serverless function (i.e. AWS Lambda). When an image generation is requested, a new function is launched, creates the image, saves it and is terminated. When 60 are requested, 60 functions will run in parallel. This feature is independent from our main server and is infinitely scalable.
RESULT
The end result is high quality images where the artwork perfectly matches the object shape and orientation. The reflection overlay gives it a neat finish reinforcing the realistic and 3D effect. The generation process can easily be configured from the admin page. Changing the mask, increasing the curvature or updating the overlay can be done in a few clicks. Changes can be applied to new items as well as old items. Images can be regenerated at any time.
02 AI-powered search engine
CHALLENGE
On Withgoods, the products are created by the users. For each artwork uploaded, dozens of new products are created. As the number of items quickly increased, it became necessary to provide an effective way to search. Since we are dealing with images, a simple text search wouldn't be enough; we needed a better way to classify and sort artworks. We wanted to keep the upload process as quick and seamless as possible for both users and admins. No additional actions such as labeling or reviewing should be required.
SOLUTION
The idea is to take advantage of AI with the Google Vision API. The Vision API takes an image as input and produces metadata such as labels and dominant colors.
From the generated metadata we extract the labels; each label comes with a confidence score. We only get the labels with a high score, which usually gives us between 3 to 5 labels. The returned labels being in English only, we then use Google Cloud Translation API to obtain their Korean translation. For colors, we get a set of dominant colors which comes with a score (i.e. importance of this color in the image) and a percentage (i.e. how much of this image is taken by this color). We use these two metrics to extract only the most relevant colors, usually 1 to 3. These colors will then be matched against a custom palette, the same palette that will be used as a filter when searching.
It's a completely automatic, silent and scalable solution
This process is run in the background so the user experience is not affected in any way. When an artwork is uploaded, a serverless function (i.e. AWS Lambda) will trigger the necessary calls to the Google Cloud services. The function will then parse and persist its metadata in our database. It's a completely automatic, silent and scalable solution.
RESULT
The search page is the most visited page (i.e. after our landing page). It holds the longest session times and allows our users to effectively find what they are looking for. If you are looking for an illustration of a black cat, you are able to find just that.
03 On-the-fly image optimizer
CHALLENGE
In the earliest versions of Withgoods, users could upload images up to 5mb in size. These images being served in their original format, it seriously impacted our pages performance. Additionally, the same image is needed alternatively as a small thumbnail, a medium-sized product image or a high quality gallery image. Our solution has to be flexible. Finally, as our artists provide their original images, we must protect their intellectual property.
SOLUTION
Our original images are stored in AWS S3 (i.e. file storage service). First, we set up AWS CloudFront (i.e. content delivery network) to deliver images faster through AWS globally-distributed network. Then, we take advantage of CloudFront Lambda@Edge feature. It allows us to run serverless code at certain steps of the content distribution. The objective is to request the image with the needed optimizations, apply these changes, then save and cache the result for future use.
During the first step and before hitting the cache (cf. 1 in schema), we validate and parse the request looking for 3 possible parameters. The first one is the desired dimensions and is the only mandatory one. Its format is WIDTHxHEIGHT (e.g. 500x500). The second one is quality. Here we accept the values “full” (i.e. original quality), “fine” (i.e. lowest quality settings before artifacts start to appear), and “low”. The third and last parameter is the watermark. Here we can pick from a set of watermarks to apply (e.g. logo or grid). From the combination of these we generate a unique URI to store and retrieve the generated image.
The next time this URI is requested, the optimized image will be instantly returned from CloudFront cache
After completing the first step, we ask CloudFront if the URI exists. If it does, the optimized image is immediately returned. If it doesn't, we ask for the original image directly from S3. When the file is returned from S3 but before it is returned to the client (cf. 2 in schema) we intercept it and will apply all the requested optimizations. Using an image processing library, we resize to the desired dimensions, format to the new quality settings and if needed, apply a watermark. We both save the optimized image in S3 and send it back. CloudFront will cache it and return it to the client. The next time this URI is requested, the optimized image will be instantly returned from CloudFront cache.
RESULT
We can now optimize and protect our images on the fly. Implementing this solution drastically improved page loading speed and reduced data usage. We were able to increase the upload limit from 5 to 20mb for better raw image quality. Reducing the image size, also meant reducing the transfer costs, thus reducing the bill. Now whenever our UI changes and requires new settings, it only takes one run to generate the new optimized images and will be done in an automatic and effortless way.