-1

I cannot figure out how to draw a pixel in ipycanvas. I am drawing rectangles instead of pixels and this makes drawing very slow.

Drawing a rectangle using:

canvas.fill_rect

Code to display image in ipycanvas :

import pandas as pd
import numpy as np

import matplotlib.pyplot as plt

from PIL import Image

import ipycanvas
from ipycanvas import Canvas

import requests
from io import BytesIO

url = r"https://wallpapercave.com/dwp1x/wp1816238.jpg"
response = requests.get(url)
img = Image.open(BytesIO(response.content))

array = img.tobytes()

canvas = Canvas(width=img.width, height=img.height)
with ipycanvas.hold_canvas():
    for i in range(int(len(array)/3)):
        r = array[i * 3 + 0] # red
        g = array[i * 3 + 1] # green
        b = array[i * 3 + 2] # blue
        canvas.fill_style = f"#{r:02x}{g:02x}{b:02x}" # setting color
        canvas.fill_rect(i%img.width, int(i/img.width), 1, 1) # drawing rectangle
canvas

Output:

output image

I am drawing image pixel by pixel because I want to apply filters in images.

How to draw pixels in ipycanvas?

Udesh
  • 2,415
  • 2
  • 22
  • 32
  • any reason for using ipycanvas specifically? – Sam Mason Dec 01 '22 at 16:15
  • it was love @first glance – Udesh Dec 01 '22 at 16:28
  • 1
    I ask because both jupyter and numpy are compatible with PIL images... I'd use jupyter for viewing and numpy for pixel level operations – Sam Mason Dec 01 '22 at 16:30
  • can make a full answer if that would help – Sam Mason Dec 01 '22 at 16:31
  • I am learning about using filters in images and using `ipycanvas` for display the image pixel by pixel. In `ipycanvas` we create a canvas and do artwork upon it. I have difficulties in displaying image after applying filters on the array of bytes because its takes lots of time to render image since I am creating rectangle `image_width` * `image_height` times. – Udesh Dec 01 '22 at 16:40
  • lets try another way of asking. there are alternatives to using ipycanvas that would be much faster would you be interested in that? or do you really want to be using Python to draw on an [HTML5 Canvas](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) – Sam Mason Dec 01 '22 at 16:45

1 Answers1

1

Not sure if this will help but given you're talking about filtering I'd assume you mean things like convolutions. Numpy and Scipy help a lot and provide various ways of applying these and work well with images from Pillow.

For example:

import requests
from io import BytesIO
from PIL import Image

import numpy as np
from scipy import signal

image_req = requests.get("https://wallpapercave.com/dwp1x/wp1816238.jpg")
image_req.raise_for_status()

image = Image.open(BytesIO(image_req.content))

# create gaussian glur of a given standard deviation
sd = 3
filt = np.outer(*2*[signal.windows.gaussian(int(sd*5)|1, sd)])
filt /= filt.sum()

# interpret image as 3d array
arr = np.array(image)

# apply it to each channel independently, this loop runs in ~0.1 seconds
for chan in range(3):
    arr[:,:,chan] = signal.oaconvolve(arr[:,:,chan], filt, mode='same')

# array back into image for display in notebook
Image.fromarray(arr)

This produces an image like:

blurred image

Sam Mason
  • 15,216
  • 1
  • 41
  • 60