# Create a mesh from image with transparency

Is there a way to create a flat mesh from an image that has transparency, so that the mesh matches shape and does not include the transparency in the geometry?

I have tried converting my image in an .svg with inkscape and adding a bitmap, but the results get very messy.

Here is my image:

Thanks.

I wrote a script to do exactly this a while back, here it is:

Tips on usage, if you really are using pixel art, then avoid representing the pixels using 4 pixels. You don't have to.. but it makes the resulting mesh unnecessarily vertex heavy before doing any operations like 'limited dissolve' (which joins all adjacent geometry when possible)

Script, is a little long but I'll include here anyway.

from collections import defaultdict

import bpy

scene = bpy.context.scene

color_map = defaultdict(list)
filename = "aYlTzbV.png"
img = bpy.data.images[filename]
scale = 0.3

def idx_to_co(idx, width):
r = int(idx / width)
c = idx % width
return r, c

def co_to_idx(r, c, width):
return r * width + c

def rgba_from_index(idx, pxs):
start_raw_index = idx * 4
return pxs[start_raw_index:start_raw_index+4]

def sv_main():

def is_fully_opaque(rgba):
return rgba[3] == 1.0

pixels = img.pixels
pxs = list(pixels)

w = width = img.size[0]
h = height = img.size[1]

num_pixels = len(pxs)
gl = grouped_list = [pxs[i:i+4] for i in range(num_pixels)[::4]]

for c in range(w):
for r in range(h):
idx = co_to_idx(r, c, w)
rgba = rgba_from_index(idx, pxs)
if is_fully_opaque(rgba):
color_map[tuple(rgba[:3])].append([r*scale, -c*scale, 0.0])

def create_repr_plane(obj_name, mesh_name, vlist):
s = scale/2
verts = []
faces = []

for i, v in enumerate(vlist):
x, y = v[:2]
v_add([[-s+x, s+y, 0], [-s+x, -s+y, 0], [s+x, -s+y, 0], [s+x, s+y, 0]])

offset = i*4
f_add([0 + offset, 1 + offset, 2 + offset, 3 + offset])

profile_mesh = bpy.data.meshes.new(obj_name)
profile_mesh.from_pydata(verts, [], faces)
profile_mesh.update()

profile_object = bpy.data.objects.new(obj_name, profile_mesh)

return profile_object

sv_main()

for i, (k, v) in enumerate(color_map.items()):

obj = create_repr_plane("dupli_object_" + str(i), "dupli_mesh_" + str(i), v)

repr_of_color = "{0:.4f} {1:.4f} {2:.4f}".format(*k)
mat = bpy.data.materials.new('sv_material_' + repr_of_color)
mat.use_nodes = True
mat.use_fake_user = True  # usually handy
obj.active_material = mat
nodes = mat.node_tree.nodes
nodes["Diffuse BSDF"].inputs[0].default_value = list(k) + [1]


It does a few things:

• rages through the image (if doesn't really care if it's low or high res, but high res will slow it down)
• Indexes the coordinates of all similar coloured pixels
• generates a quad based mesh to represent each pixel, and joins them all in one mesh object for one colour
• makes a cycles material node for each object and sets it to the indexed color.

doesn't do
Several post processing steps

• doesn't join the resulting objects into one multi-material object
• doesn't perform remove doubles / limited dissolve

### Warning:

This script assumes your low res image doesn't have thousands of different colours. It will create as many different objects as colors found in the image. Tip is to first Quantize the image or let some tool index the colors for you. This will perform terrible with lots of gradients, if you need gradients this script is not for you. It's writen in the spirit of low res low dynamic range images.

• Thanks a lot! I hope you don't mind if I keep it as a file and use it on other projects. Thanks again! – TrakJohnson Jul 9 '15 at 9:03
• You can use it any way you wish, hopefully it shows how useful it can be to learn a programming language. – zeffii Jul 9 '15 at 9:15
• i made a similar (probably less elegant) add-on version of the same problem for 2.79 github.com/benkl/pixeler – BK. Feb 22 '18 at 1:43

This method may be not efficient, but this is how I did it :)