Try to run my example:
import numpy as np
import cairo
import matplotlib.pyplot as plt
img_size = 28
size = 0.8
color = (255, 0, 0)
thickness = 2
data = np.zeros((img_size, img_size, 3), dtype=np.uint8)
surface = cairo.ImageSurface.create_for_data(
data, cairo.FORMAT_RGB16_565, img_size, img_size
)
cr = cairo.Context(surface)
# fill with solid white
cr.set_source_rgb(1, 1, 1)
cr.paint()
size = img_size * size - thickness
cr.rectangle((img_size - size) / 2, (img_size - size) / 2, size, size)
cr.set_line_width(thickness)
cr.set_source_rgb(*color)
cr.stroke()
surface.write_to_png("shape.png")
plt.imshow(data)
plt.savefig("shape_from_np.png")
shape.png looks like:
shape_from_np.png looks like:
I was thinking maybe I missed the format, or channels/shape, but if I print out the red layer like data[:,:,0]
, it shows weird 0 values at the bottom half as well, and I'm not sure why.
In documentation I found ImageSurface.create_from_png(...)
so I used your 'shape.png'
to test what values it will use for PNG image.
import cairo
surface = cairo.ImageSurface.create_from_png('shape.png')
print('format:', surface.get_format())
print('width :', surface.get_width())
print('height:', surface.get_height())
print('stride:', surface.get_stride())
print('stride/width:', surface.get_stride()/surface.get_width())
and this gives
format: 1
width : 28
height: 28
stride: 112
stride/width: 4.0
I found that format: 1
means cairo.Format.RGB24
and in doc cairo.Format I found it needs 32bit
pixel which means 4
bytes in
data = np.zeros((img_size, img_size, 4), dtype=np.uint8)
and the same 4
gives me stride/width
(stride/28
)
Using these values I can create correct image but BGR
instead of RGB
So it still needs some changes.
But cv2
uses BGR
images and it saves it correctly without changes.
import cv2
cv2.imwrite('cv2.png', data)
import numpy as np
import cairo
import matplotlib.pyplot as plt
img_size = 28
size = 0.8
color = (255, 0, 0)
thickness = 2
data = np.zeros((img_size, img_size, 4), dtype=np.uint8)
surface = cairo.ImageSurface.create_for_data(data, cairo.FORMAT_RGB24, img_size, img_size)
cr = cairo.Context(surface)
# fill with solid white
cr.set_source_rgb(1, 1, 1)
cr.paint()
size = int(img_size * size) - thickness
cr.rectangle((img_size - size) / 2, (img_size - size) / 2, size, size)
cr.set_line_width(thickness)
cr.set_source_rgb(*color)
cr.stroke()
plt.imshow(data)
plt.savefig("shape_from_np.png")
surface.write_to_png("shape.png")
import cv2
cv2.imwrite('cv2.png', data)
Doc: ImageSurface, Format