diff --git a/TODOs b/TODOs
index df683851259b6d95ee2d1b7e69c50435c45b1114..b34b882c6356d10137f6cfe6b6a5970fb3e11533 100644
--- a/TODOs
+++ b/TODOs
@@ -5,8 +5,6 @@
 - enqueue_nd_range_kernel size/offset mess
 
 - CommandQueue.set_property
-- _enqueue_copy_image_to_buffer
-- _enqueue_copy_buffer_to_image
 - _Program.create_with_built_in_kernels
 - _Program.compile
 - _Program.link
diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py
index d0053f048a2ec32c245888baa9e9764d1f800c50..f16121afabc4794832b931bbb436feb70fa85a98 100644
--- a/pyopencl/__init__.py
+++ b/pyopencl/__init__.py
@@ -869,10 +869,10 @@ 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_to_buffer = _mark_copy_deprecated(
-#         _cl._enqueue_copy_image_to_buffer)
-# enqueue_copy_buffer_to_image = _mark_copy_deprecated(
-#         _cl._enqueue_copy_buffer_to_image)
+enqueue_copy_image_to_buffer = _mark_copy_deprecated(
+        _cl._enqueue_copy_image_to_buffer)
+enqueue_copy_buffer_to_image = _mark_copy_deprecated(
+        _cl._enqueue_copy_buffer_to_image)
 enqueue_read_buffer = _mark_copy_deprecated(_cl._enqueue_read_buffer)
 enqueue_write_buffer = _mark_copy_deprecated(_cl._enqueue_write_buffer)
 enqueue_copy_buffer = _mark_copy_deprecated(_cl._enqueue_copy_buffer)
diff --git a/pyopencl/c_wrapper/wrap_cl_core.h b/pyopencl/c_wrapper/wrap_cl_core.h
index c22738b8efc75a94a1cde096b923501d7ba9433d..b50ab024e5b715e48e75301bc85db4a69e75db9a 100644
--- a/pyopencl/c_wrapper/wrap_cl_core.h
+++ b/pyopencl/c_wrapper/wrap_cl_core.h
@@ -260,6 +260,15 @@ error *enqueue_fill_image(clobj_t *evt, clobj_t _queue, clobj_t mem,
                           size_t origin_l, const size_t *_region,
                           size_t region_l, const clobj_t *_wait_for,
                           uint32_t num_wait_for);
+error *enqueue_copy_image_to_buffer(clobj_t *evt, clobj_t _queue, clobj_t _src,
+                                    clobj_t _dst, const size_t *_orig, size_t,
+                                    const size_t *_reg, size_t, size_t offset,
+                                    const clobj_t *_wait_for, uint32_t);
+error *enqueue_copy_buffer_to_image(clobj_t *evt, clobj_t _queue, clobj_t _src,
+                                    clobj_t _dst, size_t offset,
+                                    const size_t *_orig, size_t,
+                                    const size_t *_reg, size_t,
+                                    const clobj_t *_wait_for, uint32_t);
 // CL Object
 intptr_t clobj__int_ptr(clobj_t obj);
 error *clobj__get_info(clobj_t obj, cl_uint param, generic_info *out);
diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py
index a3a1313a2010a54db078bf61d7ee282f68c38217..aca699344900b021bd688446a47b8a2280f4d735 100644
--- a/pyopencl/cffi_cl.py
+++ b/pyopencl/cffi_cl.py
@@ -1353,6 +1353,42 @@ def enqueue_fill_image(queue, img, color, origin, region, wait_for=None):
                                           region_l, c_wait_for, num_wait_for))
     return Event._create(ptr_event[0])
 
+
+def enqueue_copy_image_to_buffer(queue, src, dest, origin, region, offset,
+                                 wait_for=None):
+    origin = tuple(origin)
+    region = tuple(region)
+    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",
+                           status_code.INVALID_VALUE,
+                           "enqueue_copy_image_to_buffer")
+    _event = _ffi.new('clobj_t*')
+    c_wait_for, num_wait_for = _clobj_list(wait_for)
+    _handle_error(_lib.enqueue_copy_image_to_buffer(
+        _event, queue.ptr, src.ptr, dest.ptr, origin, origin_l, region,
+        region_l, offset, c_wait_for, num_wait_for))
+    return Event._create(ptr_event[0])
+
+
+def enqueue_copy_buffer_to_image(queue, src, dest, offset, origin, region,
+                                 wait_for=None):
+    origin = tuple(origin)
+    region = tuple(region)
+    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",
+                           status_code.INVALID_VALUE,
+                           "enqueue_copy_buffer_to_image")
+    _event = _ffi.new('clobj_t*')
+    c_wait_for, num_wait_for = _clobj_list(wait_for)
+    _handle_error(_lib.enqueue_copy_buffer_to_image(
+        _event, queue.ptr, src.ptr, dest.ptr, offset, origin, origin_l,
+        region, region_l, c_wait_for, num_wait_for))
+    return Event._create(ptr_event[0])
+
 # }}}
 
 # {{{ gl interop
diff --git a/src/c_wrapper/image.cpp b/src/c_wrapper/image.cpp
index e39bfa436e8caae354711096789770a5622d7288..2892e17c2d8a0b0ad9c63944ddf0002dd780b940 100644
--- a/src/c_wrapper/image.cpp
+++ b/src/c_wrapper/image.cpp
@@ -2,6 +2,7 @@
 #include "context.h"
 #include "command_queue.h"
 #include "event.h"
+#include "buffer.h"
 
 namespace pyopencl {
 
@@ -52,62 +53,6 @@ image::get_image_info(cl_image_info param) const
     }
 }
 
-// {{{ image transfers
-
-//   PYOPENCL_INLINE
-//   event *enqueue_copy_image_to_buffer(
-//       command_queue &cq,
-//       memory_object_holder &src,
-//       memory_object_holder &dest,
-//       py::object py_orig,
-//       py::object py_reg,
-//       size_t offset,
-//       py::object py_wait_for
-//       )
-//   {
-//     PYOPENCL_PARSE_WAIT_FOR;
-//     COPY_PY_COORD_TRIPLE(orig);
-//     COPY_PY_REGION_TRIPLE(reg);
-
-//     cl_event evt;
-//     PYOPENCL_RETRY_IF_MEM_ERROR(
-//       PYOPENCL_CALL_GUARDED(clEnqueueCopyImageToBuffer, (
-//             cq.data(), src.data(), dest.data(),
-//             orig, reg, offset,
-//             PYOPENCL_WAITLIST_ARGS, &evt
-//             ));
-//       );
-//     PYOPENCL_RETURN_NEW_EVENT(evt);
-//   }
-
-//   PYOPENCL_INLINE
-//   event *enqueue_copy_buffer_to_image(
-//       command_queue &cq,
-//       memory_object_holder &src,
-//       memory_object_holder &dest,
-//       size_t offset,
-//       py::object py_orig,
-//       py::object py_reg,
-//       py::object py_wait_for
-//       )
-//   {
-//     PYOPENCL_PARSE_WAIT_FOR;
-//     COPY_PY_COORD_TRIPLE(orig);
-//     COPY_PY_REGION_TRIPLE(reg);
-
-//     cl_event evt;
-//     PYOPENCL_RETRY_IF_MEM_ERROR(
-//       PYOPENCL_CALL_GUARDED(clEnqueueCopyBufferToImage, (
-//             cq.data(), src.data(), dest.data(),
-//             offset, orig, reg,
-//             PYOPENCL_WAITLIST_ARGS, &evt
-//             ));
-//       );
-//     PYOPENCL_RETURN_NEW_EVENT(evt);
-//   }
-
-// }}}
-
 }
 
 // c wrapper
@@ -252,3 +197,43 @@ enqueue_fill_image(clobj_t *evt, clobj_t _queue, clobj_t mem,
         });
 }
 #endif
+
+// {{{ image transfers
+
+error*
+enqueue_copy_image_to_buffer(clobj_t *evt, clobj_t _queue, clobj_t _src,
+                             clobj_t _dst, const size_t *_orig, size_t orig_l,
+                             const size_t *_reg, size_t reg_l, size_t offset,
+                             const clobj_t *_wait_for, uint32_t num_wait_for)
+{
+    auto queue = static_cast<command_queue*>(_queue);
+    auto src = static_cast<image*>(_src);
+    auto dst = static_cast<buffer*>(_dst);
+    const auto wait_for = buf_from_class<event>(_wait_for, num_wait_for);
+    ConstBuffer<size_t, 3> orig(_orig, orig_l);
+    ConstBuffer<size_t, 3> reg(_reg, reg_l, 1);
+    return c_handle_retry_mem_error([&] {
+            pyopencl_call_guarded(clEnqueueCopyImageToBuffer, queue, src, dst,
+                                  orig, reg, offset, wait_for, event_out(evt));
+        });
+}
+
+error*
+enqueue_copy_buffer_to_image(clobj_t *evt, clobj_t _queue, clobj_t _src,
+                             clobj_t _dst, size_t offset, const size_t *_orig,
+                             size_t orig_l, const size_t *_reg, size_t reg_l,
+                             const clobj_t *_wait_for, uint32_t num_wait_for)
+{
+    auto queue = static_cast<command_queue*>(_queue);
+    auto src = static_cast<buffer*>(_src);
+    auto dst = static_cast<image*>(_dst);
+    const auto wait_for = buf_from_class<event>(_wait_for, num_wait_for);
+    ConstBuffer<size_t, 3> orig(_orig, orig_l);
+    ConstBuffer<size_t, 3> reg(_reg, reg_l, 1);
+    return c_handle_retry_mem_error([&] {
+            pyopencl_call_guarded(clEnqueueCopyBufferToImage, queue, src, dst,
+                                  offset, orig, reg, wait_for, event_out(evt));
+        });
+}
+
+// }}}