Creating a Figma Plugin to Add Stroke to Bitmaps

The Plugin is Image Stroke.

Creating a Figma Plugin to Add Stroke to Bitmaps
🌐
你可以阅读本篇文章的中文版本

The primary purpose of the Image Stroke plugin is to add vector strokes to bitmap layers in Figma. Similar to the Layer Style - Stroke effect commonly found in software like Photoshop, this functionality has been missing in Figma. 

Image Stroke | Figma
直接在 Figma 中为位图添加矢量描边。 只专注于生成图像的轮廓描边,不处理图像内部细节;开箱即用,一切都在 Figma 内部完成;中文英文语言切换;符合 Figma 的浅色和深色主题模式;免费; 详细使用说明可在插件中查看。 --- Add Vector Strokes to Bitmaps Directly in Figma Focuses solely on generating the outline stroke of the image, without processing internal details;Ready to use out of the box,…

Creating this plugin was driven by two main goals: one was to fulfill my own needs, and the other was to familiarize myself with the development workflow of Cursor.

As shown, the left image is a bitmap with a transparent background. Applying a stroke directly to it results in the middle image, where the stroke is applied to the layer rather than the image content. The right image demonstrates the desired effect achieved by this plugin.

https://figma plugin url

Why Use Image Stroke?

Traditional methods for adding strokes :

  • Using other bitmap-to-vector plugins, adjusting parameters to generate a vectorized version of the entire content, and then manually adding a stroke.
  • Exporting the image to Adobe Illustrator, expanding it to create a vectorized graphic, and then pasting it back into Figma.
  • Exporting the image to Adobe Photoshop, adding a stroke directly, and exporting it again, which still results in a bitmap.

Image Stroke‘s advantages:

  • Focuses solely on generating the outline stroke of the image content, without processing internal details, which may result in faster processing.
  • Everything is done within Figma, eliminating the need to open other software like Adobe products.
  • Automatically detects transparency thresholds (threshold), making it as plug-and-play as possible.
  • Permanently free.

However, Image Stroke has its limitations:

  • The contour detection algorithm still has room for improvement.
  • Sometimes, the automatic detection of transparency thresholds (threshold) may fail, requiring manual parameter adjustments.
  • Certain special images may not work correctly, necessitating additional manual adjustments to image properties.

Additional Notes:

  • Only supports single-image content strokes. If an image contains multiple disconnected elements, only the leftmost one will be stroked.Fixed
  • It is recommended to place the image outside of a frame when using the plugin; otherwise, the generated stroke may be misaligned.Fixed
  • The plugin recognizes the original image, so it cannot generate paths for cropped images. The correct approach is to crop the image, export it as a PNG, and then use the plugin.

The following sections will provide detailed explanations of these points.

Parameter Explanation

Stroke Width and Stroke Color

  • Simply input the values as you would for the Stroke property in Figma.
  • The stroke corners are set to be smooth by default.

Sampling Rate

A higher value results in a simpler contour (1-10), with fewer anchor points and less detail.

  • Note that the sampling rate is also related to the image size.
    • For larger images, a higher sampling rate can be used.
    • For smaller images, a smaller sampling rate is recommended.
  • It is advisable to start with a value of 1 and adjust as needed.
  • If the sampling rate is mismatched, no path will be generated.
  • Note: Circular edges are considered complex edges.

Simplify Tolerance

A higher value results in a smoother path.

  • The adjustment logic is similar to that of the sampling rate and is also related to edge complexity and image size.
  • However, it is not recommended to increase both parameters simultaneously, as this may result in overly simplistic paths.

Edge Threshold

Similar to the threshold in vectorization algorithms, this parameter is related to the clarity of the image edges. As shown in the illustration, I manually reduced the edge clarity using a blur effect. The more blurred the edges, the lower the threshold needs to be to accurately follow the edges.

  • For images with blurred or semi-transparent edges, adjusting the threshold is necessary to accurately capture the edges, especially after using tools like "remove background," which can complicate the transparency of the image edges. To achieve the desired effect, it is recommended to zoom in and experiment with different threshold values.
  • Sometimes, the threshold may need to be set very low.

Closed Path Threshold

Closes the path when the distance between the starting and ending anchor points is less than this value; otherwise, the contour tracing continues. This will be discussed in the "Process and Principle" section.

This parameter is generally not modified, so hidden in the advanced settings.

Process and Principle

First, I must declare that I am not a programmer. Most of the plugin's code was generated by Cursor. My role was to propose requirements and guide Cursor in generating the code in the right direction.

Initially, I considered writing a vectorization function, but found it too complex and ineffective. I then researched the algorithm Photoshop uses to generate strokes and discovered the Distance Field series of algorithms. Valve had improved this algorithm for vectorizing textures and applied it in their Source engine (Improved Alpha-Tested Magnification for Vector Textures and Special Effects). However, this still wasn't what I was looking for—it needed to be simpler.

After further research, I found that the "Marching Ants" algorithm might be the answer. This seems to be an old yet common algorithm, though I was unaware of it due to my lack of expertise in this field. With some guidance from a friend, I gathered some materials and shared them with Cursor, which eventually led to the current code.

  1. Start scanning the image from the top-left corner, column by column, and from top to bottom within each column.
  2. Identify the first non-transparent pixel as the starting point.
  3. From the starting point, explore the transparency of the 8 surrounding pixels until the next contour point is found.
  4. A pixel is considered a contour point if it is not transparent and has at least one transparent pixel nearby.
  5. Trace other contour points in a specific direction and sampling rate to create a single, closed path.
  6. Use SVG's M command to generate anchor points and L to connect to the next anchor point. When the distance between the start and end points is less than a certain parameter, use Z to close the path.

After some black-box testing, I set the parameters for the automatic threshold, with the detected first pixel's transparency coefficient approximately set to 2. If the output is incorrect, increment the value by 1 until it reaches 255.

It's worth noting that image processing requires decoding the image into RGBA data, as mentioned in the Working with Images documentation. However, Cursor was not initially aware of this. As a user of AI-assisted coding, even if you're not writing the code yourself, it's important to understand the logical relationships in the code. Cursor could also evolve in this direction, such as offering one-click access to documentation from well-known libraries, in addition to notepads.

Limitations

Contour Detection Algorithm Still Has Room for Improvement

Currently, the scanning starts linearly from top to bottom and left to right. Scanning from all sides might be more efficient, though I'm not certain, and multiple tracing directions might affect path closure.

Automatic Edge Threshold Detection May Fail

As mentioned, manual parameter adjustments may be necessary. To manually set the threshold, zoom in on the image until you can see the square pixels. Locate the first pixel in the top-left corner and estimate its transparency threshold. The lower the pixel's transparency, the lower the threshold parameter should be.

Some Special Images May Not Work

Currently, only PNG images are supported. You may need to manually export the image or use ⇧⌘C. Due to the limited number of test images, there may be cases where adjusting parameters doesn't work. I will consider further optimizations if time permits.

Only Supports Single-Image Content Strokes

If an image contains multiple disconnected elements, only the leftmost one will be stroked.

Plugin Recognizes the Original Image

The plugin cannot generate paths for cropped images. The correct approach is to crop the image, export it as a PNG, and then use the plugin.

No Open-Source Repository

Since most of the code was generated by AI and is not particularly complex, I feel that uploading it to GitHub might not be appropriate. If there's significant interest in the source code, I may consider opening a repository.

订阅 Design Scenes

发布最新文章时,会以邮件通知你
zelda@link.com
订阅