diff --git a/components/micropython/usermodule/mp_uctx.c b/components/micropython/usermodule/mp_uctx.c
index c4638549b06d0635ed1f9ba36b5a4bff9d7106cb..bc0373ee074684cac39d98d016f140d04bbb6c68 100644
--- a/components/micropython/usermodule/mp_uctx.c
+++ b/components/micropython/usermodule/mp_uctx.c
@@ -397,6 +397,25 @@ static mp_obj_t mp_ctx_texture(size_t n_args, const mp_obj_t *args) {
 }
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_ctx_texture_obj, 6, 6, mp_ctx_texture);
 
+static mp_obj_t mp_ctx_image(size_t n_args, const mp_obj_t *args) {
+    mp_ctx_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+
+    const char *path = mp_obj_str_get_str(args[1]);
+    float x0 = 0.0;
+    float y0 = 0.0;
+    float width = -1.0;
+    float height = -1.0;
+
+    if (n_args > 2) x0 = mp_obj_get_float(args[2]);
+    if (n_args > 3) y0 = mp_obj_get_float(args[3]);
+    if (n_args > 4) width = mp_obj_get_float(args[4]);
+    if (n_args > 5) height = mp_obj_get_float(args[5]);
+    ctx_draw_image(self->ctx, path, x0, y0, width, height);
+
+    return args[0];
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_ctx_image_obj, 2, 6, mp_ctx_image);
+
 #if 0
 static mp_obj_t mp_ctx_font(mp_obj_t self_in, mp_obj_t font_in)
 {
@@ -818,6 +837,7 @@ static const mp_rom_map_elem_t mp_ctx_locals_dict_table[] = {
     MP_CTX_METHOD(add_stop),
     MP_CTX_METHOD(line_dash),
     MP_CTX_METHOD(texture),
+    MP_CTX_METHOD(image),
     MP_CTX_METHOD(save),
     MP_CTX_METHOD(restore),
     MP_CTX_METHOD(start_frame),
diff --git a/python_payload/mypystubs/ctx.pyi b/python_payload/mypystubs/ctx.pyi
index 53c0defde179b3814916de8f9cf89a0d475b8f44..24dbe68bd4d8e0e369535b2e0d9ed9f6935d0279 100644
--- a/python_payload/mypystubs/ctx.pyi
+++ b/python_payload/mypystubs/ctx.pyi
@@ -284,6 +284,14 @@ class Context(Protocol):
         radiuses are in use.
         """
         pass
+    def image(self, path: str, x: float, y: float, w: float, h: float) -> "Context":
+        """
+        Draw the image at path a in a rectangle with upper left coordinates at
+        x,y which is w wide and h high. If w or h is -1 the other is set
+        maintaining aspect ratio, if both are -1 the pixel dimensions of the
+        image is used.
+        """
+        pass
     def logo(self, x: float, y: float, dim: float) -> "Context":
         """
         TOD(q3k): document
diff --git a/sim/fakes/ctx.py b/sim/fakes/ctx.py
index 27993172391bde25bbd80e9f2bbe7dcc6973b229..eff4a3a4647af5360e58b2425411bb226c850d13 100644
--- a/sim/fakes/ctx.py
+++ b/sim/fakes/ctx.py
@@ -216,6 +216,19 @@ class Context:
         )
         return self
 
+    def image(self, path, x, y, width, height):
+        # TODO: replace with base64 encoded, decoded version of image
+        self._emit(f"save")
+        self._emit(f"rectangle {x} {y} {width} {height}")
+        self._emit(f"rgba 0.5 0.5 0.5 0.5")
+        self._emit(f"fill")
+        self._emit(f"rectangle {x} {y} {width} {height}")
+        self._emit(f"gray 1.0")
+        self._emit(f"lineWidth 1")
+        self._emit(f"stroke")
+        self._emit(f"restore")
+        return self
+
     def rectangle(self, x, y, width, height):
         self._emit(f"rectangle {x} {y} {width} {height}")
         return self