diff --git a/config/config.exs b/config/config.exs
index 02bfa3191..9f125f79e 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -66,10 +66,11 @@ config :mime, :types, %{
 config :mobilizon, Mobilizon.Web.Upload,
   uploader: Mobilizon.Web.Upload.Uploader.Local,
   filters: [
-    Mobilizon.Web.Upload.Filter.Dedupe,
     Mobilizon.Web.Upload.Filter.AnalyzeMetadata,
     Mobilizon.Web.Upload.Filter.Resize,
-    Mobilizon.Web.Upload.Filter.Optimize
+    Mobilizon.Web.Upload.Filter.Optimize,
+    Mobilizon.Web.Upload.Filter.BlurHash,
+    Mobilizon.Web.Upload.Filter.Dedupe
   ],
   allow_list_mime_types: ["image/gif", "image/jpeg", "image/png", "image/webp"],
   link_name: true,
diff --git a/lib/web/upload/filter/analyze_metadata.ex b/lib/web/upload/filter/analyze_metadata.ex
index cb7acbba9..ea12fb487 100644
--- a/lib/web/upload/filter/analyze_metadata.ex
+++ b/lib/web/upload/filter/analyze_metadata.ex
@@ -20,13 +20,7 @@ defmodule Mobilizon.Web.Upload.Filter.AnalyzeMetadata do
       |> Mogrify.open()
       |> Mogrify.verbose()
 
-    upload =
-      upload
-      |> Map.put(:width, image.width)
-      |> Map.put(:height, image.height)
-      |> Map.put(:blurhash, get_blurhash(file))
-
-    {:ok, :filtered, upload}
+    {:ok, :filtered, %Upload{upload | width: image.width, height: image.height}}
   rescue
     e in ErlangError ->
       Logger.warn("#{__MODULE__}: #{inspect(e)}")
@@ -34,14 +28,4 @@ defmodule Mobilizon.Web.Upload.Filter.AnalyzeMetadata do
   end
 
   def filter(_), do: {:ok, :noop}
-
-  defp get_blurhash(file) do
-    case :eblurhash.magick(to_charlist(file)) do
-      {:ok, blurhash} ->
-        to_string(blurhash)
-
-      _ ->
-        nil
-    end
-  end
 end
diff --git a/lib/web/upload/filter/blurhash.ex b/lib/web/upload/filter/blurhash.ex
new file mode 100644
index 000000000..b2454dea6
--- /dev/null
+++ b/lib/web/upload/filter/blurhash.ex
@@ -0,0 +1,31 @@
+defmodule Mobilizon.Web.Upload.Filter.BlurHash do
+  @moduledoc """
+  Computes blurhash from the upload
+  """
+  require Logger
+  alias Mobilizon.Web.Upload
+
+  @behaviour Mobilizon.Web.Upload.Filter
+
+  @spec filter(Upload.t()) ::
+          {:ok, :filtered, Upload.t()} | {:ok, :noop} | {:error, String.t()}
+  def filter(%Upload{tempfile: file, content_type: "image" <> _} = upload) do
+    {:ok, :filtered, %Upload{upload | blurhash: generate_blurhash(file)}}
+  rescue
+    e in ErlangError ->
+      Logger.warn("#{__MODULE__}: #{inspect(e)}")
+      {:ok, :noop}
+  end
+
+  def filter(_), do: {:ok, :noop}
+
+  defp generate_blurhash(file) do
+    case :eblurhash.magick(to_charlist(file)) do
+      {:ok, blurhash} ->
+        to_string(blurhash)
+
+      _ ->
+        nil
+    end
+  end
+end
diff --git a/lib/web/upload/upload.ex b/lib/web/upload/upload.ex
index 13169ddc7..16b2f389b 100644
--- a/lib/web/upload/upload.ex
+++ b/lib/web/upload/upload.ex
@@ -62,9 +62,10 @@ defmodule Mobilizon.Web.Upload do
           path: String.t(),
           size: integer(),
           width: integer(),
-          height: integer()
+          height: integer(),
+          blurhash: String.t()
         }
-  defstruct [:id, :name, :tempfile, :content_type, :path, :size, :width, :height]
+  defstruct [:id, :name, :tempfile, :content_type, :path, :size, :width, :height, :blurhash]
 
   @spec store(source, options :: [option()]) :: {:ok, map()} | {:error, any()}
   def store(upload, opts \\ []) do