I have found a workaround to display the image sharp.
It requires manually changing a value in the code each time you change scaling in Windows.
Step 1:
%%javascript
const ratio = window.devicePixelRatio;
alert("devicePixelRatio: " + ratio);
Step 2:
devicePixelRatio = 1.875 # manually enter the value that was shown
Step 3:
from PIL import Image
from IPython.display import HTML
import numpy as np
import io
import base64
# 32x32 data
bw_data = np.zeros((32,32),dtype=np.uint8)
# (odd_rows, even_columns)
bw_data[1::2,::2] = 1
# (even_rows, odd_columns)
bw_data[::2,1::2] = 1
# Build pixel-exact HTML
def display_pixel_image(np_array):
# Convert binary image to black & white PIL image
img = Image.fromarray(np_array * 255).convert('1')
# Convert to base64-encoded PNG
buf = io.BytesIO()
img.save(buf, format='PNG')
b64 = base64.b64encode(buf.getvalue()).decode('utf-8')
# HTML + CSS to counteract scaling
html = f"""
<style>
.pixel-art {{
width: calc({img.width}px / {devicePixelRatio});
image-rendering: pixelated;
display: block;
margin: 0;
padding: 0;
}}
</style>
<img class="pixel-art" src="data:image/png;base64,{b64}">
"""
display(HTML(html))
display_pixel_image(bw_data)
output:
Visual Studio Code cannot access ipython kernel so I don't know how to retrieve devicePixelRatio from Javascript. I tried to make an ipython widget, but was not able to refresh it automatically. If this can be done automatically then it won't require user input.