3
$\begingroup$

I would like to be able to draw a circle inside an image that is available in image editor.

I found this code here but I do not know how to manipulate the xy values for drawing a circle properly.

size = 640, 480

import bpy
# blank image
image = bpy.data.images.new("MyImage", width=size[0], height=size[1])

## For white image
# pixels = [1.0] * (4 * size[0] * size[1])

pixels = [None] * size[0] * size[1]
for x in range(size[0]):
    for y in range(size[1]):
        # assign RGBA to something useful
        r = x / size[0]
        g = y / size[1]
        b = (1 - r) * g
        a = 1.0

        pixels[(y * size[0]) + x] = [r, g, b, a]

# flatten list
pixels = [chan for px in pixels for chan in px]

# assign pixels
image.pixels = pixels

# write image
image.filepath_raw = "/tmp/temp.png"
image.file_format = 'PNG'
image.save()

```
$\endgroup$
1
  • $\begingroup$ Wow never knew direct pixel access was possible. Can we now extend it with popular python image libraries as well? $\endgroup$
    – Peter
    Jan 25 '20 at 11:24
3
$\begingroup$

Try this (I'm on Blender 2.81a):

import bpy
import math

size = 640, 480

# Calculate distance between two point
def distance(p0, p1):
    return math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)

# blank image
image = bpy.data.images.new("circle_img", width=size[0], height=size[1])

pixels = [None] * size[0] * size[1]
center = (int(size[0]/2.0), int(size[1]/2.0)) # center of image
radius = 50 # radius of circle in pixels
for x in range(size[0]):
    for y in range(size[1]):
        d = distance((x,y),center)
        if d < radius:
            r = g = b = a = 1.0 # white
        else:
            r = g = b = 0.0 # black
            a = 1.0            
        pixels[(y * size[0]) + x] = [r, g, b, a]

# flatten list
pixels = [chan for px in pixels for chan in px]

# assign pixels
image.pixels = pixels

# write image
image.filepath_raw = "/tmp/temp.png"
image.file_format = 'PNG'
image.save()

Circle isn't very pretty though (could use some anti-alias or blur)!

$\endgroup$
2
  • $\begingroup$ Thanks, that works for me. $\endgroup$
    – yarun can
    Jan 14 '20 at 17:16
  • $\begingroup$ Be tempted to leverage of v = Vector((x + 0.5, y + 0.5)) rather than the expensive euclidean distance calculation, and maybe use the "pixel center" (eg for pixel 0, 0 the center is (0.5, 0.5)) and not type cast the image center to int. The distance is then (v - center).length $\endgroup$
    – batFINGER
    Jan 15 '20 at 2:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.