diff --git a/.dockerignore b/.dockerignore
index 0cab07a8576857c798959306d75cc30a29e6aafe..7e4ec6ee40a4c3a167e4149cc8690cf0f96fcac7 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -9,6 +9,7 @@
 /ipfs
 /dev/conduit-db
 /dev/psql
+/vcpkg
 
 # Generated files
 assets.bin.go
diff --git a/.gitignore b/.gitignore
index 0cab07a8576857c798959306d75cc30a29e6aafe..7e4ec6ee40a4c3a167e4149cc8690cf0f96fcac7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@
 /ipfs
 /dev/conduit-db
 /dev/psql
+/vcpkg
 
 # Generated files
 assets.bin.go
diff --git a/Dockerfile b/Dockerfile
index 781a421315687e7f56c31e52177bdfec661f5393..bfda3d7f5bf453a8b777277525c9ce2f7d7c8978 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -3,7 +3,7 @@
 FROM golang:1.20-alpine AS builder
 
 # Install build dependencies
-RUN apk add --no-cache git musl-dev dos2unix build-base
+RUN apk add --no-cache git musl-dev dos2unix build-base libde265-dev libheif-dev
 
 WORKDIR /opt
 COPY . /opt
diff --git a/go.mod b/go.mod
index 3bd1a2b34acdaeb153bd499e3fc3030449dee400..2a591c3a691074148d0d3152b5f6d06dc2e58dd2 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,6 @@ go 1.20
 require (
 	github.com/DavidHuie/gomigrate v0.0.0-20190826182718-4adc4b3de142
 	github.com/PuerkitoBio/goquery v1.8.1
-	github.com/adrium/goheif v0.0.0-20230113233934-ca402e77a786
 	github.com/alioygur/is v1.0.3
 	github.com/bep/debounce v1.2.1
 	github.com/bwmarrin/snowflake v0.3.0
@@ -54,6 +53,7 @@ require (
 	github.com/redis/go-redis/v9 v9.1.0
 	github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
 	github.com/stretchr/testify v1.8.4
+	github.com/strukturag/libheif v1.16.2
 	github.com/t2bot/go-singleflight-streams v0.0.6-0.20230825030520-3269fb2864dd
 	github.com/t2bot/go-typed-singleflight v0.0.3
 	github.com/testcontainers/testcontainers-go v0.23.0
@@ -115,7 +115,6 @@ require (
 	github.com/prometheus/common v0.44.0 // indirect
 	github.com/prometheus/procfs v0.11.1 // indirect
 	github.com/rs/xid v1.5.0 // indirect
-	github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // indirect
 	github.com/smartystreets/assertions v1.0.0 // indirect
 	golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
 	golang.org/x/mod v0.12.0 // indirect
diff --git a/go.sum b/go.sum
index c32496892d213e8c4dabfbf77cd20a3543bf1ffe..2d6aacbae6803d4b3a8b5d9fc6be2574e7559a76 100644
--- a/go.sum
+++ b/go.sum
@@ -14,8 +14,6 @@ github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5
 github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek=
 github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
 github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
-github.com/adrium/goheif v0.0.0-20230113233934-ca402e77a786 h1:zvgtcRb2B5gynWjm+Fc9oJZPHXwmcgyH0xCcNm6Rmo4=
-github.com/adrium/goheif v0.0.0-20230113233934-ca402e77a786/go.mod h1:aKVJoQ0cc9K5Xb058XSnnAxXLliR97qbSqWBlm5ca1E=
 github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
 github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
 github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw=
@@ -331,8 +329,6 @@ github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
 github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
 github.com/rubyist/circuitbreaker v2.2.1+incompatible h1:KUKd/pV8Geg77+8LNDwdow6rVCAYOp8+kHUyFvL6Mhk=
 github.com/rubyist/circuitbreaker v2.2.1+incompatible/go.mod h1:Ycs3JgJADPuzJDwffe12k6BZT8hxVi6lFK+gWYJLN4A=
-github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc=
-github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
 github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
 github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
@@ -361,6 +357,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/strukturag/libheif v1.16.2 h1:wCgk8RhYopsFsg73misRH7HLlKflrVBYyIcIcxd/Dr0=
+github.com/strukturag/libheif v1.16.2/go.mod h1:E/PNRlmVtrtj9j2AvBZlrO4dsBDu6KfwDZn7X1Ce8Ks=
 github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
 github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
 github.com/t2bot/go-singleflight-streams v0.0.6-0.20230825030520-3269fb2864dd h1:rDXR2R4X4lgNQlp2wq5Gb28+3xtvbnp7xi8CJnmFAc4=
diff --git a/thumbnailing/i/heif.go b/thumbnailing/i/heif.go
index c377ed65e3967d154bf522740a4fdd227db8fb0f..e8baad552ff776e6d3c38a296e130c1646aa98f2 100644
--- a/thumbnailing/i/heif.go
+++ b/thumbnailing/i/heif.go
@@ -1,10 +1,10 @@
 package i
 
 import (
-	"errors"
+	"image"
 	"io"
 
-	"github.com/adrium/goheif"
+	_ "github.com/strukturag/libheif/go/heif"
 	"github.com/turt2live/matrix-media-repo/common/rcontext"
 	"github.com/turt2live/matrix-media-repo/thumbnailing/m"
 )
@@ -25,20 +25,17 @@ func (d heifGenerator) matches(img io.Reader, contentType string) bool {
 }
 
 func (d heifGenerator) GetOriginDimensions(b io.Reader, contentType string, ctx rcontext.RequestContext) (bool, int, int, error) {
-	i, err := goheif.DecodeConfig(b)
+	cfg, _, err := image.DecodeConfig(b)
 	if err != nil {
 		return false, 0, 0, err
 	}
-	return true, i.Width, i.Height, nil
+	return true, cfg.Width, cfg.Height, nil
 }
 
 func (d heifGenerator) GenerateThumbnail(b io.Reader, contentType string, width int, height int, method string, animated bool, ctx rcontext.RequestContext) (*m.Thumbnail, error) {
-	// Use more memory, but prevent crashes
-	goheif.SafeEncoding = true
-
-	src, err := goheif.Decode(b)
+	src, _, err := image.Decode(b)
 	if err != nil {
-		return nil, errors.New("heif: error decoding thumbnail: " + err.Error())
+		return nil, err
 	}
 
 	return pngGenerator{}.GenerateThumbnailOf(src, width, height, method, ctx)