diff --git a/src/pixie.nim b/src/pixie.nim
index 3b8c5dd..c98d950 100644
--- a/src/pixie.nim
+++ b/src/pixie.nim
@@ -40,7 +40,7 @@ proc decodeImageDimensions*(
 proc decodeImage*(data: string): Image {.raises: [PixieError].} =
   ## Loads an image from memory.
   if data.len > 8 and data.readUint64(0) == cast[uint64](pngSignature):
-    newImage(decodePng(data))
+    decodePng(data).convertToImage()
   elif data.len > 2 and data.readUint16(0) == cast[uint16](jpegStartOfImage):
     decodeJpeg(data)
   elif data.len > 2 and data.readStr(0, 2) == bmpSignature:
@@ -51,7 +51,7 @@ proc decodeImage*(data: string): Image {.raises: [PixieError].} =
   elif data.len > 6 and data.readStr(0, 6) in gifSignatures:
     decodeGif(data)
   elif data.len > (14+8) and data.readStr(0, 4) == qoiSignature:
-    newImage(decodeQoi(data))
+    decodeQoi(data).convertToImage()
   elif data.len > 9 and data.readStr(0, 2) in ppmSignatures:
     decodePpm(data)
   else:
@@ -60,7 +60,7 @@ proc decodeImage*(data: string): Image {.raises: [PixieError].} =
 proc decodeMask*(data: string): Mask {.raises: [PixieError].} =
   ## Loads a mask from memory.
   if data.len > 8 and data.readUint64(0) == cast[uint64](pngSignature):
-    newMask(newImage(decodePng(data)))
+    newMask(decodePng(data).convertToImage())
   else:
     raise newException(PixieError, "Unsupported mask file format")
 
diff --git a/src/pixie/fileformats/png.nim b/src/pixie/fileformats/png.nim
index 7f2f717..7cc98e3 100644
--- a/src/pixie/fileformats/png.nim
+++ b/src/pixie/fileformats/png.nim
@@ -338,10 +338,24 @@ proc decodeImageData(
     discard # Not possible, parseHeader validates
 
 proc newImage*(png: Png): Image {.raises: [PixieError].} =
+  ## Creates a new Image from the PNG.
   result = newImage(png.width, png.height)
   copyMem(result.data[0].addr, png.data[0].addr, png.data.len * 4)
   result.data.toPremultipliedAlpha()
 
+proc convertToImage*(png: Png): Image {.raises: [].} =
+  ## Converts a PNG into an Image by moving the data. This is faster but can
+  ## only be done once.
+  type Movable = ref object
+    width, height, channels: int
+    data: seq[ColorRGBX]
+
+  result = Image()
+  result.width = png.width
+  result.height = png.height
+  result.data = move cast[Movable](png).data
+  result.data.toPremultipliedAlpha()
+
 proc decodePngDimensions*(
   data: pointer, len: int
 ): ImageDimensions {.raises: [PixieError].} =
diff --git a/src/pixie/fileformats/qoi.nim b/src/pixie/fileformats/qoi.nim
index 1d6fa4e..5395f6b 100644
--- a/src/pixie/fileformats/qoi.nim
+++ b/src/pixie/fileformats/qoi.nim
@@ -30,11 +30,25 @@ proc hash(p: ColorRGBA): int =
   (p.r.int * 3 + p.g.int * 5 + p.b.int * 7 + p.a.int * 11) mod indexLen
 
 proc newImage*(qoi: Qoi): Image =
-  ## Converts raw QOI data to `Image`.
+  ## Creates a new Image from the QOI.
   result = newImage(qoi.width, qoi.height)
   copyMem(result.data[0].addr, qoi.data[0].addr, qoi.data.len * 4)
   result.data.toPremultipliedAlpha()
 
+proc convertToImage*(qoi: Qoi): Image {.raises: [].} =
+  ## Converts a QOI into an Image by moving the data. This is faster but can
+  ## only be done once.
+  type Movable = ref object
+    width, height, channels: int
+    colorspace: Colorspace
+    data: seq[ColorRGBX]
+
+  result = Image()
+  result.width = qoi.width
+  result.height = qoi.height
+  result.data = move cast[Movable](qoi).data
+  result.data.toPremultipliedAlpha()
+
 proc decodeQoi*(data: string): Qoi {.raises: [PixieError].} =
   ## Decompress QOI file format data.
   if data.len <= 14 or data[0 .. 3] != qoiSignature:
diff --git a/tests/benchmark_png.nim b/tests/benchmark_png.nim
index 81fcf76..39f2bbc 100644
--- a/tests/benchmark_png.nim
+++ b/tests/benchmark_png.nim
@@ -13,12 +13,12 @@ block:
   timeIt "pixie decode":
     discard decodePng(data)
 
+  timeIt "pixie decode + alpha":
+    discard decodePng(data).convertToImage()
+
   timeIt "pixie encode":
     discard encodePng(decodedPng)
 
-  timeIt "pixie decode + alpha":
-    discard newImage(decodePng(data))
-
   timeIt "pixie encode + alpha":
     discard encodePng(decodedImage)
 
@@ -55,9 +55,9 @@ block:
 
 block:
   timeIt "cairo decode":
-    discard imageSurfaceCreateFromPng(filePath)
+    discard imageSurfaceCreateFromPng(filePath.cstring)
 
-  let decoded = imageSurfaceCreateFromPng(filePath)
+  let decoded = imageSurfaceCreateFromPng(filePath.cstring)
   timeIt "cairo encode":
     var write: WriteFunc =
       proc(closure: pointer, data: cstring, len: int32): Status {.cdecl.} =