add support for new PICTURE metadata block
diff --git a/src/libFLAC++/metadata.cpp b/src/libFLAC++/metadata.cpp
index fc55703..30ca841 100644
--- a/src/libFLAC++/metadata.cpp
+++ b/src/libFLAC++/metadata.cpp
@@ -68,6 +68,9 @@
 					case FLAC__METADATA_TYPE_CUESHEET:
 						ret = new CueSheet(object, /*copy=*/false);
 						break;
+					case FLAC__METADATA_TYPE_PICTURE:
+						ret = new Picture(object, /*copy=*/false);
+						break;
 					default:
 						ret = new Unknown(object, /*copy=*/false);
 						break;
@@ -87,6 +90,7 @@
 			const SeekTable *seektable = dynamic_cast<const SeekTable *>(object);
 			const VorbisComment *vorbiscomment = dynamic_cast<const VorbisComment *>(object);
 			const CueSheet *cuesheet = dynamic_cast<const CueSheet *>(object);
+			const Picture *picture = dynamic_cast<const Picture *>(object);
 			const Unknown *unknown = dynamic_cast<const Unknown *>(object);
 
 			if(0 != streaminfo)
@@ -101,6 +105,8 @@
 				return new VorbisComment(*vorbiscomment);
 			else if(0 != cuesheet)
 				return new CueSheet(*cuesheet);
+			else if(0 != picture)
+				return new Picture(*picture);
 			else if(0 != unknown)
 				return new Unknown(*unknown);
 			else {
@@ -1015,6 +1021,111 @@
 
 
 		//
+		// Picture
+		//
+
+		Picture::Picture():
+		Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE), /*copy=*/false)
+		{ }
+
+		Picture::~Picture()
+		{ }
+
+		::FLAC__StreamMetadata_Picture_Type Picture::get_type() const
+		{
+			FLAC__ASSERT(is_valid());
+			return object_->data.picture.type;
+		}
+
+		const char *Picture::get_mime_type() const
+		{
+			FLAC__ASSERT(is_valid());
+			return object_->data.picture.mime_type;
+		}
+
+		const FLAC__byte *Picture::get_description() const
+		{
+			FLAC__ASSERT(is_valid());
+			return object_->data.picture.description;
+		}
+
+		FLAC__uint32 Picture::get_width() const
+		{
+			FLAC__ASSERT(is_valid());
+			return object_->data.picture.width;
+		}
+
+		FLAC__uint32 Picture::get_height() const
+		{
+			FLAC__ASSERT(is_valid());
+			return object_->data.picture.height;
+		}
+
+		FLAC__uint32 Picture::get_depth() const
+		{
+			FLAC__ASSERT(is_valid());
+			return object_->data.picture.depth;
+		}
+
+		FLAC__uint32 Picture::get_data_length() const
+		{
+			FLAC__ASSERT(is_valid());
+			return object_->data.picture.data_length;
+		}
+
+		const FLAC__byte *Picture::get_data() const
+		{
+			FLAC__ASSERT(is_valid());
+			return object_->data.picture.data;
+		}
+
+		void Picture::set_type(::FLAC__StreamMetadata_Picture_Type type)
+		{
+			FLAC__ASSERT(is_valid());
+			object_->data.picture.type = type;
+		}
+
+		bool Picture::set_mime_type(const char *string)
+		{
+			FLAC__ASSERT(is_valid());
+			// We can safely const_cast since copy=true
+			return (bool)::FLAC__metadata_object_picture_set_mime_type(object_, const_cast<char*>(string), /*copy=*/true);
+		}
+
+		bool Picture::set_description(const FLAC__byte *string)
+		{
+			FLAC__ASSERT(is_valid());
+			// We can safely const_cast since copy=true
+			return (bool)::FLAC__metadata_object_picture_set_description(object_, const_cast<FLAC__byte*>(string), /*copy=*/true);
+		}
+
+		void Picture::set_width(FLAC__uint32 value) const
+		{
+			FLAC__ASSERT(is_valid());
+			object_->data.picture.width = value;
+		}
+
+		void Picture::set_height(FLAC__uint32 value) const
+		{
+			FLAC__ASSERT(is_valid());
+			object_->data.picture.height = value;
+		}
+
+		void Picture::set_depth(FLAC__uint32 value) const
+		{
+			FLAC__ASSERT(is_valid());
+			object_->data.picture.depth = value;
+		}
+
+		bool Picture::set_data(const FLAC__byte *data, FLAC__uint32 data_length)
+		{
+			FLAC__ASSERT(is_valid());
+			// We can safely const_cast since copy=true
+			return (bool)::FLAC__metadata_object_picture_set_data(object_, const_cast<FLAC__byte*>(data), data_length, /*copy=*/true);
+		}
+
+
+		//
 		// Unknown
 		//
 
@@ -1124,6 +1235,36 @@
 				return false;
 		}
 
+		FLACPP_API bool get_picture(const char *filename, Picture *&picture, ::FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth)
+		{
+			FLAC__ASSERT(0 != filename);
+
+			::FLAC__StreamMetadata *object;
+
+			picture = 0;
+
+			if(::FLAC__metadata_get_picture(filename, &object, type, mime_type, description, max_width, max_height, max_depth)) {
+				picture = new Picture(object, /*copy=*/false);
+				return true;
+			}
+			else
+				return false;
+		}
+
+		FLACPP_API bool get_picture(const char *filename, Picture &picture, ::FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth)
+		{
+			FLAC__ASSERT(0 != filename);
+
+			::FLAC__StreamMetadata *object;
+
+			if(::FLAC__metadata_get_picture(filename, &object, type, mime_type, description, max_width, max_height, max_depth)) {
+				picture.assign(object, /*copy=*/false);
+				return true;
+			}
+			else
+				return false;
+		}
+
 
 		// ============================================================
 		//
diff --git a/src/libFLAC/format.c b/src/libFLAC/format.c
index 939ec67..bb5feeb 100644
--- a/src/libFLAC/format.c
+++ b/src/libFLAC/format.c
@@ -104,6 +104,14 @@
 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN = 7+258*8; /* bits */
 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* bits */
 
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN = 32; /* bits */
+
 FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */
 FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */
 FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */
@@ -168,7 +176,32 @@
 	"APPLICATION",
 	"SEEKTABLE",
 	"VORBIS_COMMENT",
-	"CUESHEET"
+	"CUESHEET",
+	"PICTURE"
+};
+
+FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[] = {
+	"Other",
+	"32x32 pixels 'file icon' (PNG only)",
+	"Other file icon",
+	"Cover (front)",
+	"Cover (back)",
+	"Leaflet page",
+	"Media (e.g. label side of CD)",
+	"Lead artist/lead performer/soloist",
+	"Artist/performer",
+	"Conductor",
+	"Band/Orchestra",
+	"Composer",
+	"Lyricist/text writer",
+	"Recording Location",
+	"During recording",
+	"During performance",
+	"Movie/video screen capture",
+	"A bright coloured fish",
+	"Illustration",
+	"Band/artist logotype",
+	"Publisher/Studio logotype"
 };
 
 FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate)
@@ -437,6 +470,30 @@
 	return true;
 }
 
+FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Picture *picture, const char **violation)
+{
+	char *p;
+	FLAC__byte *b;
+
+	for(p = picture->mime_type; *p; p++) {
+		if(*p < 0x20 || *p > 0x7e) {
+			if(violation) *violation = "MIME type string must contain only printable ASCII characters (0x20-0x7e)";
+			return false;
+		}
+	}
+
+	for(b = picture->description; *b; ) {
+		unsigned n = utf8len_(b);
+		if(n == 0) {
+			if(violation) *violation = "description string must be valid UTF-8";
+			return false;
+		}
+		b += n;
+	}
+
+	return true;
+}
+
 /*
  * These routines are private to libFLAC
  */
diff --git a/src/libFLAC/include/private/metadata.h b/src/libFLAC/include/private/metadata.h
index 277d989..7d4b5d8 100644
--- a/src/libFLAC/include/private/metadata.h
+++ b/src/libFLAC/include/private/metadata.h
@@ -34,7 +34,12 @@
 
 #include "FLAC/metadata.h"
 
+/* WATCHOUT: all malloc()ed data in the block is free()ed; this may not
+ * be a consistent state (e.g. PICTURE) or equivalent to the initial
+ * state after FLAC__metadata_object_new()
+ */
 void FLAC__metadata_object_delete_data(FLAC__StreamMetadata *object);
+
 void FLAC__metadata_object_cuesheet_track_delete_data(FLAC__StreamMetadata_CueSheet_Track *object);
 
 #endif
diff --git a/src/libFLAC/metadata_iterators.c b/src/libFLAC/metadata_iterators.c
index 2ecb8b1..a1c699a 100644
--- a/src/libFLAC/metadata_iterators.c
+++ b/src/libFLAC/metadata_iterators.c
@@ -92,6 +92,7 @@
 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block);
 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track);
 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block);
+static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block);
 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length);
 
 static FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block);
@@ -104,6 +105,7 @@
 static FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block);
 static FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block);
 static FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block);
+static FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block);
 static FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length);
 
 static FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block);
@@ -274,6 +276,55 @@
 		cd->got_error = true;
 }
 
+FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth)
+{
+	FLAC__Metadata_SimpleIterator *it;
+	FLAC__uint64 max_area_seen = 0;
+	FLAC__uint64 max_depth_seen = 0;
+
+	FLAC__ASSERT(0 != filename);
+	FLAC__ASSERT(0 != picture);
+
+	*picture = 0;
+
+	it = FLAC__metadata_simple_iterator_new();
+	if(0 == it)
+		return false;
+	if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) {
+		FLAC__metadata_simple_iterator_delete(it);
+		return false;
+	}
+	do {
+		if(FLAC__metadata_simple_iterator_get_block_type(it) == FLAC__METADATA_TYPE_PICTURE) {
+			FLAC__StreamMetadata *obj = FLAC__metadata_simple_iterator_get_block(it);
+			FLAC__uint64 area = (FLAC__uint64)obj->data.picture.width * (FLAC__uint64)obj->data.picture.height;
+			/* check constraints */
+			if(
+				(type == (FLAC__StreamMetadata_Picture_Type)(-1) || type == obj->data.picture.type) &&
+				(mime_type == 0 || !strcmp(mime_type, obj->data.picture.mime_type)) &&
+				(description == 0 || !strcmp((const char *)description, (const char *)obj->data.picture.description)) &&
+				obj->data.picture.width <= max_width &&
+				obj->data.picture.height <= max_height &&
+				obj->data.picture.depth <= max_depth &&
+				(area > max_area_seen || (area == max_area_seen && obj->data.picture.depth > max_depth_seen))
+			) {
+				if(*picture)
+					FLAC__metadata_object_delete(*picture);
+				*picture = obj;
+				max_area_seen = area;
+				max_depth_seen = obj->data.picture.depth;
+			}
+			else {
+				FLAC__metadata_object_delete(obj);
+			}
+		}
+	} while(FLAC__metadata_simple_iterator_next(it));
+
+	FLAC__metadata_simple_iterator_delete(it);
+
+	return (0 != *picture);
+}
+
 
 /****************************************************************************
  *
@@ -1851,6 +1902,8 @@
 			return read_metadata_block_data_vorbis_comment_cb_(handle, read_cb, &block->data.vorbis_comment);
 		case FLAC__METADATA_TYPE_CUESHEET:
 			return read_metadata_block_data_cuesheet_cb_(handle, read_cb, &block->data.cue_sheet);
+		case FLAC__METADATA_TYPE_PICTURE:
+			return read_metadata_block_data_picture_cb_(handle, read_cb, &block->data.picture);
 		default:
 			return read_metadata_block_data_unknown_cb_(handle, read_cb, &block->data.unknown, block->length);
 	}
@@ -1882,7 +1935,6 @@
 	return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
 }
 
-
 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length)
 {
 	(void)block; /* nothing to do; we don't care about reading the padding bytes */
@@ -1947,7 +1999,7 @@
 	const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
 	FLAC__byte buffer[4]; /* magic number is asserted below */
 
-	FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == 4);
+	FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == sizeof(buffer));
 
 	if(read_cb(buffer, 1, entry_length_len, handle) != entry_length_len)
 		return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
@@ -1979,7 +2031,7 @@
 	const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
 	FLAC__byte buffer[4]; /* magic number is asserted below */
 
-	FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == 4);
+	FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == sizeof(buffer));
 
 	if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, &(block->vendor_string))))
 		return status;
@@ -2117,6 +2169,85 @@
 	return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
 }
 
+FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cstring_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__byte **data, FLAC__uint32 *length, FLAC__uint32 length_len)
+{
+	FLAC__byte buffer[sizeof(FLAC__uint32)];
+
+	FLAC__ASSERT(0 != data);
+	FLAC__ASSERT(length_len%8 == 0);
+
+	length_len /= 8; /* convert to bytes */
+
+	FLAC__ASSERT(sizeof(buffer) >= length_len);
+
+	if(read_cb(buffer, 1, length_len, handle) != length_len)
+		return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+	*length = unpack_uint32_(buffer, length_len);
+
+	if(0 != *data)
+		free(*data);
+
+	if(0 == (*data = (FLAC__byte*)malloc(*length+1)))
+		return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
+
+	if(*length > 0) {
+		if(read_cb(*data, 1, *length, handle) != *length)
+			return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+	}
+
+	(*data)[*length] = '\0';
+
+	return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
+}
+
+FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block)
+{
+	FLAC__Metadata_SimpleIteratorStatus status;
+	FLAC__byte buffer[4]; /* asserted below that this is big enough */
+	FLAC__uint32 len;
+
+	FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8);
+	FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8);
+	FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8);
+	FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8);
+
+	FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_TYPE_LEN % 8 == 0);
+	len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN / 8;
+	if(read_cb(buffer, 1, len, handle) != len)
+		return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+	block->type = (FLAC__StreamMetadata_Picture_Type)unpack_uint32_(buffer, len);
+
+	if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, (FLAC__byte**)(&(block->mime_type)), &len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK)
+		return status;
+
+	if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, &(block->description), &len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK)
+		return status;
+
+	FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN % 8 == 0);
+	len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN / 8;
+	if(read_cb(buffer, 1, len, handle) != len)
+		return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+	block->width = unpack_uint32_(buffer, len);
+
+	FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN % 8 == 0);
+	len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN / 8;
+	if(read_cb(buffer, 1, len, handle) != len)
+		return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+	block->height = unpack_uint32_(buffer, len);
+
+	FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN % 8 == 0);
+	len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN / 8;
+	if(read_cb(buffer, 1, len, handle) != len)
+		return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+	block->depth = unpack_uint32_(buffer, len);
+
+	/* for convenience we use read_metadata_block_data_picture_cstring_cb_() even though it adds an extra terminating NUL we don't use */
+	if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, &(block->data), &(block->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK)
+		return status;
+
+	return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
+}
+
 FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length)
 {
 	if(block_length == 0) {
@@ -2193,6 +2324,8 @@
 			return write_metadata_block_data_vorbis_comment_cb_(handle, write_cb, &block->data.vorbis_comment);
 		case FLAC__METADATA_TYPE_CUESHEET:
 			return write_metadata_block_data_cuesheet_cb_(handle, write_cb, &block->data.cue_sheet);
+		case FLAC__METADATA_TYPE_PICTURE:
+			return write_metadata_block_data_picture_cb_(handle, write_cb, &block->data.picture);
 		default:
 			return write_metadata_block_data_unknown_cb_(handle, write_cb, &block->data.unknown, block->length);
 	}
@@ -2285,7 +2418,7 @@
 	const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
 	FLAC__byte buffer[4]; /* magic number is asserted below */
 
-	FLAC__ASSERT(max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == 4);
+	FLAC__ASSERT(max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == sizeof(buffer));
 
 	pack_uint32_little_endian_(block->vendor_string.length, buffer, entry_length_len);
 	if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len)
@@ -2402,6 +2535,73 @@
 	return true;
 }
 
+FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block)
+{
+	unsigned len;
+	size_t slen;
+	FLAC__byte buffer[4]; /* magic number is asserted below */
+
+	FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_TYPE_LEN%8);
+	FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN%8);
+	FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN%8);
+	FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN%8);
+	FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN%8);
+	FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN%8);
+	FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN%8);
+	FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8);
+	FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8);
+	FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8);
+	FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8);
+	FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8);
+	FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8);
+	FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8);
+
+	len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8;
+	pack_uint32_(block->type, buffer, len);
+	if(write_cb(buffer, 1, len, handle) != len)
+		return false;
+
+	len = FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8;
+	slen = strlen(block->mime_type);
+	pack_uint32_(slen, buffer, len);
+	if(write_cb(buffer, 1, len, handle) != len)
+		return false;
+	if(write_cb(block->mime_type, 1, slen, handle) != slen)
+		return false;
+
+	len = FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8;
+	slen = strlen((const char *)block->description);
+	pack_uint32_(slen, buffer, len);
+	if(write_cb(buffer, 1, len, handle) != len)
+		return false;
+	if(write_cb(block->description, 1, slen, handle) != slen)
+		return false;
+
+	len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8;
+	pack_uint32_(block->width, buffer, len);
+	if(write_cb(buffer, 1, len, handle) != len)
+		return false;
+
+	len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8;
+	pack_uint32_(block->height, buffer, len);
+	if(write_cb(buffer, 1, len, handle) != len)
+		return false;
+
+	len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8;
+	pack_uint32_(block->depth, buffer, len);
+	if(write_cb(buffer, 1, len, handle) != len)
+		return false;
+
+	len = FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8;
+	pack_uint32_(block->data_length, buffer, len);
+	if(write_cb(buffer, 1, len, handle) != len)
+		return false;
+	if(write_cb(block->data, 1, block->data_length, handle) != block->data_length)
+		return false;
+
+	return true;
+}
+
 FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length)
 {
 	if(write_cb(block->data, 1, block_length, handle) != block_length)
@@ -2556,7 +2756,7 @@
 	size_t n;
 	unsigned i;
 
-	FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == 4);
+	FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == sizeof(buffer));
 
 	/* skip any id3v2 tag */
 	errno = 0;
diff --git a/src/libFLAC/metadata_object.c b/src/libFLAC/metadata_object.c
index 6846c3b..7efa2cf 100644
--- a/src/libFLAC/metadata_object.c
+++ b/src/libFLAC/metadata_object.c
@@ -47,8 +47,17 @@
  *
  ***************************************************************************/
 
+/* copy bytes:
+ *  from = NULL  && bytes = 0
+ *       to <- NULL
+ *  from != NULL && bytes > 0
+ *       to <- copy of from
+ *  else ASSERT
+ * malloc error leaved 'to' unchanged
+ */
 static FLAC__bool copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes)
 {
+	FLAC__ASSERT(0 != to);
 	if(bytes > 0 && 0 != from) {
 		FLAC__byte *x;
 		if(0 == (x = (FLAC__byte*)malloc(bytes)))
@@ -64,6 +73,25 @@
 	return true;
 }
 
+#if 0 /* UNUSED */
+/* like copy_bytes_(), but free()s the original '*to' if the copy succeeds and the original '*to' is non-NULL */
+static FLAC__bool free_copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes)
+{
+	FLAC__byte *copy;
+	FLAC__ASSERT(0 != to);
+	if(copy_bytes_(&copy, from, bytes)) {
+		if(*to)
+			free(*to);
+		*to = copy;
+		return true;
+	}
+	else
+		return false;
+}
+#endif
+
+/* reallocate entry to 1 byte larger and add a terminating NUL */
+/* realloc() failure leaves entry unchanged */
 static FLAC__bool ensure_null_terminated_(FLAC__byte **entry, unsigned length)
 {
 	FLAC__byte *x = (FLAC__byte*)realloc(*entry, length+1);
@@ -76,6 +104,24 @@
 		return false;
 }
 
+/* copies the NUL-terminated C-string 'from' to '*to', leaving '*to'
+ * unchanged if malloc fails, free()ing the original '*to' if it
+ * succeeds and the original '*to' was not NULL
+ */
+static FLAC__bool copy_cstring_(char **to, const char *from)
+{
+	FLAC__ASSERT(to);
+	char *copy = strdup(from);
+	if(copy) {
+		if(*to)
+			free(*to);
+		*to = copy;
+		return true;
+	}
+	else
+		return false;
+}
+
 static FLAC__bool copy_vcentry_(FLAC__StreamMetadata_VorbisComment_Entry *to, const FLAC__StreamMetadata_VorbisComment_Entry *from)
 {
 	to->length = from->length;
@@ -417,18 +463,49 @@
 				*/
 				break;
 			case FLAC__METADATA_TYPE_VORBIS_COMMENT:
-				{
-					object->data.vorbis_comment.vendor_string.length = (unsigned)strlen(FLAC__VENDOR_STRING);
-					if(!copy_bytes_(&object->data.vorbis_comment.vendor_string.entry, (const FLAC__byte*)FLAC__VENDOR_STRING, object->data.vorbis_comment.vendor_string.length+1)) {
-						free(object);
-						return 0;
-					}
-					vorbiscomment_calculate_length_(object);
+				object->data.vorbis_comment.vendor_string.length = (unsigned)strlen(FLAC__VENDOR_STRING);
+				if(!copy_bytes_(&object->data.vorbis_comment.vendor_string.entry, (const FLAC__byte*)FLAC__VENDOR_STRING, object->data.vorbis_comment.vendor_string.length+1)) {
+					free(object);
+					return 0;
 				}
+				vorbiscomment_calculate_length_(object);
 				break;
 			case FLAC__METADATA_TYPE_CUESHEET:
 				cuesheet_calculate_length_(object);
 				break;
+			case FLAC__METADATA_TYPE_PICTURE:
+				object->length = (
+					FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+					FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* empty mime_type string */
+					FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* empty description string */
+					FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+					FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+					FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+					FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN +
+					0 /* no data */
+				) / 8;
+				object->data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER;
+				object->data.picture.mime_type = 0;
+				object->data.picture.description = 0;
+				/* calloc() took care of this for us:
+				object->data.picture.width = 0;
+				object->data.picture.height = 0;
+				object->data.picture.depth = 0;
+				object->data.picture.data_length = 0;
+				object->data.picture.data = 0;
+				*/
+				/* now initialize mime_type and description with empty strings to make things easier on the client */
+				if(!copy_cstring_(&object->data.picture.mime_type, "")) {
+					free(object);
+					return 0;
+				}
+				if(!copy_cstring_((char**)(&object->data.picture.description), "")) {
+					if(object->data.picture.mime_type)
+						free(object->data.picture.mime_type);
+					free(object);
+					return 0;
+				}
+				break;
 			default:
 				/* calloc() took care of this for us:
 				object->length = 0;
@@ -508,6 +585,25 @@
 					}
 				}
 				break;
+			case FLAC__METADATA_TYPE_PICTURE:
+				to->data.picture.type = object->data.picture.type;
+				if(!copy_cstring_(&to->data.picture.mime_type, object->data.picture.mime_type)) {
+					FLAC__metadata_object_delete(to);
+					return 0;
+				}
+				if(!copy_cstring_((char**)(&to->data.picture.description), (const char*)object->data.picture.description)) {
+					FLAC__metadata_object_delete(to);
+					return 0;
+				}
+				to->data.picture.width = object->data.picture.width;
+				to->data.picture.height = object->data.picture.height;
+				to->data.picture.depth = object->data.picture.depth;
+				to->data.picture.data_length = object->data.picture.data_length;
+				if(!copy_bytes_((&to->data.picture.data), object->data.picture.data, object->data.picture.data_length)) {
+					FLAC__metadata_object_delete(to);
+					return 0;
+				}
+				break;
 			default:
 				if(!copy_bytes_(&to->data.unknown.data, object->data.unknown.data, object->length)) {
 					FLAC__metadata_object_delete(to);
@@ -556,6 +652,20 @@
 				cuesheet_track_array_delete_(object->data.cue_sheet.tracks, object->data.cue_sheet.num_tracks);
 			}
 			break;
+		case FLAC__METADATA_TYPE_PICTURE:
+			if(0 != object->data.picture.mime_type) {
+				free(object->data.picture.mime_type);
+				object->data.picture.mime_type = 0;
+			}
+			if(0 != object->data.picture.description) {
+				free(object->data.picture.description);
+				object->data.picture.description = 0;
+			}
+			if(0 != object->data.picture.data) {
+				free(object->data.picture.data);
+				object->data.picture.data = 0;
+			}
+			break;
 		default:
 			if(0 != object->data.unknown.data) {
 				free(object->data.unknown.data);
@@ -710,6 +820,27 @@
 	return true;
 }
 
+static FLAC__bool compare_block_data_picture_(const FLAC__StreamMetadata_Picture *block1, const FLAC__StreamMetadata_Picture *block2)
+{
+	if(block1->type != block2->type)
+		return false;
+	if(block1->mime_type != block2->mime_type && (0 == block1->mime_type || 0 == block2->mime_type || strcmp(block1->mime_type, block2->mime_type)))
+		return false;
+	if(block1->description != block2->description && (0 == block1->description || 0 == block2->description || strcmp((const char *)block1->description, (const char *)block2->description)))
+		return false;
+	if(block1->width != block2->width)
+		return false;
+	if(block1->height != block2->height)
+		return false;
+	if(block1->depth != block2->depth)
+		return false;
+	if(block1->data_length != block2->data_length)
+		return false;
+	if(block1->data != block2->data && (0 == block1->data || 0 == block2->data || memcmp(block1->data, block2->data, block1->data_length)))
+		return false;
+	return true;
+}
+
 static FLAC__bool compare_block_data_unknown_(const FLAC__StreamMetadata_Unknown *block1, const FLAC__StreamMetadata_Unknown *block2, unsigned block_length)
 {
 	FLAC__ASSERT(0 != block1);
@@ -748,6 +879,8 @@
 			return compare_block_data_vorbiscomment_(&block1->data.vorbis_comment, &block2->data.vorbis_comment);
 		case FLAC__METADATA_TYPE_CUESHEET:
 			return compare_block_data_cuesheet_(&block1->data.cue_sheet, &block2->data.cue_sheet);
+		case FLAC__METADATA_TYPE_PICTURE:
+			return compare_block_data_picture_(&block1->data.picture, &block2->data.picture);
 		default:
 			return compare_block_data_unknown_(&block1->data.unknown, &block2->data.unknown, block1->length);
 	}
@@ -1553,3 +1686,99 @@
 		return (sum % 0xFF) << 24 | length << 8 | (FLAC__uint32)(cs->num_tracks-1);
 	}
 }
+
+FLAC_API FLAC__bool FLAC__metadata_object_picture_set_mime_type(FLAC__StreamMetadata *object, char *mime_type, FLAC__bool copy)
+{
+	char *old;
+	size_t old_length, new_length;
+
+	FLAC__ASSERT(0 != object);
+	FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
+	FLAC__ASSERT(0 != mime_type);
+
+	old = object->data.picture.mime_type;
+	old_length = old? strlen(old) : 0;
+	new_length = strlen(mime_type);
+
+	/* do the copy first so that if we fail we leave the object untouched */
+	if(copy) {
+		if(!copy_bytes_((FLAC__byte**)(&object->data.picture.mime_type), (FLAC__byte*)mime_type, new_length+1))
+			return false;
+	}
+	else {
+		object->data.picture.mime_type = mime_type;
+	}
+
+	if(0 != old)
+		free(old);
+
+	object->length -= old_length;
+	object->length += new_length;
+	return true;
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_picture_set_description(FLAC__StreamMetadata *object, FLAC__byte *description, FLAC__bool copy)
+{
+	FLAC__byte *old;
+	size_t old_length, new_length;
+
+	FLAC__ASSERT(0 != object);
+	FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
+	FLAC__ASSERT(0 != description);
+
+	old = object->data.picture.description;
+	old_length = old? strlen((const char *)old) : 0;
+	new_length = strlen((const char *)description);
+
+	/* do the copy first so that if we fail we leave the object untouched */
+	if(copy) {
+		if(!copy_bytes_(&object->data.picture.description, description, new_length+1))
+			return false;
+	}
+	else {
+		object->data.picture.description = description;
+	}
+
+	if(0 != old)
+		free(old);
+
+	object->length -= old_length;
+	object->length += new_length;
+	return true;
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_picture_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, FLAC__uint32 length, FLAC__bool copy)
+{
+	FLAC__byte *old;
+
+	FLAC__ASSERT(0 != object);
+	FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
+	FLAC__ASSERT((0 != data && length > 0) || (0 == data && length == 0 && copy == false));
+
+	old = object->data.picture.data;
+
+	/* do the copy first so that if we fail we leave the object untouched */
+	if(copy) {
+		if(!copy_bytes_(&object->data.picture.data, data, length))
+			return false;
+	}
+	else {
+		object->data.picture.data = data;
+	}
+
+	if(0 != old)
+		free(old);
+
+	object->length -= object->data.picture.data_length;
+	object->data.picture.data_length = length;
+	object->length += length;
+	return true;
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMetadata *object, const char **violation)
+{
+	FLAC__ASSERT(0 != object);
+	FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
+
+	return FLAC__format_picture_is_legal(&object->data.picture, violation);
+}
diff --git a/src/libFLAC/stream_decoder.c b/src/libFLAC/stream_decoder.c
index d64280d..802d495 100644
--- a/src/libFLAC/stream_decoder.c
+++ b/src/libFLAC/stream_decoder.c
@@ -99,6 +99,7 @@
 static FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length);
 static FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj);
 static FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj);
+static FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_Picture *obj);
 static FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder);
 static FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder);
 static FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FLAC__bool do_full_decode);
@@ -1296,6 +1297,10 @@
 					if(!read_metadata_cuesheet_(decoder, &block.data.cue_sheet))
 						return false;
 					break;
+				case FLAC__METADATA_TYPE_PICTURE:
+					if(!read_metadata_picture_(decoder, &block.data.picture))
+						return false;
+					break;
 				case FLAC__METADATA_TYPE_STREAMINFO:
 				case FLAC__METADATA_TYPE_SEEKTABLE:
 					FLAC__ASSERT(0);
@@ -1342,6 +1347,14 @@
 					if(0 != block.data.cue_sheet.tracks)
 						free(block.data.cue_sheet.tracks);
 					break;
+				case FLAC__METADATA_TYPE_PICTURE:
+					if(0 != block.data.picture.mime_type)
+						free(block.data.picture.mime_type);
+					if(0 != block.data.picture.description)
+						free(block.data.picture.description);
+					if(0 != block.data.picture.data)
+						free(block.data.picture.data);
+					break;
 				case FLAC__METADATA_TYPE_STREAMINFO:
 				case FLAC__METADATA_TYPE_SEEKTABLE:
 					FLAC__ASSERT(0);
@@ -1616,6 +1629,69 @@
 	return true;
 }
 
+FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_Picture *obj)
+{
+	FLAC__uint32 len;
+
+	FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input));
+
+	/* read type */
+	if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &obj->type, FLAC__STREAM_METADATA_PICTURE_TYPE_LEN, read_callback_, decoder))
+		return false; /* read_callback_ sets the state for us */
+
+	/* read MIME type */
+	if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN, read_callback_, decoder))
+		return false; /* read_callback_ sets the state for us */
+	if(0 == (obj->mime_type = (char*)malloc(len+1))) {
+		decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+		return false;
+	}
+	if(len > 0) {
+		if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)obj->mime_type, len, read_callback_, decoder))
+			return false; /* read_callback_ sets the state for us */
+	}
+	obj->mime_type[len] = '\0';
+
+	/* read description */
+	if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN, read_callback_, decoder))
+		return false; /* read_callback_ sets the state for us */
+	if(0 == (obj->description = (FLAC__byte*)malloc(len+1))) {
+		decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+		return false;
+	}
+	if(len > 0) {
+		if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, obj->description, len, read_callback_, decoder))
+			return false; /* read_callback_ sets the state for us */
+	}
+	obj->description[len] = '\0';
+
+	/* read width */
+	if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &obj->width, FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN, read_callback_, decoder))
+		return false; /* read_callback_ sets the state for us */
+
+	/* read height */
+	if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &obj->height, FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN, read_callback_, decoder))
+		return false; /* read_callback_ sets the state for us */
+
+	/* read depth */
+	if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &obj->depth, FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN, read_callback_, decoder))
+		return false; /* read_callback_ sets the state for us */
+
+	/* read data */
+	if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &(obj->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN, read_callback_, decoder))
+		return false; /* read_callback_ sets the state for us */
+	if(0 == (obj->data = (FLAC__byte*)malloc(obj->data_length))) {
+		decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+		return false;
+	}
+	if(obj->data_length > 0) {
+		if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, obj->data, obj->data_length, read_callback_, decoder))
+			return false; /* read_callback_ sets the state for us */
+	}
+
+	return true;
+}
+
 FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder)
 {
 	FLAC__uint32 x;
diff --git a/src/libFLAC/stream_encoder.c b/src/libFLAC/stream_encoder.c
index be11e5e..407346f 100644
--- a/src/libFLAC/stream_encoder.c
+++ b/src/libFLAC/stream_encoder.c
@@ -773,6 +773,10 @@
 			if(!FLAC__format_cuesheet_is_legal(&encoder->protected_->metadata[i]->data.cue_sheet, encoder->protected_->metadata[i]->data.cue_sheet.is_cd, /*violation=*/0))
 				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
 		}
+		else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_PICTURE) {
+			if(!FLAC__format_picture_is_legal(&encoder->protected_->metadata[i]->data.picture, /*violation=*/0))
+				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
+		}
 	}
 
 	encoder->private_->input_capacity = 0;
diff --git a/src/libFLAC/stream_encoder_framing.c b/src/libFLAC/stream_encoder_framing.c
index 87611b7..29bde9e 100644
--- a/src/libFLAC/stream_encoder_framing.c
+++ b/src/libFLAC/stream_encoder_framing.c
@@ -177,6 +177,33 @@
 				}
 			}
 			break;
+		case FLAC__METADATA_TYPE_PICTURE:
+			{
+				size_t len;
+				if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.picture.type, FLAC__STREAM_METADATA_PICTURE_TYPE_LEN))
+					return false;
+				len = strlen(metadata->data.picture.mime_type);
+				if(!FLAC__bitbuffer_write_raw_uint32(bb, len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN))
+					return false;
+				if(!FLAC__bitbuffer_write_byte_block(bb, (const FLAC__byte*)metadata->data.picture.mime_type, len))
+					return false;
+				len = strlen((const char *)metadata->data.picture.description);
+				if(!FLAC__bitbuffer_write_raw_uint32(bb, len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN))
+					return false;
+				if(!FLAC__bitbuffer_write_byte_block(bb, metadata->data.picture.description, len))
+					return false;
+				if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.picture.width, FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN))
+					return false;
+				if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.picture.height, FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN))
+					return false;
+				if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.picture.depth, FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN))
+					return false;
+				if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.picture.data_length, FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN))
+					return false;
+				if(!FLAC__bitbuffer_write_byte_block(bb, metadata->data.picture.data, metadata->data.picture.data_length))
+					return false;
+			}
+			break;
 		default:
 			if(!FLAC__bitbuffer_write_byte_block(bb, metadata->data.unknown.data, metadata->length))
 				return false;
diff --git a/src/metaflac/operations.c b/src/metaflac/operations.c
index a2a7d7f..aad872b 100644
--- a/src/metaflac/operations.c
+++ b/src/metaflac/operations.c
@@ -646,6 +646,18 @@
 				}
 			}
 			break;
+		case FLAC__METADATA_TYPE_PICTURE:
+			PPR; printf("  type: %u (%s)\n", block->data.picture.type, block->data.picture.type < FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED? FLAC__StreamMetadata_Picture_TypeString[block->data.picture.type] : "UNDEFINED");
+			PPR; printf("  MIME type: %s\n", block->data.picture.mime_type);
+			PPR; printf("  description: %s\n", block->data.picture.description);
+			PPR; printf("  width: %u\n", (unsigned)block->data.picture.width);
+			PPR; printf("  height: %u\n", (unsigned)block->data.picture.height);
+			PPR; printf("  depth: %u\n", (unsigned)block->data.picture.depth);
+			PPR; printf("  data length: %u\n", (unsigned)block->data.picture.data_length);
+			PPR; printf("  data:\n");
+			if(0 != block->data.picture.data)
+				hexdump(filename, block->data.picture.data, block->data.picture.data_length, "    ");
+			break;
 		default:
 			PPR; printf("  data contents:\n");
 			if(0 != block->data.unknown.data)
diff --git a/src/test_libFLAC++/decoders.cpp b/src/test_libFLAC++/decoders.cpp
index 486af3b..976342d 100644
--- a/src/test_libFLAC++/decoders.cpp
+++ b/src/test_libFLAC++/decoders.cpp
@@ -58,8 +58,8 @@
 	"Filename"
 };
 
-static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static ::FLAC__StreamMetadata *expected_metadata_sequence_[8];
+static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static ::FLAC__StreamMetadata *expected_metadata_sequence_[9];
 static unsigned num_expected_;
 static const char *flacfilename_ = "metadata.flac";
 static off_t flacfilesize_;
@@ -86,12 +86,12 @@
 
 static void init_metadata_blocks_()
 {
-	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static void free_metadata_blocks_()
 {
-	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static bool generate_file_()
@@ -105,6 +105,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!file_utils__generate_flacfile(flacfilename_, &flacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
@@ -710,6 +711,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -756,6 +758,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application1_;
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -785,6 +788,7 @@
 	expected_metadata_sequence_[num_expected_++] = &seektable_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -815,6 +819,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -851,6 +856,7 @@
 	expected_metadata_sequence_[num_expected_++] = &seektable_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -993,6 +999,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application1_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
diff --git a/src/test_libFLAC++/encoders.cpp b/src/test_libFLAC++/encoders.cpp
index 24845b8..94124b9 100644
--- a/src/test_libFLAC++/encoders.cpp
+++ b/src/test_libFLAC++/encoders.cpp
@@ -42,8 +42,8 @@
 	"Filename"
 };
 
-static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static ::FLAC__StreamMetadata *metadata_sequence_[] = { &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_ };
+static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static ::FLAC__StreamMetadata *metadata_sequence_[] = { &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_ };
 static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
 static const char *flacfilename_ = "metadata.flac";
 
@@ -73,12 +73,12 @@
 
 static void init_metadata_blocks_()
 {
-	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static void free_metadata_blocks_()
 {
-	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 class StreamEncoder : public FLAC::Encoder::Stream {
diff --git a/src/test_libFLAC++/metadata_manip.cpp b/src/test_libFLAC++/metadata_manip.cpp
index a813813..cf27b9e 100644
--- a/src/test_libFLAC++/metadata_manip.cpp
+++ b/src/test_libFLAC++/metadata_manip.cpp
@@ -106,6 +106,16 @@
 	return x;
 }
 
+static char *strdup_or_die_(const char *s)
+{
+	char *x = strdup(s);
+	if(0 == x) {
+		fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
+		exit(1);
+	}
+	return x;
+}
+
 /* functions for working with our metadata copy */
 
 static bool replace_in_our_metadata_(FLAC::Metadata::Prototype *block, unsigned position, bool copy)
@@ -474,10 +484,10 @@
 	printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
 }
 
-static bool generate_file_(FLAC__bool include_cuesheet)
+static bool generate_file_(FLAC__bool include_extras)
 {
-	::FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, padding;
-	::FLAC__StreamMetadata *metadata[3];
+	::FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
+	::FLAC__StreamMetadata *metadata[4];
 	unsigned i = 0, n = 0;
 
 	printf("generating FLAC file for test\n");
@@ -524,23 +534,54 @@
 			return die_("priming our metadata");
 	}
 
+	{
+		picture.is_last = false;
+		picture.type = ::FLAC__METADATA_TYPE_PICTURE;
+		picture.length =
+			(
+				FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+				FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
+				FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
+				FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+				FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+				FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+				FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
+			) / 8
+		;
+		picture.data.picture.type = ::FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
+		picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
+		picture.length += strlen(picture.data.picture.mime_type);
+		picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
+		picture.length += strlen((const char *)picture.data.picture.description);
+		picture.data.picture.width = 300;
+		picture.data.picture.height = 300;
+		picture.data.picture.depth = 24;
+		picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
+		picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
+		picture.length += picture.data.picture.data_length;
+	}
+
 	padding.is_last = true;
 	padding.type = ::FLAC__METADATA_TYPE_PADDING;
 	padding.length = 1234;
 
 	metadata[n++] = &vorbiscomment;
-	if (include_cuesheet)
+	if(include_extras) {
 		metadata[n++] = cuesheet;
+		metadata[n++] = &picture;
+	}
 	metadata[n++] = &padding;
 
 	FLAC::Metadata::StreamInfo s(&streaminfo);
 	FLAC::Metadata::VorbisComment v(&vorbiscomment);
 	FLAC::Metadata::CueSheet c(cuesheet, /*copy=*/false);
+	FLAC::Metadata::Picture pi(&picture);
 	FLAC::Metadata::Padding p(&padding);
 	if(
 		!insert_to_our_metadata_(&s, i++, /*copy=*/true) ||
 		!insert_to_our_metadata_(&v, i++, /*copy=*/true) ||
-		(include_cuesheet && !insert_to_our_metadata_(&v, i++, /*copy=*/true)) ||
+		(include_extras && !insert_to_our_metadata_(&c, i++, /*copy=*/true)) ||
+		(include_extras && !insert_to_our_metadata_(&pi, i++, /*copy=*/true)) ||
 		!insert_to_our_metadata_(&p, i++, /*copy=*/true)
 	)
 		return die_("priming our metadata");
@@ -616,7 +657,7 @@
 
 	printf("\n\n++++++ testing level 0 interface\n");
 
-	if(!generate_file_(/*include_cuesheet=*/true))
+	if(!generate_file_(/*include_extras=*/true))
 		return false;
 
 	if(!test_file_(flacfile_, /*ignore_metadata=*/true))
@@ -705,6 +746,38 @@
 		printf("OK\n");
 	}
 
+	{
+		printf("testing FLAC::Metadata::get_picture(Picture *&)... ");
+
+		FLAC::Metadata::Picture *picture = 0;
+
+		if(!FLAC::Metadata::get_picture(flacfile_, picture, /*type=*/(::FLAC__StreamMetadata_Picture_Type)(-1), /*mime_type=*/0, /*description=*/0, /*max_width=*/(unsigned)(-1), /*max_height=*/(unsigned)(-1), /*max_depth=*/(unsigned)(-1)))
+			return die_("during FLAC::Metadata::get_picture()");
+
+		/* check to see if some basic data matches (c.f. generate_file_()) */
+		if(picture->get_type () != ::FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
+			return die_("mismatch in picture->get_type ()");
+
+		printf("OK\n");
+
+		delete picture;
+	}
+
+	{
+		printf("testing FLAC::Metadata::get_picture(Picture &)... ");
+
+		FLAC::Metadata::Picture picture;
+
+		if(!FLAC::Metadata::get_picture(flacfile_, picture, /*type=*/(::FLAC__StreamMetadata_Picture_Type)(-1), /*mime_type=*/0, /*description=*/0, /*max_width=*/(unsigned)(-1), /*max_height=*/(unsigned)(-1), /*max_depth=*/(unsigned)(-1)))
+			return die_("during FLAC::Metadata::get_picture()");
+
+		/* check to see if some basic data matches (c.f. generate_file_()) */
+		if(picture.get_type () != ::FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
+			return die_("mismatch in picture->get_type ()");
+
+		printf("OK\n");
+	}
+
 	if(!remove_file_(flacfile_))
 		return false;
 
@@ -729,7 +802,7 @@
 	{
 	printf("simple iterator on read-only file\n");
 
-	if(!generate_file_(/*include_cuesheet=*/false))
+	if(!generate_file_(/*include_extras=*/false))
 		return false;
 
 	if(!change_stats_(flacfile_, /*read_only=*/true))
@@ -1394,7 +1467,7 @@
 
 	printf("generate read-only file\n");
 
-	if(!generate_file_(/*include_cuesheet=*/false))
+	if(!generate_file_(/*include_extras=*/false))
 		return false;
 
 	if(!change_stats_(flacfile_, /*read_only=*/true))
@@ -1949,7 +2022,7 @@
 
 	printf("generate file\n");
 
-	if(!generate_file_(/*include_cuesheet=*/false))
+	if(!generate_file_(/*include_extras=*/false))
 		return false;
 
 	printf("create chain\n");
diff --git a/src/test_libFLAC++/metadata_object.cpp b/src/test_libFLAC++/metadata_object.cpp
index 845fb1f..ccf41f5 100644
--- a/src/test_libFLAC++/metadata_object.cpp
+++ b/src/test_libFLAC++/metadata_object.cpp
@@ -22,7 +22,7 @@
 #include <stdlib.h> /* for malloc() */
 #include <string.h> /* for memcmp() */
 
-static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application_, vorbiscomment_, cuesheet_;
+static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application_, vorbiscomment_, cuesheet_, picture_;
 
 static bool die_(const char *msg)
 {
@@ -40,6 +40,16 @@
 	return x;
 }
 
+static char *strdup_or_die_(const char *s)
+{
+	char *x = strdup(s);
+	if(0 == x) {
+		fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
+		exit(1);
+	}
+	return x;
+}
+
 static bool index_is_equal_(const ::FLAC__StreamMetadata_CueSheet_Index &index, const ::FLAC__StreamMetadata_CueSheet_Index &indexcopy)
 {
 	if(indexcopy.offset != index.offset)
@@ -131,7 +141,7 @@
 	vorbiscomment_.data.vorbis_comment.comments[1].entry = (FLAC__byte*)malloc_or_die_(12+1);
 	memcpy(vorbiscomment_.data.vorbis_comment.comments[1].entry, "name3=value3", 12+1);
 
-	cuesheet_.is_last = true;
+	cuesheet_.is_last = false;
 	cuesheet_.type = ::FLAC__METADATA_TYPE_CUESHEET;
 	cuesheet_.length =
 		/* cuesheet guts */
@@ -186,6 +196,31 @@
 	cuesheet_.data.cue_sheet.tracks[1].indices = (FLAC__StreamMetadata_CueSheet_Index*)malloc_or_die_(cuesheet_.data.cue_sheet.tracks[1].num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index));
 	cuesheet_.data.cue_sheet.tracks[1].indices[0].offset = 0;
 	cuesheet_.data.cue_sheet.tracks[1].indices[0].number = 1;
+
+	picture_.is_last = true;
+	picture_.type = FLAC__METADATA_TYPE_PICTURE;
+	picture_.length =
+		(
+			FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+			FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
+			FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
+			FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+			FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+			FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+			FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
+		) / 8
+	;
+	picture_.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
+	picture_.data.picture.mime_type = strdup_or_die_("image/jpeg");
+	picture_.length += strlen(picture_.data.picture.mime_type);
+	picture_.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
+	picture_.length += strlen((const char *)picture_.data.picture.description);
+	picture_.data.picture.width = 300;
+	picture_.data.picture.height = 300;
+	picture_.data.picture.depth = 24;
+	picture_.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
+	picture_.data.picture.data_length = strlen((const char *)picture_.data.picture.data);
+	picture_.length += picture_.data.picture.data_length;
 }
 
 static void free_metadata_blocks_()
@@ -199,6 +234,9 @@
 	free(cuesheet_.data.cue_sheet.tracks[0].indices);
 	free(cuesheet_.data.cue_sheet.tracks[1].indices);
 	free(cuesheet_.data.cue_sheet.tracks);
+	free(picture_.data.picture.mime_type);
+	free(picture_.data.picture.description);
+	free(picture_.data.picture.data);
 }
 
 bool test_metadata_object_streaminfo()
@@ -223,7 +261,7 @@
 	{
 		FLAC::Metadata::StreamInfo blockcopy(block);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != block)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -237,7 +275,7 @@
 	{
 		FLAC::Metadata::StreamInfo blockcopy(streaminfo_);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != streaminfo_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -248,7 +286,7 @@
 	{
 		FLAC::Metadata::StreamInfo blockcopy(&streaminfo_);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != streaminfo_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -259,7 +297,7 @@
 	{
 		FLAC::Metadata::StreamInfo blockcopy(&streaminfo_, /*copy=*/true);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != streaminfo_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -271,7 +309,7 @@
 		::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&streaminfo_);
 		FLAC::Metadata::StreamInfo blockcopy(copy, /*copy=*/false);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != streaminfo_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -283,7 +321,7 @@
 		FLAC::Metadata::StreamInfo blockcopy;
 		blockcopy.assign(&streaminfo_, /*copy=*/true);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != streaminfo_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -296,7 +334,7 @@
 		FLAC::Metadata::StreamInfo blockcopy;
 		blockcopy.assign(copy, /*copy=*/false);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != streaminfo_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -307,7 +345,7 @@
 	{
 		FLAC::Metadata::StreamInfo blockcopy = block;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == block))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -318,7 +356,7 @@
 	{
 		FLAC::Metadata::StreamInfo blockcopy = streaminfo_;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == streaminfo_))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -329,7 +367,7 @@
 	{
 		FLAC::Metadata::StreamInfo blockcopy = &streaminfo_;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == streaminfo_))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -456,7 +494,7 @@
 	{
 		FLAC::Metadata::Padding blockcopy(block);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != block)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -470,7 +508,7 @@
 	{
 		FLAC::Metadata::Padding blockcopy(padding_);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != padding_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -481,7 +519,7 @@
 	{
 		FLAC::Metadata::Padding blockcopy(&padding_);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != padding_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -492,7 +530,7 @@
 	{
 		FLAC::Metadata::Padding blockcopy(&padding_, /*copy=*/true);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != padding_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -504,7 +542,7 @@
 		::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&padding_);
 		FLAC::Metadata::Padding blockcopy(copy, /*copy=*/false);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != padding_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -516,7 +554,7 @@
 		FLAC::Metadata::Padding blockcopy;
 		blockcopy.assign(&padding_, /*copy=*/true);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != padding_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -529,7 +567,7 @@
 		FLAC::Metadata::Padding blockcopy;
 		blockcopy.assign(copy, /*copy=*/false);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != padding_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -540,7 +578,7 @@
 	{
 		FLAC::Metadata::Padding blockcopy = block;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == block))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -551,7 +589,7 @@
 	{
 		FLAC::Metadata::Padding blockcopy = padding_;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == padding_))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -562,7 +600,7 @@
 	{
 		FLAC::Metadata::Padding blockcopy = &padding_;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == padding_))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -617,7 +655,7 @@
 	{
 		FLAC::Metadata::Application blockcopy(block);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != block)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -631,7 +669,7 @@
 	{
 		FLAC::Metadata::Application blockcopy(application_);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != application_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -642,7 +680,7 @@
 	{
 		FLAC::Metadata::Application blockcopy(&application_);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != application_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -653,7 +691,7 @@
 	{
 		FLAC::Metadata::Application blockcopy(&application_, /*copy=*/true);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != application_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -665,7 +703,7 @@
 		::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&application_);
 		FLAC::Metadata::Application blockcopy(copy, /*copy=*/false);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != application_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -677,7 +715,7 @@
 		FLAC::Metadata::Application blockcopy;
 		blockcopy.assign(&application_, /*copy=*/true);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != application_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -690,7 +728,7 @@
 		FLAC::Metadata::Application blockcopy;
 		blockcopy.assign(copy, /*copy=*/false);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != application_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -701,7 +739,7 @@
 	{
 		FLAC::Metadata::Application blockcopy = block;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == block))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -712,7 +750,7 @@
 	{
 		FLAC::Metadata::Application blockcopy = application_;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == application_))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -723,7 +761,7 @@
 	{
 		FLAC::Metadata::Application blockcopy = &application_;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == application_))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -787,7 +825,7 @@
 	{
 		FLAC::Metadata::SeekTable blockcopy(block);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != block)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -801,7 +839,7 @@
 	{
 		FLAC::Metadata::SeekTable blockcopy(seektable_);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != seektable_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -812,7 +850,7 @@
 	{
 		FLAC::Metadata::SeekTable blockcopy(&seektable_);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != seektable_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -823,7 +861,7 @@
 	{
 		FLAC::Metadata::SeekTable blockcopy(&seektable_, /*copy=*/true);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != seektable_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -835,7 +873,7 @@
 		::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&seektable_);
 		FLAC::Metadata::SeekTable blockcopy(copy, /*copy=*/false);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != seektable_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -847,7 +885,7 @@
 		FLAC::Metadata::SeekTable blockcopy;
 		blockcopy.assign(&seektable_, /*copy=*/true);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != seektable_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -860,7 +898,7 @@
 		FLAC::Metadata::SeekTable blockcopy;
 		blockcopy.assign(copy, /*copy=*/false);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != seektable_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -871,7 +909,7 @@
 	{
 		FLAC::Metadata::SeekTable blockcopy = block;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == block))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -882,7 +920,7 @@
 	{
 		FLAC::Metadata::SeekTable blockcopy = seektable_;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == seektable_))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -893,7 +931,7 @@
 	{
 		FLAC::Metadata::SeekTable blockcopy = &seektable_;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == seektable_))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1140,7 +1178,7 @@
 	{
 		FLAC::Metadata::VorbisComment blockcopy(block);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != block)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1154,7 +1192,7 @@
 	{
 		FLAC::Metadata::VorbisComment blockcopy(vorbiscomment_);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != vorbiscomment_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1165,7 +1203,7 @@
 	{
 		FLAC::Metadata::VorbisComment blockcopy(&vorbiscomment_);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != vorbiscomment_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1176,7 +1214,7 @@
 	{
 		FLAC::Metadata::VorbisComment blockcopy(&vorbiscomment_, /*copy=*/true);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != vorbiscomment_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1188,7 +1226,7 @@
 		::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&vorbiscomment_);
 		FLAC::Metadata::VorbisComment blockcopy(copy, /*copy=*/false);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != vorbiscomment_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1200,7 +1238,7 @@
 		FLAC::Metadata::VorbisComment blockcopy;
 		blockcopy.assign(&vorbiscomment_, /*copy=*/true);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != vorbiscomment_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1213,7 +1251,7 @@
 		FLAC::Metadata::VorbisComment blockcopy;
 		blockcopy.assign(copy, /*copy=*/false);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != vorbiscomment_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1224,7 +1262,7 @@
 	{
 		FLAC::Metadata::VorbisComment blockcopy = block;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == block))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1235,7 +1273,7 @@
 	{
 		FLAC::Metadata::VorbisComment blockcopy = vorbiscomment_;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == vorbiscomment_))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1246,7 +1284,7 @@
 	{
 		FLAC::Metadata::VorbisComment blockcopy = &vorbiscomment_;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == vorbiscomment_))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1518,7 +1556,7 @@
 	{
 		FLAC::Metadata::CueSheet blockcopy(block);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != block)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1532,7 +1570,7 @@
 	{
 		FLAC::Metadata::CueSheet blockcopy(cuesheet_);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != cuesheet_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1543,7 +1581,7 @@
 	{
 		FLAC::Metadata::CueSheet blockcopy(&cuesheet_);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != cuesheet_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1554,7 +1592,7 @@
 	{
 		FLAC::Metadata::CueSheet blockcopy(&cuesheet_, /*copy=*/true);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != cuesheet_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1566,7 +1604,7 @@
 		::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&cuesheet_);
 		FLAC::Metadata::CueSheet blockcopy(copy, /*copy=*/false);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != cuesheet_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1578,7 +1616,7 @@
 		FLAC::Metadata::CueSheet blockcopy;
 		blockcopy.assign(&cuesheet_, /*copy=*/true);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != cuesheet_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1591,7 +1629,7 @@
 		FLAC::Metadata::CueSheet blockcopy;
 		blockcopy.assign(copy, /*copy=*/false);
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(blockcopy != cuesheet_)
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1602,7 +1640,7 @@
 	{
 		FLAC::Metadata::CueSheet blockcopy = block;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == block))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1613,7 +1651,7 @@
 	{
 		FLAC::Metadata::CueSheet blockcopy = cuesheet_;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == cuesheet_))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1624,7 +1662,7 @@
 	{
 		FLAC::Metadata::CueSheet blockcopy = &cuesheet_;
 		if(!blockcopy.is_valid())
-			return die_("!block.is_valid()");
+			return die_("!blockcopy.is_valid()");
 		if(!(blockcopy == cuesheet_))
 			return die_("copy is not identical to original");
 		printf("OK\n");
@@ -1759,6 +1797,254 @@
 	return true;
 }
 
+bool test_metadata_object_picture()
+{
+	unsigned expected_length;
+
+	printf("testing class FLAC::Metadata::Picture\n");
+
+	printf("testing Picture::Picture()... ");
+	FLAC::Metadata::Picture block;
+	if(!block.is_valid())
+		return die_("!block.is_valid()");
+	expected_length = (
+		FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+		FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN +
+		FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN +
+		FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+		FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+		FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+		FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN
+	) / 8;
+	if(block.get_length() != expected_length) {
+		printf("FAILED, bad length, expected %u, got %u\n", expected_length, block.get_length());
+		return false;
+	}
+	printf("OK\n");
+
+	printf("testing Picture::Picture(const Picture &)... +\n");
+	printf("        Picture::operator!=(const Picture &)... ");
+	{
+		FLAC::Metadata::Picture blockcopy(block);
+		if(!blockcopy.is_valid())
+			return die_("!blockcopy.is_valid()");
+		if(blockcopy != block)
+			return die_("copy is not identical to original");
+		printf("OK\n");
+
+		printf("testing Picture::~Picture()... ");
+	}
+	printf("OK\n");
+
+	printf("testing Picture::Picture(const ::FLAC__StreamMetadata &)... +\n");
+	printf("        Picture::operator!=(const ::FLAC__StreamMetadata &)... ");
+	{
+		FLAC::Metadata::Picture blockcopy(picture_);
+		if(!blockcopy.is_valid())
+			return die_("!blockcopy.is_valid()");
+		if(blockcopy != picture_)
+			return die_("copy is not identical to original");
+		printf("OK\n");
+	}
+
+	printf("testing Picture::Picture(const ::FLAC__StreamMetadata *)... +\n");
+	printf("        Picture::operator!=(const ::FLAC__StreamMetadata *)... ");
+	{
+		FLAC::Metadata::Picture blockcopy(&picture_);
+		if(!blockcopy.is_valid())
+			return die_("!blockcopy.is_valid()");
+		if(blockcopy != picture_)
+			return die_("copy is not identical to original");
+		printf("OK\n");
+	}
+
+	printf("testing Picture::Picture(const ::FLAC__StreamMetadata *, copy=true)... +\n");
+	printf("        Picture::operator!=(const ::FLAC__StreamMetadata *)... ");
+	{
+		FLAC::Metadata::Picture blockcopy(&picture_, /*copy=*/true);
+		if(!blockcopy.is_valid())
+			return die_("!blockcopy.is_valid()");
+		if(blockcopy != picture_)
+			return die_("copy is not identical to original");
+		printf("OK\n");
+	}
+
+	printf("testing Picture::Picture(const ::FLAC__StreamMetadata *, copy=false)... +\n");
+	printf("        Picture::operator!=(const ::FLAC__StreamMetadata *)... ");
+	{
+		::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&picture_);
+		FLAC::Metadata::Picture blockcopy(copy, /*copy=*/false);
+		if(!blockcopy.is_valid())
+			return die_("!blockcopy.is_valid()");
+		if(blockcopy != picture_)
+			return die_("copy is not identical to original");
+		printf("OK\n");
+	}
+
+	printf("testing Picture::assign(const ::FLAC__StreamMetadata *, copy=true)... +\n");
+	printf("        Picture::operator!=(const ::FLAC__StreamMetadata *)... ");
+	{
+		FLAC::Metadata::Picture blockcopy;
+		blockcopy.assign(&picture_, /*copy=*/true);
+		if(!blockcopy.is_valid())
+			return die_("!blockcopy.is_valid()");
+		if(blockcopy != picture_)
+			return die_("copy is not identical to original");
+		printf("OK\n");
+	}
+
+	printf("testing Picture::assign(const ::FLAC__StreamMetadata *, copy=false)... +\n");
+	printf("        Picture::operator!=(const ::FLAC__StreamMetadata *)... ");
+	{
+		::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&picture_);
+		FLAC::Metadata::Picture blockcopy;
+		blockcopy.assign(copy, /*copy=*/false);
+		if(!blockcopy.is_valid())
+			return die_("!blockcopy.is_valid()");
+		if(blockcopy != picture_)
+			return die_("copy is not identical to original");
+		printf("OK\n");
+	}
+
+	printf("testing Picture::operator=(const Picture &)... +\n");
+	printf("        Picture::operator==(const Picture &)... ");
+	{
+		FLAC::Metadata::Picture blockcopy = block;
+		if(!blockcopy.is_valid())
+			return die_("!blockcopy.is_valid()");
+		if(!(blockcopy == block))
+			return die_("copy is not identical to original");
+		printf("OK\n");
+	}
+
+	printf("testing Picture::operator=(const ::FLAC__StreamMetadata &)... +\n");
+	printf("        Picture::operator==(const ::FLAC__StreamMetadata &)... ");
+	{
+		FLAC::Metadata::Picture blockcopy = picture_;
+		if(!blockcopy.is_valid())
+			return die_("!blockcopy.is_valid()");
+		if(!(blockcopy == picture_))
+			return die_("copy is not identical to original");
+		printf("OK\n");
+	}
+
+	printf("testing Picture::operator=(const ::FLAC__StreamMetadata *)... +\n");
+	printf("        Picture::operator==(const ::FLAC__StreamMetadata *)... ");
+	{
+		FLAC::Metadata::Picture blockcopy = &picture_;
+		if(!blockcopy.is_valid())
+			return die_("!blockcopy.is_valid()");
+		if(!(blockcopy == picture_))
+			return die_("copy is not identical to original");
+		printf("OK\n");
+	}
+
+	printf("testing Picture::get_type()... ");
+	if(block.get_type() != ::FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER)
+		return die_("value mismatch, expected ::FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER");
+	printf("OK\n");
+
+	printf("testing Picture::set_type()... +\n");
+	printf("        Picture::get_type()... ");
+	block.set_type(::FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA);
+	if(block.get_type() != ::FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA)
+		return die_("value mismatch, expected ::FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA");
+	printf("OK\n");
+
+	printf("testing Picture::set_mime_type()... ");
+	if(!block.set_mime_type("qmage/jpeg"))
+		return die_("returned false");
+	printf("OK\n");
+	picture_.data.picture.mime_type[0] = 'q';
+
+	printf("testing Picture::get_mime_type()... ");
+	if(0 != strcmp(block.get_mime_type(), picture_.data.picture.mime_type))
+		return die_("value mismatch");
+	printf("OK\n");
+
+	printf("testing Picture::set_description()... ");
+	if(!block.set_description((const FLAC__byte*)"qesc"))
+		return die_("returned false");
+	printf("OK\n");
+	picture_.data.picture.description[0] = 'q';
+
+	printf("testing Picture::get_description()... ");
+	if(0 != strcmp((const char *)block.get_description(), (const char *)picture_.data.picture.description))
+		return die_("value mismatch");
+	printf("OK\n");
+
+	printf("testing Picture::get_width()... ");
+	if(block.get_width() != 0)
+		return die_("value mismatch, expected 0");
+	printf("OK\n");
+
+	printf("testing Picture::set_width()... +\n");
+	printf("        Picture::get_width()... ");
+	block.set_width(400);
+	if(block.get_width() != 400)
+		return die_("value mismatch, expected 400");
+	printf("OK\n");
+
+	printf("testing Picture::get_height()... ");
+	if(block.get_height() != 0)
+		return die_("value mismatch, expected 0");
+	printf("OK\n");
+
+	printf("testing Picture::set_height()... +\n");
+	printf("        Picture::get_height()... ");
+	block.set_height(200);
+	if(block.get_height() != 200)
+		return die_("value mismatch, expected 200");
+	printf("OK\n");
+
+	printf("testing Picture::get_depth()... ");
+	if(block.get_depth() != 0)
+		return die_("value mismatch, expected 0");
+	printf("OK\n");
+
+	printf("testing Picture::set_depth()... +\n");
+	printf("        Picture::get_depth()... ");
+	block.set_depth(16);
+	if(block.get_depth() != 16)
+		return die_("value mismatch, expected 16");
+	printf("OK\n");
+
+	printf("testing Picture::get_data_length()... ");
+	if(block.get_data_length() != 0)
+		return die_("value mismatch, expected 0");
+	printf("OK\n");
+
+	printf("testing Picture::set_data()... ");
+	if(!block.set_data((const FLAC__byte*)"qOMEJPEGDATA", strlen("qOMEJPEGDATA")))
+		return die_("returned false");
+	printf("OK\n");
+	picture_.data.picture.data[0] = 'q';
+
+	printf("testing Picture::get_data()... ");
+	if(block.get_data_length() != picture_.data.picture.data_length)
+		return die_("length mismatch");
+	if(0 != memcmp(block.get_data(), picture_.data.picture.data, picture_.data.picture.data_length))
+		return die_("value mismatch");
+	printf("OK\n");
+
+	printf("testing FLAC::Metadata::clone(const FLAC::Metadata::Prototype *)... ");
+	FLAC::Metadata::Prototype *clone_ = FLAC::Metadata::clone(&block);
+	if(0 == clone_)
+		return die_("returned NULL");
+	if(0 == dynamic_cast<FLAC::Metadata::Picture *>(clone_))
+		return die_("downcast is NULL");
+	if(*dynamic_cast<FLAC::Metadata::Picture *>(clone_) != block)
+		return die_("clone is not identical");
+	printf("OK\n");
+	printf("testing Picture::~Picture()... ");
+	delete clone_;
+	printf("OK\n");
+
+
+	printf("PASSED\n\n");
+	return true;
+}
+
 bool test_metadata_object()
 {
 	printf("\n+++ libFLAC++ unit test: metadata objects\n\n");
@@ -1783,6 +2069,9 @@
 	if(!test_metadata_object_cuesheet())
 		return false;
 
+	if(!test_metadata_object_picture())
+		return false;
+
 	free_metadata_blocks_();
 
 	return true;
diff --git a/src/test_libFLAC/decoders.c b/src/test_libFLAC/decoders.c
index 1ac22d4..3765853 100644
--- a/src/test_libFLAC/decoders.c
+++ b/src/test_libFLAC/decoders.c
@@ -58,8 +58,8 @@
 	FLAC__bool error_occurred;
 } StreamDecoderClientData;
 
-static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static FLAC__StreamMetadata *expected_metadata_sequence_[8];
+static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static FLAC__StreamMetadata *expected_metadata_sequence_[9];
 static unsigned num_expected_;
 static const char *flacfilename_ = "metadata.flac";
 static off_t flacfilesize_;
@@ -86,12 +86,12 @@
 
 static void init_metadata_blocks_()
 {
-	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static void free_metadata_blocks_()
 {
-	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static FLAC__bool generate_file_()
@@ -105,6 +105,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!file_utils__generate_flacfile(flacfilename_, &flacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
@@ -627,6 +628,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -667,6 +669,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application1_;
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -692,6 +695,7 @@
 	expected_metadata_sequence_[num_expected_++] = &seektable_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -718,6 +722,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -748,6 +753,7 @@
 	expected_metadata_sequence_[num_expected_++] = &seektable_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -866,6 +872,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application1_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
diff --git a/src/test_libFLAC/encoders.c b/src/test_libFLAC/encoders.c
index 053695f..f3e9788 100644
--- a/src/test_libFLAC/encoders.c
+++ b/src/test_libFLAC/encoders.c
@@ -45,8 +45,8 @@
 	"Filename"
 };
 
-static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static FLAC__StreamMetadata *metadata_sequence_[] = { &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_ };
+static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static FLAC__StreamMetadata *metadata_sequence_[] = { &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_ };
 static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
 static const char *flacfilename_ = "metadata.flac";
 
@@ -76,12 +76,12 @@
 
 static void init_metadata_blocks_()
 {
-	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static void free_metadata_blocks_()
 {
-	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static FLAC__StreamEncoderWriteStatus stream_encoder_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
diff --git a/src/test_libFLAC/metadata_manip.c b/src/test_libFLAC/metadata_manip.c
index 21a8fa4..81885fd 100644
--- a/src/test_libFLAC/metadata_manip.c
+++ b/src/test_libFLAC/metadata_manip.c
@@ -100,6 +100,16 @@
 	return x;
 }
 
+static char *strdup_or_die_(const char *s)
+{
+	char *x = strdup(s);
+	if(0 == x) {
+		fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
+		exit(1);
+	}
+	return x;
+}
+
 /* functions for working with our metadata copy */
 
 static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
@@ -485,10 +495,10 @@
 	printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
 }
 
-static FLAC__bool generate_file_(FLAC__bool include_cuesheet)
+static FLAC__bool generate_file_(FLAC__bool include_extras)
 {
-	FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, padding;
-	FLAC__StreamMetadata *metadata[3];
+	FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
+	FLAC__StreamMetadata *metadata[4];
 	unsigned i = 0, n = 0;
 
 	printf("generating FLAC file for test\n");
@@ -535,19 +545,49 @@
 			return die_("priming our metadata");
 	}
 
+	{
+		picture.is_last = false;
+		picture.type = FLAC__METADATA_TYPE_PICTURE;
+		picture.length =
+			(
+				FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+				FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
+				FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
+				FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+				FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+				FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+				FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
+			) / 8
+		;
+		picture.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
+		picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
+		picture.length += strlen(picture.data.picture.mime_type);
+		picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
+		picture.length += strlen((const char *)picture.data.picture.description);
+		picture.data.picture.width = 300;
+		picture.data.picture.height = 300;
+		picture.data.picture.depth = 24;
+		picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
+		picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
+		picture.length += picture.data.picture.data_length;
+	}
+
 	padding.is_last = true;
 	padding.type = FLAC__METADATA_TYPE_PADDING;
 	padding.length = 1234;
 
 	metadata[n++] = &vorbiscomment;
-	if (include_cuesheet)
+	if(include_extras) {
 		metadata[n++] = cuesheet;
+		metadata[n++] = &picture;
+	}
 	metadata[n++] = &padding;
 
 	if(
 		!insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
 		!insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
-		(include_cuesheet && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
+		(include_extras && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
+		(include_extras && !insert_to_our_metadata_(&picture, i++, /*copy=*/true)) ||
 		!insert_to_our_metadata_(&padding, i++, /*copy=*/true)
 	)
 		return die_("priming our metadata");
@@ -627,10 +667,11 @@
 	FLAC__StreamMetadata streaminfo;
 	FLAC__StreamMetadata *tags = 0;
 	FLAC__StreamMetadata *cuesheet = 0;
+	FLAC__StreamMetadata *picture = 0;
 
 	printf("\n\n++++++ testing level 0 interface\n");
 
-	if(!generate_file_(/*include_cuesheet=*/true))
+	if(!generate_file_(/*include_extras=*/true))
 		return false;
 
 	if(!test_file_(flacfile_, decoder_metadata_callback_null_))
@@ -675,12 +716,25 @@
 
 	/* check to see if some basic data matches (c.f. generate_file_()) */
 	if(cuesheet->data.cue_sheet.lead_in != 123)
-		return die_("mismatch in cuesheet->data.vorbis_comment.num_comments");
+		return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
 
 	printf("OK\n");
 
 	FLAC__metadata_object_delete(cuesheet);
 
+	printf("testing FLAC__metadata_get_picture()... ");
+
+	if(!FLAC__metadata_get_picture(flacfile_, &picture, /*type=*/(FLAC__StreamMetadata_Picture_Type)(-1), /*mime_type=*/0, /*description=*/0, /*max_width=*/(unsigned)(-1), /*max_height=*/(unsigned)(-1), /*max_depth=*/(unsigned)(-1)))
+		return die_("during FLAC__metadata_get_picture()");
+
+	/* check to see if some basic data matches (c.f. generate_file_()) */
+	if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
+		return die_("mismatch in picture->data.picture.type");
+
+	printf("OK\n");
+
+	FLAC__metadata_object_delete(picture);
+
 	if(!remove_file_(flacfile_))
 		return false;
 
@@ -703,7 +757,7 @@
 
 	printf("simple iterator on read-only file\n");
 
-	if(!generate_file_(/*include_cuesheet=*/false))
+	if(!generate_file_(/*include_extras=*/false))
 		return false;
 
 	if(!change_stats_(flacfile_, /*read_only=*/true))
@@ -1362,7 +1416,7 @@
 
 	printf("generate read-only file\n");
 
-	if(!generate_file_(/*include_cuesheet=*/false))
+	if(!generate_file_(/*include_extras=*/false))
 		return false;
 
 	if(!change_stats_(flacfile_, /*read_only=*/true))
@@ -1875,7 +1929,7 @@
 
 	printf("generate file\n");
 
-	if(!generate_file_(/*include_cuesheet=*/false))
+	if(!generate_file_(/*include_extras=*/false))
 		return false;
 
 	printf("create chain\n");
diff --git a/src/test_libFLAC/metadata_object.c b/src/test_libFLAC/metadata_object.c
index 304df90..2939ed3 100644
--- a/src/test_libFLAC/metadata_object.c
+++ b/src/test_libFLAC/metadata_object.c
@@ -463,10 +463,43 @@
 	cs_calc_len_(block);
 }
 
+static void pi_set_mime_type(FLAC__StreamMetadata *block, const char *s)
+{
+	if(block->data.picture.mime_type) {
+		block->length -= strlen(block->data.picture.mime_type);
+		free(block->data.picture.mime_type);
+	}
+	block->data.picture.mime_type = strdup(s);
+	FLAC__ASSERT(block->data.picture.mime_type);
+	block->length += strlen(block->data.picture.mime_type);
+}
+
+static void pi_set_description(FLAC__StreamMetadata *block, const FLAC__byte *s)
+{
+	if(block->data.picture.description) {
+		block->length -= strlen((const char *)block->data.picture.description);
+		free(block->data.picture.description);
+	}
+	block->data.picture.description = (FLAC__byte*)strdup((const char *)s);
+	FLAC__ASSERT(block->data.picture.description);
+	block->length += strlen((const char *)block->data.picture.description);
+}
+
+static void pi_set_data(FLAC__StreamMetadata *block, const FLAC__byte *data, FLAC__uint32 len)
+{
+	if(block->data.picture.data) {
+		block->length -= block->data.picture.data_length;
+		free(block->data.picture.data);
+	}
+	block->data.picture.data = (FLAC__byte*)strdup((const char *)data);
+	FLAC__ASSERT(block->data.picture.data);
+	block->data.picture.data_length = len;
+	block->length += len;
+}
 
 FLAC__bool test_metadata_object()
 {
-	FLAC__StreamMetadata *block, *blockcopy, *vorbiscomment, *cuesheet;
+	FLAC__StreamMetadata *block, *blockcopy, *vorbiscomment, *cuesheet, *picture;
 	FLAC__StreamMetadata_SeekPoint seekpoint_array[14];
 	FLAC__StreamMetadata_VorbisComment_Entry entry;
 	FLAC__StreamMetadata_CueSheet_Index index;
@@ -1996,5 +2029,253 @@
 	printf("OK\n");
 
 
+	printf("testing PICTURE\n");
+
+	printf("testing FLAC__metadata_object_new()... ");
+	block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE);
+	if(0 == block) {
+		printf("FAILED, returned NULL\n");
+		return false;
+	}
+	expected_length = (
+		FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+		FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN +
+		FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN +
+		FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+		FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+		FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+		FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN
+	) / 8;
+	if(block->length != expected_length) {
+		printf("FAILED, bad length, expected %u, got %u\n", expected_length, block->length);
+		return false;
+	}
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_clone()... ");
+	picture = FLAC__metadata_object_clone(block);
+	if(0 == picture) {
+		printf("FAILED, returned NULL\n");
+		return false;
+	}
+	if(!mutils__compare_block(picture, block))
+		return false;
+	printf("OK\n");
+
+	pi_set_mime_type(picture, "image/png\t");
+	printf("testing FLAC__metadata_object_picture_set_mime_type(copy)...");
+	if(!FLAC__metadata_object_picture_set_mime_type(block, "image/png\t", /*copy=*/true)) {
+		printf("FAILED, returned false\n");
+		return false;
+	}
+	if(!mutils__compare_block(picture, block))
+		return false;
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_picture_is_legal()...");
+	{
+		const char *violation;
+		if(FLAC__metadata_object_picture_is_legal(block, &violation)) {
+			printf("FAILED, returned true when expecting false\n");
+			return false;
+		}
+		printf("returned false as expected, violation=\"%s\" OK\n", violation);
+	}
+
+	pi_set_mime_type(picture, "image/png");
+	printf("testing FLAC__metadata_object_picture_set_mime_type(copy)...");
+	if(!FLAC__metadata_object_picture_set_mime_type(block, "image/png", /*copy=*/true)) {
+		printf("FAILED, returned false\n");
+		return false;
+	}
+	if(!mutils__compare_block(picture, block))
+		return false;
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_picture_is_legal()...");
+	{
+		const char *violation;
+		if(!FLAC__metadata_object_picture_is_legal(block, &violation)) {
+			printf("FAILED, returned false, violation=\"%s\"\n", violation);
+			return false;
+		}
+		printf("OK\n");
+	}
+
+	pi_set_description(picture, (const FLAC__byte *)"DESCRIPTION\xff");
+	printf("testing FLAC__metadata_object_picture_set_description(copy)...");
+	if(!FLAC__metadata_object_picture_set_description(block, (FLAC__byte *)"DESCRIPTION\xff", /*copy=*/true)) {
+		printf("FAILED, returned false\n");
+		return false;
+	}
+	if(!mutils__compare_block(picture, block))
+		return false;
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_picture_is_legal()...");
+	{
+		const char *violation;
+		if(FLAC__metadata_object_picture_is_legal(block, &violation)) {
+			printf("FAILED, returned true when expecting false\n");
+			return false;
+		}
+		printf("returned false as expected, violation=\"%s\" OK\n", violation);
+	}
+
+	pi_set_description(picture, (const FLAC__byte *)"DESCRIPTION");
+	printf("testing FLAC__metadata_object_picture_set_description(copy)...");
+	if(!FLAC__metadata_object_picture_set_description(block, (FLAC__byte *)"DESCRIPTION", /*copy=*/true)) {
+		printf("FAILED, returned false\n");
+		return false;
+	}
+	if(!mutils__compare_block(picture, block))
+		return false;
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_picture_is_legal()...");
+	{
+		const char *violation;
+		if(!FLAC__metadata_object_picture_is_legal(block, &violation)) {
+			printf("FAILED, returned false, violation=\"%s\"\n", violation);
+			return false;
+		}
+		printf("OK\n");
+	}
+
+
+	pi_set_data(picture, (const FLAC__byte*)"PNGDATA", strlen("PNGDATA"));
+	printf("testing FLAC__metadata_object_picture_set_data(copy)...");
+	if(!FLAC__metadata_object_picture_set_data(block, (FLAC__byte*)"PNGDATA", strlen("PNGDATA"), /*copy=*/true)) {
+		printf("FAILED, returned false\n");
+		return false;
+	}
+	if(!mutils__compare_block(picture, block))
+		return false;
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_clone()... ");
+	blockcopy = FLAC__metadata_object_clone(block);
+	if(0 == blockcopy) {
+		printf("FAILED, returned NULL\n");
+		return false;
+	}
+	if(!mutils__compare_block(block, blockcopy))
+		return false;
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_delete()... ");
+	FLAC__metadata_object_delete(blockcopy);
+	printf("OK\n");
+
+	pi_set_mime_type(picture, "image/png\t");
+	printf("testing FLAC__metadata_object_picture_set_mime_type(own)...");
+	if(!FLAC__metadata_object_picture_set_mime_type(block, strdup("image/png\t"), /*copy=*/false)) {
+		printf("FAILED, returned false\n");
+		return false;
+	}
+	if(!mutils__compare_block(picture, block))
+		return false;
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_picture_is_legal()...");
+	{
+		const char *violation;
+		if(FLAC__metadata_object_picture_is_legal(block, &violation)) {
+			printf("FAILED, returned true when expecting false\n");
+			return false;
+		}
+		printf("returned false as expected, violation=\"%s\" OK\n", violation);
+	}
+
+	pi_set_mime_type(picture, "image/png");
+	printf("testing FLAC__metadata_object_picture_set_mime_type(own)...");
+	if(!FLAC__metadata_object_picture_set_mime_type(block, strdup("image/png"), /*copy=*/false)) {
+		printf("FAILED, returned false\n");
+		return false;
+	}
+	if(!mutils__compare_block(picture, block))
+		return false;
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_picture_is_legal()...");
+	{
+		const char *violation;
+		if(!FLAC__metadata_object_picture_is_legal(block, &violation)) {
+			printf("FAILED, returned false, violation=\"%s\"\n", violation);
+			return false;
+		}
+		printf("OK\n");
+	}
+
+	pi_set_description(picture, (const FLAC__byte *)"DESCRIPTION\xff");
+	printf("testing FLAC__metadata_object_picture_set_description(own)...");
+	if(!FLAC__metadata_object_picture_set_description(block, (FLAC__byte *)strdup("DESCRIPTION\xff"), /*copy=*/false)) {
+		printf("FAILED, returned false\n");
+		return false;
+	}
+	if(!mutils__compare_block(picture, block))
+		return false;
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_picture_is_legal()...");
+	{
+		const char *violation;
+		if(FLAC__metadata_object_picture_is_legal(block, &violation)) {
+			printf("FAILED, returned true when expecting false\n");
+			return false;
+		}
+		printf("returned false as expected, violation=\"%s\" OK\n", violation);
+	}
+
+	pi_set_description(picture, (const FLAC__byte *)"DESCRIPTION");
+	printf("testing FLAC__metadata_object_picture_set_description(own)...");
+	if(!FLAC__metadata_object_picture_set_description(block, (FLAC__byte *)strdup("DESCRIPTION"), /*copy=*/false)) {
+		printf("FAILED, returned false\n");
+		return false;
+	}
+	if(!mutils__compare_block(picture, block))
+		return false;
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_picture_is_legal()...");
+	{
+		const char *violation;
+		if(!FLAC__metadata_object_picture_is_legal(block, &violation)) {
+			printf("FAILED, returned false, violation=\"%s\"\n", violation);
+			return false;
+		}
+		printf("OK\n");
+	}
+
+	pi_set_data(picture, (const FLAC__byte*)"PNGDATA", strlen("PNGDATA"));
+	printf("testing FLAC__metadata_object_picture_set_data(own)...");
+	if(!FLAC__metadata_object_picture_set_data(block, (FLAC__byte*)strdup("PNGDATA"), strlen("PNGDATA"), /*copy=*/false)) {
+		printf("FAILED, returned false\n");
+		return false;
+	}
+	if(!mutils__compare_block(picture, block))
+		return false;
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_clone()... ");
+	blockcopy = FLAC__metadata_object_clone(block);
+	if(0 == blockcopy) {
+		printf("FAILED, returned NULL\n");
+		return false;
+	}
+	if(!mutils__compare_block(block, blockcopy))
+		return false;
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_delete()... ");
+	FLAC__metadata_object_delete(blockcopy);
+	printf("OK\n");
+
+	printf("testing FLAC__metadata_object_delete()... ");
+	FLAC__metadata_object_delete(picture);
+	FLAC__metadata_object_delete(block);
+	printf("OK\n");
+
+
 	return true;
 }
diff --git a/src/test_libOggFLAC++/decoders.cpp b/src/test_libOggFLAC++/decoders.cpp
index 0776d0b..9a91ab9 100644
--- a/src/test_libOggFLAC++/decoders.cpp
+++ b/src/test_libOggFLAC++/decoders.cpp
@@ -58,8 +58,8 @@
 	"Filename"
 };
 
-static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static ::FLAC__StreamMetadata *expected_metadata_sequence_[8];
+static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static ::FLAC__StreamMetadata *expected_metadata_sequence_[9];
 static unsigned num_expected_;
 static const char *flacfilename_ = "metadata.ogg";
 static off_t flacfilesize_;
@@ -90,12 +90,12 @@
 
 static void init_metadata_blocks_()
 {
-	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static void free_metadata_blocks_()
 {
-	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static bool generate_file_()
@@ -109,6 +109,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 	/* WATCHOUT: the encoder should move the VORBIS_COMMENT block to the front, right after STREAMINFO */
 
@@ -723,6 +724,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application1_;
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -769,6 +771,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application1_;
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -798,6 +801,7 @@
 	expected_metadata_sequence_[num_expected_++] = &padding_;
 	expected_metadata_sequence_[num_expected_++] = &seektable_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -828,6 +832,7 @@
 	expected_metadata_sequence_[num_expected_++] = &seektable_;
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -864,6 +869,7 @@
 	expected_metadata_sequence_[num_expected_++] = &padding_;
 	expected_metadata_sequence_[num_expected_++] = &seektable_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -1006,6 +1012,7 @@
 	expected_metadata_sequence_[num_expected_++] = &seektable_;
 	expected_metadata_sequence_[num_expected_++] = &application1_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
diff --git a/src/test_libOggFLAC++/encoders.cpp b/src/test_libOggFLAC++/encoders.cpp
index d2c7f69..ce91c8e 100644
--- a/src/test_libOggFLAC++/encoders.cpp
+++ b/src/test_libOggFLAC++/encoders.cpp
@@ -42,8 +42,8 @@
 	"Filename"
 };
 
-static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static ::FLAC__StreamMetadata *metadata_sequence_[] = { &vorbiscomment_, &padding_, &seektable_, &application1_, &application2_, &cuesheet_, &unknown_ };
+static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static ::FLAC__StreamMetadata *metadata_sequence_[] = { &vorbiscomment_, &padding_, &seektable_, &application1_, &application2_, &cuesheet_, &picture_, &unknown_ };
 static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
 static const char *flacfilename_ = "metadata.ogg";
 
@@ -77,12 +77,12 @@
 
 static void init_metadata_blocks_()
 {
-	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static void free_metadata_blocks_()
 {
-	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 class StreamEncoder : public OggFLAC::Encoder::Stream {
diff --git a/src/test_libOggFLAC/decoders.c b/src/test_libOggFLAC/decoders.c
index f02abbc..4eea85d 100644
--- a/src/test_libOggFLAC/decoders.c
+++ b/src/test_libOggFLAC/decoders.c
@@ -59,8 +59,8 @@
 	FLAC__bool error_occurred;
 } StreamDecoderClientData;
 
-static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static FLAC__StreamMetadata *expected_metadata_sequence_[8];
+static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static FLAC__StreamMetadata *expected_metadata_sequence_[9];
 static unsigned num_expected_;
 static const char *flacfilename_ = "metadata.ogg";
 static off_t flacfilesize_;
@@ -91,12 +91,12 @@
 
 static void init_metadata_blocks_()
 {
-	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static void free_metadata_blocks_()
 {
-	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static FLAC__bool generate_file_()
@@ -110,6 +110,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 	/* WATCHOUT: the encoder should move the VORBIS_COMMENT block to the front, right after STREAMINFO */
 
@@ -643,6 +644,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application1_;
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -683,6 +685,7 @@
 	expected_metadata_sequence_[num_expected_++] = &application1_;
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -708,6 +711,7 @@
 	expected_metadata_sequence_[num_expected_++] = &padding_;
 	expected_metadata_sequence_[num_expected_++] = &seektable_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -734,6 +738,7 @@
 	expected_metadata_sequence_[num_expected_++] = &seektable_;
 	expected_metadata_sequence_[num_expected_++] = &application2_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -764,6 +769,7 @@
 	expected_metadata_sequence_[num_expected_++] = &padding_;
 	expected_metadata_sequence_[num_expected_++] = &seektable_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -882,6 +888,7 @@
 	expected_metadata_sequence_[num_expected_++] = &seektable_;
 	expected_metadata_sequence_[num_expected_++] = &application1_;
 	expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+	expected_metadata_sequence_[num_expected_++] = &picture_;
 	expected_metadata_sequence_[num_expected_++] = &unknown_;
 
 	if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
diff --git a/src/test_libOggFLAC/encoders.c b/src/test_libOggFLAC/encoders.c
index 871ead4..d7701a5 100644
--- a/src/test_libOggFLAC/encoders.c
+++ b/src/test_libOggFLAC/encoders.c
@@ -45,8 +45,8 @@
 	"Filename"
 };
 
-static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static FLAC__StreamMetadata *metadata_sequence_[] = { &vorbiscomment_, &padding_, &seektable_, &application1_, &application2_, &cuesheet_, &unknown_ };
+static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static FLAC__StreamMetadata *metadata_sequence_[] = { &vorbiscomment_, &padding_, &seektable_, &application1_, &application2_, &cuesheet_, &picture_, &unknown_ };
 static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
 static const char *flacfilename_ = "metadata.ogg";
 
@@ -80,12 +80,12 @@
 
 static void init_metadata_blocks_()
 {
-	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static void free_metadata_blocks_()
 {
-	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+	mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
 }
 
 static OggFLAC__StreamEncoderReadStatus stream_encoder_read_callback_(const OggFLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
diff --git a/src/test_libs_common/metadata_utils.c b/src/test_libs_common/metadata_utils.c
index 926a894..1c88251 100644
--- a/src/test_libs_common/metadata_utils.c
+++ b/src/test_libs_common/metadata_utils.c
@@ -289,6 +289,56 @@
 	return true;
 }
 
+FLAC__bool mutils__compare_block_data_picture(const FLAC__StreamMetadata_Picture *block, const FLAC__StreamMetadata_Picture *blockcopy)
+{
+	size_t len, lencopy;
+	if(blockcopy->type != block->type) {
+		printf("FAILED, type mismatch, expected %u, got %u\n", (unsigned)block->type, (unsigned)blockcopy->type);
+		return false;
+	}
+	len = strlen(block->mime_type);
+	lencopy = strlen(blockcopy->mime_type);
+	if(lencopy != len) {
+		printf("FAILED, mime_type length mismatch, expected %u, got %u\n", (unsigned)len, (unsigned)lencopy);
+		return false;
+	}
+	if(strcmp(blockcopy->mime_type, block->mime_type)) {
+		printf("FAILED, mime_type mismatch, expected %s, got %s\n", block->mime_type, blockcopy->mime_type);
+		return false;
+	}
+	len = strlen((const char *)block->description);
+	lencopy = strlen((const char *)blockcopy->description);
+	if(lencopy != len) {
+		printf("FAILED, description length mismatch, expected %u, got %u\n", (unsigned)len, (unsigned)lencopy);
+		return false;
+	}
+	if(strcmp((const char *)blockcopy->description, (const char *)block->description)) {
+		printf("FAILED, description mismatch, expected %s, got %s\n", block->description, blockcopy->description);
+		return false;
+	}
+	if(blockcopy->width != block->width) {
+		printf("FAILED, width mismatch, expected %u, got %u\n", block->width, blockcopy->width);
+		return false;
+	}
+	if(blockcopy->height != block->height) {
+		printf("FAILED, height mismatch, expected %u, got %u\n", block->height, blockcopy->height);
+		return false;
+	}
+	if(blockcopy->depth != block->depth) {
+		printf("FAILED, depth mismatch, expected %u, got %u\n", block->depth, blockcopy->depth);
+		return false;
+	}
+	if(blockcopy->data_length != block->data_length) {
+		printf("FAILED, data_length mismatch, expected %u, got %u\n", block->data_length, blockcopy->data_length);
+		return false;
+	}
+	if(memcmp(blockcopy->data, block->data, block->data_length)) {
+		printf("FAILED, data mismatch\n");
+		return false;
+	}
+	return true;
+}
+
 FLAC__bool mutils__compare_block_data_unknown(const FLAC__StreamMetadata_Unknown *block, const FLAC__StreamMetadata_Unknown *blockcopy, unsigned block_length)
 {
 	if(0 == block->data || 0 == blockcopy->data) {
@@ -341,10 +391,13 @@
 			return mutils__compare_block_data_vorbiscomment(&block->data.vorbis_comment, &blockcopy->data.vorbis_comment);
 		case FLAC__METADATA_TYPE_CUESHEET:
 			return mutils__compare_block_data_cuesheet(&block->data.cue_sheet, &blockcopy->data.cue_sheet);
+		case FLAC__METADATA_TYPE_PICTURE:
+			return mutils__compare_block_data_picture(&block->data.picture, &blockcopy->data.picture);
 		default:
 			return mutils__compare_block_data_unknown(&block->data.unknown, &blockcopy->data.unknown, block->length);
 	}
 }
+
 static void *malloc_or_die_(size_t size)
 {
 	void *x = malloc(size);
@@ -365,6 +418,16 @@
 	return x;
 }
 
+static char *strdup_or_die_(const char *s)
+{
+	char *x = strdup(s);
+	if(0 == x) {
+		fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
+		exit(1);
+	}
+	return x;
+}
+
 void mutils__init_metadata_blocks(
 	FLAC__StreamMetadata *streaminfo,
 	FLAC__StreamMetadata *padding,
@@ -373,6 +436,7 @@
 	FLAC__StreamMetadata *application2,
 	FLAC__StreamMetadata *vorbiscomment,
 	FLAC__StreamMetadata *cuesheet,
+	FLAC__StreamMetadata *picture,
 	FLAC__StreamMetadata *unknown
 )
 {
@@ -503,6 +567,31 @@
 	cuesheet->data.cue_sheet.tracks[2].number = 170;
 	cuesheet->data.cue_sheet.tracks[2].num_indices = 0;
 
+	picture->is_last = false;
+	picture->type = FLAC__METADATA_TYPE_PICTURE;
+	picture->length =
+		(
+			FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+			FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
+			FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
+			FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+			FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+			FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+			FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
+		) / 8
+	;
+	picture->data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
+	picture->data.picture.mime_type = strdup_or_die_("image/jpeg");
+	picture->length += strlen(picture->data.picture.mime_type);
+	picture->data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
+	picture->length += strlen((const char *)picture->data.picture.description);
+	picture->data.picture.width = 300;
+	picture->data.picture.height = 300;
+	picture->data.picture.depth = 24;
+	picture->data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
+	picture->data.picture.data_length = strlen((const char *)picture->data.picture.data);
+	picture->length += picture->data.picture.data_length;
+
 	unknown->is_last = true;
 	unknown->type = 126;
 	unknown->length = 8;
@@ -518,6 +607,7 @@
 	FLAC__StreamMetadata *application2,
 	FLAC__StreamMetadata *vorbiscomment,
 	FLAC__StreamMetadata *cuesheet,
+	FLAC__StreamMetadata *picture,
 	FLAC__StreamMetadata *unknown
 )
 {
@@ -530,5 +620,8 @@
 	free(cuesheet->data.cue_sheet.tracks[0].indices);
 	free(cuesheet->data.cue_sheet.tracks[1].indices);
 	free(cuesheet->data.cue_sheet.tracks);
+	free(picture->data.picture.mime_type);
+	free(picture->data.picture.description);
+	free(picture->data.picture.data);
 	free(unknown->data.unknown.data);
 }