DeepMedia logodeepmedia

Camera SDK

Version 0.8.5

Search

Choose platform

Other versions of this page

Watermarks

The Camera SDK provides extensive watermark APIs that you can use to add an image overlay to media files taken within your mobile app. Watermarking works:

  • on all devices
  • on pictures, snapshots and videos
  • with any image asset
⚠️

Watermarks are not added to the camera preview because that is trivial to do using the system's UI.

Configuration

To interact with the watermark APIs, you'll use the WatermarkManager class:

swift
let watermarks: WatermarkManager = cameraManager.watermarks
kotlin logokotlin
val watermarks: WatermarkManager = cameraManager.watermarks

Add and Remove

The WatermarkManager stores watermarks by their String key. You can define this key on your own and use it for both addition and removal of new watermarks:

swift
let watermark: Watermark = watermarks.add(id: "app_logo") // Later, to remove it, use one of the following: watermarks.remove(id: "app_logo") watermarks.remove(id: watermark.id)
kotlin logokotlin
val watermark: Watermark = watermarks.add(id = "app_logo") // Later, to remove it, use one of the following: watermarks.remove(id = "app_logo") watermarks.remove(id = watermark.id)

Targets

As soon as a watermark is added, it will appear on any picture, snapshot and video recording that will follow. You can however filter the watermark targets by passing a list of Watermark.Target to WatermarkManager.add().

For example, add(id = "logo", targets = [Watermark.Target.Video]) add(id: "logo", targets: [.video]) will configure the watermark so that it only appears on videos.

TargetDescription
Target.VideoTarget.videoShows this watermark on video recordings.
Target.PictureTarget.pictureShows this watermark on high quality pictures.
Target.SnapshotTarget.snapshotShows this watermark on snapshots.

Content

When adding new watermarks, a Watermark object is returned. It can be used to configure, among other things, the contents of the watermark.

swift
let watermark: Watermark = watermarks.add(id: "app_logo") try watermark.content(UIImage(named: "AppLogo"))
kotlin logokotlin
val watermark: Watermark = watermarks.add(id = "app_logo") watermark.content(R.raw.app_logo)

There are several possible sources for your watermark contents:

  • Flat colors: use content(red: Float, green: Float, blue: Float, alpha: Float)
  • Byte buffers: use content(Data, width: Int, height: Int, flags: [Flags]). The buffer should hold raw RGBA values as unsigned bytes (8 bits per channel)
  • UIKit images: use content(UIImage). For example, the image may be loaded from application assets using UIImage(named: "AssetName")
  • Flat colors: use content(red: Float, green: Float, blue: Float, alpha: Float)
  • Byte buffers: use content(ByteBuffer, width: Int, height: Int, flags: List<Flags>). The buffer should hold raw RGBA values as unsigned bytes (8 bits per channel)
  • Bitmaps: use content(Bitmap, recycle: Boolean). Passing true to the recycle flag ensures that Bitmap.recycle() will be called
  • Files and file descriptors: use content(File) or content(FileDescriptor)
  • Raw assets: use content(rawResourceId: Int). The asset should be placed in the res/raw folder and referenced as R.raw.asset_name.

Some of the APIs above accept a list of Watermark.Flags:

TargetDescription
Flags.PremultipliedFlags.premultipliedNotifies the rendering engine that the RGB channels were multiplied by the opacity.
Flags.FlipVerticallyFlags.flipVerticallyNotifies the rendering engine that the underlying data was loaded from the bottom up, so the image should be flipped vertically before display.

Size

To configure the size of a watermark, use the size(width: Float?, height: Float?) API. It accept optional values for width and height in the [0,1] range, where 1 the represents the full width (or height) of the destination surface.

swift
// Asset with 10% of the target's height, free width watermark.content(UIImage(named: "MyAsset")) watermark.size(width: nil, height: 0.1) // Full-screen red box, will completely cover the image watermark.content(red: 1, green: 0, blue: 0) watermark.size(width: 1, height: 1)
kotlin logokotlin
// Asset with 10% of the target's height, free width watermark.content(R.raw.my_asset) watermark.size(width = null, height = 0.1) // Full-screen red box, will completely cover the image watermark.content(red = 1F, green = 0F, blue = 0F) watermark.size(width = 1F, height = 1F)

Dimensions must be relative because watermarks are applied onto targets of different size. For example, a picture will likely have a higher resolution than snapshots. Here are all the possible combinations:

WidthHeightDistortedMeaning
SpecifiedNull / NilNoWatermark will fit the specified width. The height will be automatically computed based on the content's intrinsic dimensions to avoid distortion.
Null / NilSpecifiedNoWatermark will fit the specified height. The width will be automatically computed based on the content's intrinsic dimensions to avoid distortion.
Null / NilNull / NilNoWatermark will be sized according to its intrinsic size in pixels. This usage is discouraged since the watermark may look different on different targets.
SpecifiedSpecifiedYesEnforces both width and height. The resulting image, if the content has any intrinsic dimension (e.g. not a color), may appear distorted. This usage is required for color-based watermarks.

Position

To configure the position of a watermark, use the position(anchor: Point, offset: Point?) API.

  • anchor: x and y coordinates of a point in the [0,1] range, where (0,0) represents the top-left corner and (1,1) represents the bottom-left corner. These coordinates on the watermark image will be anchored to the same coordinates on the target surface. See the example below.
  • offset (optional): extra offset to be applied after anchoring, for example to give the watermark some padding from the target borders.
swift
watermark.position(anchor: .init(x: 0, y: 0)) // Top-left watermark.position(anchor: .init(x: 1, y: 1)) // Bottom-right watermark.position(anchor: .init(x: 0, y: 1)) // Bottom watermark.position(anchor: .init(x: 0.5, y: 0.5)) // Centered
kotlin logokotlin
watermark.position(anchor = Point(0F, 0F)) // Top-left watermark.position(anchor = Point(1F, 1F)) // Bottom-right watermark.position(anchor = Point(0F, 1F)) // Bottom watermark.position(anchor = Point(0.5F, 0.5F)) // Centered

Dimensions for both anchors and offsets must be relative because watermarks are applied onto targets of different size. For example, a picture will likely have a higher resolution than snapshots.

Advanced Usage

Dynamic Watermarks

In most cases, you will add a watermark, configure it, and then let the user take watermarked pictures and videos. However, you can call the configuration APIs at any moment during the app lifecycle.

swift
// Big, centered overlay watermark.size(width: 0.4, height: nil) watermark.position(anchor: .init(x: 0.5, y: 0.5)) // Later... make it smaller and move to the side: watermark.size(width: 0.2, height: nil) watermark.position(anchor: .init(x: 1, y: 1))
kotlin logokotlin
// Big, centered overlay watermark.size(width = 0.4F, height = null) watermark.position(anchor = Point(0.5F, 0.5F)) // Later... make it smaller and move to the side: watermark.size(width = 0.2F, height = null) watermark.position(anchor = Point(1F, 1F))

This means that by sending frequent updates, watermarks can be animated to appear as smoothly moving objects in video recordings.

⚠️

More powerful animation APIs are on the project roadmap. Stay tuned for updates.

Composition

You can present more than one more watermark on screen at the same time. Thanks to color support, this can be used to create creative effects in video recordings. For instance, the example below would show a full-screen watermark on black background, that can be removed after recording has started (with a slight delay):

swift
let background = watermarks.add(id: "background", targets: [.video]) let foreground = watermarks.add(id: "foreground", targets: [.video]) background.content(red: 0, green: 0, blue: 0) foreground.content(UIImage(named: "AppLogo")) foreground.position(anchor: .init(x: 0.5, y: 0.5) foreground.size(width: 0.4, height: nil) // A few seconds after recording has started... watermarks.remove(id: background.id) watermarks.remove(id: foreground.id)
kotlin logokotlin
val background = watermarks.add("background", targets: listOf(Target.Video)) val foreground = watermarks.add("foreground", targets: listOf(Target.Video)) background.content(red = 0F, green = 0F, blue = 0F) foreground.content(UIImage(named: "AppLogo")) foreground.position(anchor = Point(0.5F, 0.5F) foreground.size(width = 0.4F, height = null) // A few seconds after recording has started... watermarks.remove(id = background.id) watermarks.remove(id = foreground.id)

Subscribe to the DeepMedia Newsletter

The latest news about DeepMedia products, open source projects and software development at our company.

By clicking “Subscribe”, you agree that DeepMedia may use your email address to send you newsletters, including commercial communications, and to process your personal data for this purpose. You agree that DeepMedia may process said data using third-party services for this purpose in accordance with the DeepMedia Privacy Policy. You can revoke this consent at any time using the unsubscribe link included in each email or by writing at contact@deepmedia.io.