Is there a way to pass a Pandas DataFrame (or numpy arrray) to PyDeck Bitmap layer to render as an image?
I would like to do something like this
array = np.zeros([100, 200, 4], dtype=np.uint8)
array[:,:100] = [255, 100, 0, 255]
array[:,100:] = [0, 0, 255, 255]
import pydeck as pdk
bitmap_layer = pdk.Layer("BitmapLayer", data=array, opacity=0.7)
r = pdk.Deck(bitmap_layer)
r.show()
I am able to plot the values of a matrix (where each row represents the lng-lat value of a matrix) using the GridCellLayer but I'm wondering whether the Bitmap layer would work better
grid_layer = pdk.Layer(
"GridCellLayer",
df,
pickable=True,
cell_size=ini_cell_size,
get_position=['lng', 'lat'],
extruded=False,
get_fill_color = 'color',
)
The BitmapLayer is indeed more suitable for this use case.
In JavaScript you can pass a ImageData object to the image prop:
new BitmapLayer({
// ...
image: new ImageData(<Uint8ClampedArray>, width, height)
})
I think pydeck may need some modifications to support this?
@ajduberstein @ibgreen
Thanks for the question @cornhundred. You can do this in pydeck鈥揻irst convert the matrix to an image and then convert the image to a base64-encoded string. See this Stack overflow question on converting a numpy matrix to an image and then you can convert that image to a base64-encoded string.
Thanks @ajduberstein and @Pessimistress, I tried the following using the red dot and it worked
red_dot_url = '"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="'

but I was unable to visualize a custom image (blue square)
w, h = 20, 20
data = np.zeros((h, w, 3), dtype=np.uint8)
data[0:25, 0:25] = [0, 0, 255] # red patch in upper left
img = Image.fromarray(data, 'RGB')
blue_square_url = '"data:image/png;base64,'+ str(base64.b64encode(img.tobytes()).decode('utf-8')) + '"'
The blue square url is
'"data:image/png;base64,AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/"'
The following just showed a white background
# base64-encoded image string of a red dot
bitmap_layer = pdk.Layer("BitmapLayer", data=None, image=blue_square_url, opacity=1.0)
view_state = pdk.ViewState(longitude=0.5, latitude=0.5, zoom=7)
r = pdk.Deck(bitmap_layer, initial_view_state=view_state)
r.show()
Copying and pasting this into the browser (as recommended by https://github.com/visgl/deck.gl/issues/4977#issuecomment-700118566) showed a black square so I'm guessing the encoding failed.
Yes, I think the issue is with the encoding. There's a StackOverflow answer discussing how to convert PIL images to base64-encoded strings.
Thanks @ajduberstein, that worked. Although, I had to strip off a few characters from the str(img_str)[2:1]
from io import BytesIO
buffered = BytesIO()
img.save(buffered, format="PNG")
img_str = base64.b64encode(buffered.getvalue())
str(img_str)
new_blue_square_url = '"data:image/png;base64,'+ str(img_str)[2:-1] + '"'
new_blue_square_url
which gives
'"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAAHUlEQVR4nGNkYPjPQC5gIlvnqOZRzaOaRzVTRTMAIJ4BJ6WiocQAAAAASUVORK5CYII="'

@ajduberstein one more quick question, is there a way to prevent the apparent anti-aliasing that blurs the image?
