Search code examples
transloadit

Spinning circle with transloadit. Is it possible with watermark or image rotation?


I'm trying to achieve a spinning circle with artwork as a mask. From what I've seen there is no way to use a moving watermark or an automatic rotation of an image. Is it possible with transloadit?

The result should be a "vinyl" spinning.


Solution

  • This question is quite complex to answer, but it's very much do-able with Transloadit. I'll be using python to answer it primarily for OpenCV, but of course you can use a language that you prefer - I'll try and make it as language agnostic as possible. I used 4 different templates to get the result we want, as well as some local python magic to tie everything together - here goes.

    1. First we need to resize the image so it fits nicely onto the vinyl record.
    {
      "steps": {
        ":original": {
          "robot": "/upload/handle"
        },
        "resize": {
          "use": ":original",
          "robot": "/image/resize",
          "format": "png",
          "resize_strategy": "fillcrop",
          "width": 350,
          "height": 350,
          "imagemagick_stack": "v2.0.7"
        }
      }
    }
    
    1. Now, we want to mask this image using OpenCV and NumPy like so:
    # Mask the image
    # Reads the input image
    img = cv2.imread(img_path)
    # Creates a mask with the same size as the image
    mask = np.zeros(img.shape, dtype=np.uint8)
    # Creates a white circle in the centre
    mask = cv2.circle(mask, (175, 175), 175, (255, 255, 255), -1)
    # Makes a small whole in the centre of the mask
    mask = cv2.circle(mask, (175, 175), 20, (0, 0, 0), -1)
    result = cv2.bitwise_and(img, mask)
    

    This will take an image, and create a mask for it that should look like a donut.

    Mask

    Then, using a bitwise and operation between the image and the mask you end up with a cookie cutter of the original image

    After applying the mask

    1. Yet we still need to remove the black background - which is what we use this template for:
    {
      "steps": {
        ":original": {
          "robot": "/upload/handle"
        },
        "trimmed": {
          "use": ":original",
          "robot": "/image/resize",
          "alpha": "Activate",
          "type": "TrueColor",
          "transparent": "0,0,0",
          "imagemagick_stack": "v2.0.7"
        }
      }
    }
    

    This will just make all black pixels transparent.

    1. We can now use Transloadit's watermark feature to overlay this image onto our vinyl record
    {
      "steps": {
        ":original": {
          "robot": "/upload/handle"
        },
        "watermark": {
          "use": ":original",
          "robot": "/image/resize",
          "watermark_size": "33%",
          "watermark_position": "center",
          "imagemagick_stack": "v2.0.7"
        }
      }
    }
    
    1. Now, all that is left is to make it spin. What we can do is create say 60 frames, and have the image rotate, then using the /video/merge robot - to stitch it all together into a seamless GIF.
    {
      "steps": {
        ":original": {
          "robot": "/upload/handle"
        },
        "rotate_image": {
          "use": ":original",
          "robot": "/image/resize",
          "rotation": "${file.basename}",
          "resize_strategy": "crop",
          "imagemagick_stack": "v2.0.7"
        },
        "animated": {
          "robot": "/video/merge",
          "use": {
            "steps": [
              {
                "name": "rotate_image",
                "as": "image"
              }
            ],
            "bundle_steps": true
          },
          "result": true,
          "ffmpeg_stack": "v4.3.1",
          "ffmpeg": {
            "f": "gif",
            "pix_fmt": "rgb24"
          }
        }
      }
    }
    

    Here I use the image's name to determine how many degrees to rotate it by - so when I'm uploading the files to the robot I will name the image based on its index in an array using this python code:

    # Now we make a list of images that represent each frame
    no_of_frames = 60
    assembly = tl.new_assembly({'template_id': [SPINNING_VINYL_TEMPLATE_ID]})
    directory = 'Assets/Frames/{image}'.format(image=img_name)
    # Length of our animation in seconds
    length = 2
    
    for i in range(no_of_frames):
        if not os.path.exists(directory):
            os.mkdir(directory)
        # Creates an image based on the index in the animation
        # We pass this to the robot so it knows how many degrees to rotate the image by
        location = '{directory}/{index}.png'.format(directory=directory, index=round(i*360/no_of_frames))
        cv2.imwrite(location, finished_vinyl)
        assembly.add_file(open(location, 'rb'))
    

    This is my end result