diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py
index e236853bca592695e1d98fc8b42455ef26d1908d..ba0518cba01d9b35a4fa0249fd7722e0bc5542b0 100644
--- a/pyopencl/__init__.py
+++ b/pyopencl/__init__.py
@@ -868,7 +868,7 @@ def _mark_copy_deprecated(func):
 
 enqueue_read_image = _mark_copy_deprecated(_cl._enqueue_read_image)
 enqueue_write_image = _mark_copy_deprecated(_cl._enqueue_write_image)
-# enqueue_copy_image = _mark_copy_deprecated(_cl._enqueue_copy_image)
+enqueue_copy_image = _mark_copy_deprecated(_cl._enqueue_copy_image)
 # enqueue_copy_image_to_buffer = _mark_copy_deprecated(
 #         _cl._enqueue_copy_image_to_buffer)
 # enqueue_copy_buffer_to_image = _mark_copy_deprecated(
diff --git a/pyopencl/c_wrapper/wrap_cl_core.h b/pyopencl/c_wrapper/wrap_cl_core.h
index 52bb18759b64fe84e30225f710758c9dbdbb2563..08dc767881578d3214a413a3994c90d78ed0c20c 100644
--- a/pyopencl/c_wrapper/wrap_cl_core.h
+++ b/pyopencl/c_wrapper/wrap_cl_core.h
@@ -166,6 +166,12 @@ error *enqueue_read_image(clobj_t *event, clobj_t queue, clobj_t mem,
                           void *buffer, size_t row_pitch, size_t slice_pitch,
                           const clobj_t *wait_for, uint32_t num_wait_for,
                           int is_blocking, void *pyobj);
+error *enqueue_copy_image(clobj_t *_evt, clobj_t _queue, clobj_t _src,
+                          clobj_t _dst, const size_t *_src_origin,
+                          size_t src_origin_l, const size_t *_dst_origin,
+                          size_t dst_origin_l, const size_t *_region,
+                          size_t region_l, const clobj_t *_wait_for,
+                          uint32_t num_wait_for);
 error *enqueue_write_image(clobj_t *_evt, clobj_t _queue, clobj_t _mem,
                            const size_t *origin, size_t origin_l,
                            const size_t *region, size_t region_l,
diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py
index 486ab73513df4bacd216610d990039b4af830dc7..9eb05acdae3063d227a30526b73444af9172d351 100644
--- a/pyopencl/cffi_cl.py
+++ b/pyopencl/cffi_cl.py
@@ -922,13 +922,28 @@ def _enqueue_read_image(queue, mem, origin, region, hostbuf, row_pitch=0,
         bool(is_blocking), _ffi.new_handle(c_buf)))
     return _create_instance(NannyEvent, ptr_event[0])
 
+def _enqueue_copy_image(queue, src, dest, src_origin, dest_origin, region,
+                        wait_for=None):
+    src_origin_l = len(src_origin)
+    dest_origin_l = len(dest_origin)
+    region_l = len(region)
+    if src_origin_l > 3 or dest_origin_l > 3 or region_l > 3:
+        raise RuntimeError("(src/dest)origin or region has too many components",
+                           "enqueue_copy_image")
+    _event = _ffi.new('clobj_t*')
+    c_wait_for, num_wait_for = _clobj_list(wait_for)
+    _handle_error(_lib.enqueue_copy_image(
+        _event, queue.ptr, src.ptr, dest.ptr, src_origin, src_origin_l,
+        dest_origin, dest_origin_l, region, region_l, c_wait_for, num_wait_for))
+    return _create_instance(Event, ptr_event[0])
+
 def _enqueue_write_image(queue, mem, origin, region, hostbuf, row_pitch=0,
                          slice_pitch=0, wait_for=None, is_blocking=True):
     origin_l = len(origin)
     region_l = len(region)
     if origin_l > 3 or region_l > 3:
         raise RuntimeError("origin or region has too many components",
-                           "enqueue_read_image")
+                           "enqueue_write_image")
     c_buf, size, _ = _c_buffer_from_obj(hostbuf)
     _event = _ffi.new('clobj_t*')
     c_wait_for, num_wait_for = _clobj_list(wait_for)
@@ -945,7 +960,7 @@ def enqueue_map_image(queue, img, flags, origin, region, shape, dtype,
     region_l = len(region)
     if origin_l > 3 or region_l > 3:
         raise RuntimeError("origin or region has too many components",
-                           "enqueue_read_image")
+                           "enqueue_map_image")
     _event = _ffi.new('clobj_t*')
     _map = _ffi.new('clobj_t*')
     _row_pitch = _ffi.new('size_t*')
@@ -960,8 +975,7 @@ def enqueue_map_image(queue, img, flags, origin, region, shape, dtype,
     map._init_array(shape, dtype.str, strides)
     return np.asarray(map), event, _row_pitch[0], _slice_pitch[0]
 
-# TODO: copy_image fill_image
-#    copy_buffer_to_image copy_image_to_buffer
+# TODO: fill_image copy_buffer_to_image copy_image_to_buffer
 
 # }}}
 
diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp
index 23b82e78ad99d24df7a4090e3e87b00bcb12b9da..db3f1e73f01f35062b84ff8fdc358988cbe691a0 100644
--- a/src/c_wrapper/wrap_cl.cpp
+++ b/src/c_wrapper/wrap_cl.cpp
@@ -1131,33 +1131,6 @@ new_image(cl_mem mem, void *buff=0)
 
 // {{{ image transfers
 
-  //   inline
-  //   event *enqueue_copy_image(
-  //       command_queue &cq,
-  //       memory_object_holder &src,
-  //       memory_object_holder &dest,
-  //       py::object py_src_origin,
-  //       py::object py_dest_origin,
-  //       py::object py_region,
-  //       py::object py_wait_for
-  //       )
-  //   {
-  //     PYOPENCL_PARSE_WAIT_FOR;
-  //     COPY_PY_COORD_TRIPLE(src_origin);
-  //     COPY_PY_COORD_TRIPLE(dest_origin);
-  //     COPY_PY_REGION_TRIPLE(region);
-
-  //     cl_event evt;
-  //     PYOPENCL_RETRY_IF_MEM_ERROR(
-  //       PYOPENCL_CALL_GUARDED(clEnqueueCopyImage, (
-  //             cq.data(), src.data(), dest.data(),
-  //             src_origin, dest_origin, region,
-  //             PYOPENCL_WAITLIST_ARGS, &evt
-  //             ));
-  //       );
-  //     PYOPENCL_RETURN_NEW_EVENT(evt);
-  //   }
-
   //   inline
   //   event *enqueue_copy_image_to_buffer(
   //       command_queue &cq,
@@ -2564,6 +2537,32 @@ enqueue_read_image(clobj_t *_evt, clobj_t _queue, clobj_t _mem,
         });
 }
 
+error*
+enqueue_copy_image(clobj_t *_evt, clobj_t _queue, clobj_t _src, clobj_t _dst,
+                   const size_t *_src_origin, size_t src_origin_l,
+                   const size_t *_dst_origin, size_t dst_origin_l,
+                   const size_t *_region, size_t region_l,
+                   const clobj_t *_wait_for, uint32_t num_wait_for)
+{
+    auto wait_for = buf_from_class<event>(_wait_for, num_wait_for);
+    auto queue = static_cast<command_queue*>(_queue);
+    auto src = static_cast<image*>(_src);
+    auto dst = static_cast<image*>(_dst);
+    ConstBuffer<size_t, 3> src_origin(_src_origin, src_origin_l);
+    ConstBuffer<size_t, 3> dst_origin(_dst_origin, dst_origin_l);
+    ConstBuffer<size_t, 3> region(_region, region_l);
+    return c_handle_error([&] {
+            cl_event evt;
+            retry_mem_error<void>([&] {
+                    pyopencl_call_guarded(
+                        clEnqueueCopyImage, queue->data(), src->data(),
+                        dst->data(), src_origin, dst_origin, region,
+                        num_wait_for, wait_for.get(), &evt);
+                });
+            *_evt = new_event(evt);
+        });
+}
+
 error*
 enqueue_write_image(clobj_t *_evt, clobj_t _queue, clobj_t _mem,
                     const size_t *_origin, size_t origin_l,