diff --git a/src/tag/Handler.cxx b/src/tag/Handler.cxx
index 137c221a0..0699f0996 100644
--- a/src/tag/Handler.cxx
+++ b/src/tag/Handler.cxx
@@ -35,6 +35,11 @@ NullTagHandler::OnPair(StringView, StringView) noexcept
 {
 }
 
+void
+NullTagHandler::OnPicture(const char *, ConstBuffer<void>) noexcept
+{
+}
+
 void
 NullTagHandler::OnAudioFormat(gcc_unused AudioFormat af) noexcept
 {
diff --git a/src/tag/Handler.hxx b/src/tag/Handler.hxx
index 4b5118f1b..e5aad97ff 100644
--- a/src/tag/Handler.hxx
+++ b/src/tag/Handler.hxx
@@ -24,6 +24,7 @@
 #include "Chrono.hxx"
 #include "util/Compiler.h"
 
+template<typename T> struct ConstBuffer;
 struct StringView;
 struct AudioFormat;
 class TagBuilder;
@@ -39,6 +40,7 @@ public:
 	static constexpr unsigned WANT_TAG = 0x2;
 	static constexpr unsigned WANT_PAIR = 0x4;
 	static constexpr unsigned WANT_AUDIO_FORMAT = 0x8;
+	static constexpr unsigned WANT_PICTURE = 0x10;
 
 	explicit TagHandler(unsigned _want_mask) noexcept
 		:want_mask(_want_mask) {}
@@ -62,6 +64,10 @@ public:
 		return want_mask & WANT_AUDIO_FORMAT;
 	}
 
+	bool WantPicture() const noexcept {
+		return want_mask & WANT_PICTURE;
+	}
+
 	/**
 	 * Declare the duration of a song.  Do not call
 	 * this when the duration could not be determined, because
@@ -99,6 +105,18 @@ public:
 	 * too expensive.
 	 */
 	virtual void OnAudioFormat(AudioFormat af) noexcept = 0;
+
+	/**
+	 * A picture has been read.
+	 *
+	 * This method will only be called if #WANT_PICTURE was enabled.
+	 *
+	 * @param mime_type an optional MIME type string
+	 * @param buffer the picture file contents; the buffer will be
+	 * invalidated after this method returns
+	 */
+	virtual void OnPicture(const char *mime_type,
+			       ConstBuffer<void> buffer) noexcept = 0;
 };
 
 class NullTagHandler : public TagHandler {
@@ -110,6 +128,8 @@ public:
 	void OnTag(TagType type, StringView value) noexcept override;
 	void OnPair(StringView key, StringView value) noexcept override;
 	void OnAudioFormat(AudioFormat af) noexcept override;
+	void OnPicture(const char *mime_type,
+		       ConstBuffer<void> buffer) noexcept override;
 };
 
 /**
diff --git a/test/read_tags.cxx b/test/read_tags.cxx
index 5fff8c683..e2f3c01a4 100644
--- a/test/read_tags.cxx
+++ b/test/read_tags.cxx
@@ -49,7 +49,7 @@ class DumpTagHandler final : public NullTagHandler {
 
 public:
 	DumpTagHandler() noexcept
-		:NullTagHandler(WANT_DURATION|WANT_TAG|WANT_PAIR) {}
+		:NullTagHandler(WANT_DURATION|WANT_TAG|WANT_PAIR|WANT_PICTURE) {}
 
 	bool IsEmpty() const noexcept {
 		return empty;
@@ -74,6 +74,11 @@ public:
 	void OnAudioFormat(AudioFormat af) noexcept override {
 		printf("%s\n", ToString(af).c_str());
 	}
+
+	void OnPicture(const char *mime_type,
+		       ConstBuffer<void> buffer) noexcept override {
+		printf("picture mime='%s' size=%zu\n", mime_type, buffer.size);
+	}
 };
 
 int main(int argc, char **argv)