add new options: --tag-from-file for flac and --set-tag-from-file for metaflac
diff --git a/doc/html/changelog.html b/doc/html/changelog.html
index 490956e..2aabf84 100644
--- a/doc/html/changelog.html
+++ b/doc/html/changelog.html
@@ -83,7 +83,8 @@
 			<li>
 				flac:
 				<ul>
-					<li>Add support for encoding from non-compressed AIFF-C (<a href="https://sourceforge.net/tracker/?func=detail&amp;atid=113478&amp;aid=1090933&amp;group_id=13478">SF #1090933</a>).</li>
+					<li>Added a new option <a href="documentation.html#flac_options_tag_from_file"><span class="argument">--tag-from-file</span></a> for setting a tag from file (e.g. for importing a cuesheet as a tag).</li>
+					<li>Added support for encoding from non-compressed AIFF-C (<a href="https://sourceforge.net/tracker/?func=detail&amp;atid=113478&amp;aid=1090933&amp;group_id=13478">SF #1090933</a>).</li>
 					<li>Importing of non-CDDA-compliant cuesheets now only issues a warning, not an error (see <a href="http://www.hydrogenaudio.org/forums/index.php?showtopic=31282">here</a>).</li>
 					<li>Fixed a bug in cuesheet parsing where it would return an error if the last line of the cuesheet did not end with a newline.</li>
 					<li>Fixed a bug that caused a crash when <span class="argument">-a</span> and <span class="argument">-t</span> were used together (<a href="https://sourceforge.net/tracker/index.php?func=detail&amp;aid=1229481&amp;group_id=13478&amp;atid=113478">SF #1229481</a>).</li>
@@ -95,6 +96,7 @@
 			<li>
 				metaflac:
 				<ul>
+					<li>Added a new option <a href="documentation.html#metaflac_shorthand_set_tag_from_file"><span class="argument">--set-tag-from-file</span></a> for setting a tag from file (e.g. for importing a cuesheet as a tag).</li>
 					<li>Added shorthand operation <a href="documentation.html#metaflac_shorthand_remove_replay_gain"><span class="argument">--remove-replay-gain</span></a> for removing ReplayGain tags.</li>
 					<li>Importing of non-CDDA-compliant cuesheets now issues a warning.</li>
 				</ul>
diff --git a/doc/html/documentation.html b/doc/html/documentation.html
index b07004d..48e725b 100644
--- a/doc/html/documentation.html
+++ b/doc/html/documentation.html
@@ -585,6 +585,15 @@
 			</tr>
 			<tr>
 				<td nowrap="nowrap" align="right" valign="top" bgcolor="#F4F4CC">
+					<a name="flac_options_tag_from_file" />
+					<span class="argument">--tag-from-file=FIELD=FILENAME</span>
+				</td>
+				<td>
+					Like <a href="#flac_options_tag"><span class="argument">--tag</span></a>, except FILENAME is a file whose contents will be read verbatim to set the tag value.  The contents will be converted to UTF-8 from the local charset.  This can be used to store a cuesheet in a tag (e.g. <span class="argument">--tag-from-file="CUESHEET=image.cue"</span>).  Do not try to store binary data in tag fields!  Use APPLICATION blocks for that.
+				</td>
+			</tr>
+			<tr>
+				<td nowrap="nowrap" align="right" valign="top" bgcolor="#F4F4CC">
 					<a name="flac_options_blocksize" />
 					<span class="argument">-b #</span>, <span class="argument">--blocksize=#</span>
 				</td>
@@ -1135,11 +1144,20 @@
 			</tr>
 			<tr>
 				<td nowrap="nowrap" align="right" valign="top" bgcolor="#F4F4CC">
+					<a name="metaflac_shorthand_set_tag_from_file" />
+					<span class="argument">--set-tag-from-file=FIELD</span>
+				</td>
+				<td>
+					Like <a href="#metaflac_shorthand_set_tag"><span class="argument">--set-tag</span></a>, except the VALUE is a filename whose contents will be read verbatim to set the tag value.  Unless <a href="#metaflac_options_no_utf8_convert"><span class="argument">--no-utf8-convert</span></a> is specified, the contents will be converted to UTF-8 from the local charset.  This can be used to store a cuesheet in a tag (e.g. <span class="argument">--set-tag-from-file="CUESHEET=image.cue"</span>).  Do not try to store binary data in tag fields!  Use APPLICATION blocks for that.
+				</td>
+			</tr>
+			<tr>
+				<td nowrap="nowrap" align="right" valign="top" bgcolor="#F4F4CC">
 					<a name="metaflac_shorthand_import_tags_from" />
 					<span class="argument">--import-tags-from=FILE</span>
 				</td>
 				<td>
-					Import tags from a file.  Use '-' for stdin.  Each line should be of the form <span class="argument">NAME=VALUE</span>.  Multi-line comments are currently not supported.  Specify <span class="argument">--remove-all-tags</span> and/or <span class="argument">--no-utf8-convert</span> before <span class="argument">--import-tags-from</span> if necessary.
+					Import tags from a file.  Use '-' for stdin.  Each line should be of the form <span class="argument">NAME=VALUE</span>.  Multi-line comments are currently not supported.  Specify <span class="argument">--remove-all-tags</span> and/or <a href="#metaflac_options_no_utf8_convert"><span class="argument">--no-utf8-convert</span></a> before <span class="argument">--import-tags-from</span> if necessary.
 				</td>
 			</tr>
 			<tr>
@@ -1148,7 +1166,7 @@
 					<span class="argument">--export-tags-to=FILE</span>
 				</td>
 				<td>
-					Export tags to a file.  Use '-' for stdin.  Each line will be of the form <span class="argument">NAME=VALUE</span>.  Specify <span class="argument">--no-utf8-convert</span> if necessary.
+					Export tags to a file.  Use '-' for stdin.  Each line will be of the form <span class="argument">NAME=VALUE</span>.  Specify <a href="#metaflac_options_no_utf8_convert"><span class="argument">--no-utf8-convert</span></a> if necessary.
 				</td>
 			</tr>
 			<tr>
diff --git a/man/flac.sgml b/man/flac.sgml
index e959e84..44c587e 100644
--- a/man/flac.sgml
+++ b/man/flac.sgml
@@ -466,6 +466,21 @@
 	      </varlistentry>
 
 	      <varlistentry>
+		<term><option>--tag-from-file</option>=<replaceable>FIELD=FILENAME</replaceable></term>
+
+		<listitem>
+		  <para>Like --tag, except FILENAME is a file whose
+		    contents will be read verbatim to set the tag
+		    value.  The contents will be converted to UTF-8
+		    from the local charset.  This can be used to
+		    store a cuesheet in a tag (e.g.
+		    --tag-from-file="CUESHEET=image.cue").  Do not
+		    try to store binary data in tag fields!  Use
+		    APPLICATION blocks for that.</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
 		<term><option>-b</option> <replaceable>#</replaceable>, <option>--blocksize</option>=<replaceable>#</replaceable></term>
 
 		<listitem>
diff --git a/man/metaflac.sgml b/man/metaflac.sgml
index b2177e8..6a15b9a 100644
--- a/man/metaflac.sgml
+++ b/man/metaflac.sgml
@@ -244,6 +244,21 @@
         </listitem>
       </varlistentry>
       <varlistentry>
+        <term><option>--set-tag-from-file=field</option></term>
+        <listitem>
+          <para>
+	    Like --set-tag, except the VALUE is a filename whose
+	    contents will be read verbatim to set the tag value.
+	    Unless --no-utf8-convert is specified, the contents will be
+	    converted to UTF-8 from the local charset.  This can be used
+	    to store a cuesheet in a tag (e.g.
+	    --set-tag-from-file="CUESHEET=image.cue").  Do not try to
+	    store binary data in tag fields!  Use APPLICATION blocks for
+	    that.
+	  </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
 	<term><option>--import-tags-from=file</option></term>
         <listitem>
 	  <para>
diff --git a/src/flac/main.c b/src/flac/main.c
index 1e5d59e..7c94762 100644
--- a/src/flac/main.c
+++ b/src/flac/main.c
@@ -119,6 +119,7 @@
 	{ "cuesheet"                  , share__required_argument, 0, 0 },
 	{ "no-cued-seekpoints"        , share__no_argument, 0, 0 },
 	{ "tag"                       , share__required_argument, 0, 'T' },
+	{ "tag-from-file"             , share__required_argument, 0, 0 },
 	{ "compression-level-0"       , share__no_argument, 0, '0' },
 	{ "compression-level-1"       , share__no_argument, 0, '1' },
 	{ "compression-level-2"       , share__no_argument, 0, '2' },
@@ -656,6 +657,7 @@
 
 int parse_option(int short_option, const char *long_option, const char *option_argument)
 {
+	const char *violation;
 	char *p;
 
 	if(short_option == 0) {
@@ -715,6 +717,11 @@
 			FLAC__ASSERT(0 != option_argument);
 			option_values.cuesheet_filename = option_argument;
 		}
+		else if(0 == strcmp(long_option, "tag-from-file")) {
+			FLAC__ASSERT(0 != option_argument);
+			if(!flac__vorbiscomment_add(option_values.vorbis_comment, option_argument, /*value_from_file=*/true, &violation))
+				return usage_error("ERROR: (--tag-from-file) %s\n", violation);
+		}
 		else if(0 == strcmp(long_option, "no-cued-seekpoints")) {
 			option_values.cued_seekpoints = false;
 		}
@@ -858,7 +865,6 @@
 		}
 	}
 	else {
-		const char *violation;
 		switch(short_option) {
 			case 'h':
 				option_values.show_help = true;
@@ -898,7 +904,7 @@
 				break;
 			case 'T':
 				FLAC__ASSERT(0 != option_argument);
-				if(!flac__vorbiscomment_add(option_values.vorbis_comment, option_argument, &violation))
+				if(!flac__vorbiscomment_add(option_values.vorbis_comment, option_argument, /*value_from_file=*/false, &violation))
 					return usage_error("ERROR: (-T/--tag) %s\n", violation);
 				break;
 			case '0':
@@ -1208,6 +1214,7 @@
 	printf("      --replay-gain            Calculate ReplayGain & store in FLAC tags\n");
 	printf("      --cuesheet=FILENAME      Import cuesheet and store in CUESHEET block\n");
 	printf("  -T, --tag=FIELD=VALUE        Add a FLAC tag; may appear multiple times\n");
+	printf("      --tag-from-file=FIELD=FILENAME   Like --tag but gets value from file\n");
 	printf("  -S, --seekpoint={#|X|#x|#s}  Add seek point(s)\n");
 	printf("  -P, --padding=#              Write a PADDING block of length #\n");
 	printf("  -0, --compression-level-0, --fast  Synonymous with -l 0 -b 1152 -r 2,2\n");
@@ -1392,6 +1399,14 @@
 	printf("                               comment if necessary.  This option may appear\n");
 	printf("                               more than once to add several comments.  NOTE:\n");
 	printf("                               all tags will be added to all encoded files.\n");
+	printf("      --tag-from-file=FIELD=FILENAME   Like --tag, except FILENAME is a file\n");
+	printf("                               whose contents will be read verbatim to set the\n");
+	printf("                               tag value.  The contents will be converted to\n");
+	printf("                               UTF-8 from the local charset.  This can be used\n");
+	printf("                               to store a cuesheet in a tag (e.g.\n");
+	printf("                               --tag-from-file=\"CUESHEET=image.cue\").  Do not\n");
+	printf("                               try to store binary data in tag fields!  Use\n");
+	printf("                               APPLICATION blocks for that.\n");
 	printf("  -S, --seekpoint={#|X|#x|#s}  Include a point or points in a SEEKTABLE\n");
 	printf("       #  : a specific sample number for a seek point\n");
 	printf("       X  : a placeholder point (always goes at the end of the SEEKTABLE)\n");
diff --git a/src/flac/vorbiscomment.c b/src/flac/vorbiscomment.c
index 597aae9..30df758 100644
--- a/src/flac/vorbiscomment.c
+++ b/src/flac/vorbiscomment.c
@@ -23,6 +23,7 @@
 #include "vorbiscomment.h"
 #include "FLAC/assert.h"
 #include "FLAC/metadata.h"
+#include "share/grabbag.h" /* for grabbag__file_get_filesize() */
 #include "share/utf8.h"
 #include <ctype.h>
 #include <stdio.h>
@@ -32,7 +33,7 @@
 
 /*
  * This struct and the following 4 static functions are copied from
- * ../metaflac/main.c.  Maybe someday there will be a convenience
+ * ../metaflac/.  Maybe someday there will be a convenience
  * library for Vorbis comment parsing.
  */
 typedef struct {
@@ -41,6 +42,7 @@
 	/* according to the vorbis spec, field values can contain \0 so simple C strings are not enough here */
 	unsigned field_value_length;
 	char *field_value;
+	FLAC__bool field_value_from_file; /* true if field_value holds a filename for the value, false for plain value */
 } Argument_VcField;
 
 static void die(const char *message)
@@ -101,34 +103,102 @@
 {
 	FLAC__StreamMetadata_VorbisComment_Entry entry;
 	char *converted;
-	FLAC__bool needs_free = false;
 
 	FLAC__ASSERT(0 != block);
 	FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
 	FLAC__ASSERT(0 != field);
 	FLAC__ASSERT(0 != needs_write);
 
-	if(raw) {
-		entry.entry = (FLAC__byte *)field->field;
-	}
-	else if(utf8_encode(field->field, &converted) >= 0) {
-		entry.entry = (FLAC__byte *)converted;
-		needs_free = true;
-	}
-	else {
-		*violation = "couldn't convert comment to UTF-8";
-		return false;
-	}
+	if(field->field_value_from_file) {
+		/* read the file into 'data' */
+		FILE *f = 0;
+		char *data = 0;
+		const off_t size = grabbag__file_get_filesize(field->field_value);
+		if(size < 0) {
+			*violation = "can't open file for tag value";
+			return false;
+		}
+		if(size >= 0x100000) { /* magic arbitrary limit, actual format limit is near 16MB */
+			*violation = "file for tag value is too large";
+			return false;
+		}
+		if(0 == (data = malloc(size+1)))
+			die("out of memory allocating tag value");
+		data[size] = '\0';
+		if(0 == (f = fopen(field->field_value, "rb")) || fread(data, 1, size, f) != (size_t)size) {
+			free(data);
+			if(f)
+				fclose(f);
+			*violation = "error while reading file for tag value";
+			return false;
+		}
+		fclose(f);
+		if(strlen(data) != (size_t)size) {
+			free(data);
+			*violation = "file for tag value has embedded NULs";
+			return false;
+		}
 
-	entry.length = strlen((const char *)entry.entry);
+		/* move 'data' into 'converted', converting to UTF-8 if necessary */
+		if(raw) {
+			converted = data;
+		}
+		else if(utf8_encode(data, &converted) >= 0) {
+			free(data);
+		}
+		else {
+			free(data);
+			*violation = "error converting file contents to UTF-8 for tag value";
+			return false;
+		}
 
-	if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/true)) {
-		if(needs_free)
+		/* create and entry and append it */
+		if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, field->field_name, converted)) {
 			free(converted);
-		*violation = "memory allocation failure";
-		return false;
+			*violation = "file for tag value is not valid UTF-8";
+			return false;
+		}
+		free(converted);
+		if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/false)) {
+			*violation = "memory allocation failure";
+			return false;
+		}
+
+		*needs_write = true;
+		return true;
 	}
 	else {
+		FLAC__bool needs_free = false;
+		if(raw) {
+			entry.entry = (FLAC__byte *)field->field;
+		}
+		else if(utf8_encode(field->field, &converted) >= 0) {
+			entry.entry = (FLAC__byte *)converted;
+			needs_free = true;
+		}
+		else {
+			*violation = "error converting comment to UTF-8";
+			return false;
+		}
+		entry.length = strlen((const char *)entry.entry);
+		if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length)) {
+			if(needs_free)
+				free(converted);
+			/*
+			 * our previous parsing has already established that the field
+			 * name is OK, so it must be the field value
+			 */
+			*violation = "tag value for is not valid UTF-8";
+			return false;
+		}
+
+		if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/true)) {
+			if(needs_free)
+				free(converted);
+			*violation = "memory allocation failure";
+			return false;
+		}
+
 		*needs_write = true;
 		if(needs_free)
 			free(converted);
@@ -150,7 +220,7 @@
 		free(obj->field_value);
 }
 
-FLAC__bool flac__vorbiscomment_add(FLAC__StreamMetadata *block, const char *comment, const char **violation)
+FLAC__bool flac__vorbiscomment_add(FLAC__StreamMetadata *block, const char *comment, FLAC__bool value_from_file, const char **violation)
 {
 	Argument_VcField parsed;
 	FLAC__bool dummy;
@@ -161,6 +231,7 @@
 
 	memset(&parsed, 0, sizeof(parsed));
 
+	parsed.field_value_from_file = value_from_file;
 	if(!parse_vorbis_comment_field(comment, &(parsed.field), &(parsed.field_name), &(parsed.field_value), &(parsed.field_value_length), violation)) {
 		free_field(&parsed);
 		return false;
diff --git a/src/flac/vorbiscomment.h b/src/flac/vorbiscomment.h
index 802558b..2f796b5 100644
--- a/src/flac/vorbiscomment.h
+++ b/src/flac/vorbiscomment.h
@@ -21,6 +21,6 @@
 
 #include "FLAC/metadata.h"
 
-FLAC__bool flac__vorbiscomment_add(FLAC__StreamMetadata *block, const char *comment, const char **violation);
+FLAC__bool flac__vorbiscomment_add(FLAC__StreamMetadata *block, const char *comment, FLAC__bool value_from_file, const char **violation);
 
 #endif
diff --git a/src/metaflac/operations_shorthand_vorbiscomment.c b/src/metaflac/operations_shorthand_vorbiscomment.c
index 843fa29..e28cbb5 100644
--- a/src/metaflac/operations_shorthand_vorbiscomment.c
+++ b/src/metaflac/operations_shorthand_vorbiscomment.c
@@ -19,6 +19,7 @@
 #include "options.h"
 #include "utils.h"
 #include "FLAC/assert.h"
+#include "share/grabbag.h" /* for grabbag__file_get_filesize() */
 #include "share/utf8.h"
 #include <stdlib.h>
 #include <string.h>
@@ -171,34 +172,102 @@
 {
 	FLAC__StreamMetadata_VorbisComment_Entry entry;
 	char *converted;
-	FLAC__bool needs_free = false;
 
 	FLAC__ASSERT(0 != block);
 	FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
 	FLAC__ASSERT(0 != field);
 	FLAC__ASSERT(0 != needs_write);
 
-	if(raw) {
-		entry.entry = (FLAC__byte *)field->field;
-	}
-	else if(utf8_encode(field->field, &converted) >= 0) {
-		entry.entry = (FLAC__byte *)converted;
-		needs_free = true;
-	}
-	else {
-		fprintf(stderr, "%s: ERROR: couldn't convert comment to UTF-8\n", filename);
-		return false;
-	}
+	if(field->field_value_from_file) {
+		/* read the file into 'data' */
+		FILE *f = 0;
+		char *data = 0;
+		const off_t size = grabbag__file_get_filesize(field->field_value);
+		if(size < 0) {
+			fprintf(stderr, "%s: ERROR: can't open file '%s' for '%s' tag value\n", filename, field->field_value, field->field_name);
+			return false;
+		}
+		if(size >= 0x100000) { /* magic arbitrary limit, actual format limit is near 16MB */
+			fprintf(stderr, "%s: ERROR: file '%s' for '%s' tag value is too large\n", filename, field->field_value, field->field_name);
+			return false;
+		}
+		if(0 == (data = malloc(size+1)))
+			die("out of memory allocating tag value");
+		data[size] = '\0';
+		if(0 == (f = fopen(field->field_value, "rb")) || fread(data, 1, size, f) != (size_t)size) {
+			free(data);
+			if(f)
+				fclose(f);
+			fprintf(stderr, "%s: ERROR: while reading file '%s' for '%s' tag value\n", filename, field->field_value, field->field_name);
+			return false;
+		}
+		fclose(f);
+		if(strlen(data) != (size_t)size) {
+			free(data);
+			fprintf(stderr, "%s: ERROR: file '%s' for '%s' tag value has embedded NULs\n", filename, field->field_value, field->field_name);
+			return false;
+		}
 
-	entry.length = strlen((const char *)entry.entry);
+		/* move 'data' into 'converted', converting to UTF-8 if necessary */
+		if(raw) {
+			converted = data;
+		}
+		else if(utf8_encode(data, &converted) >= 0) {
+			free(data);
+		}
+		else {
+			free(data);
+			fprintf(stderr, "%s: ERROR: converting file '%s' contents to UTF-8 for tag value\n", filename, field->field_value);
+			return false;
+		}
 
-	if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/true)) {
-		if(needs_free)
+		/* create and entry and append it */
+		if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, field->field_name, converted)) {
 			free(converted);
-		fprintf(stderr, "%s: ERROR: memory allocation failure\n", filename);
-		return false;
+			fprintf(stderr, "%s: ERROR: file '%s' for '%s' tag value is not valid UTF-8\n", filename, field->field_value, field->field_name);
+			return false;
+		}
+		free(converted);
+		if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/false)) {
+			fprintf(stderr, "%s: ERROR: memory allocation failure\n", filename);
+			return false;
+		}
+
+		*needs_write = true;
+		return true;
 	}
 	else {
+		FLAC__bool needs_free = false;
+		if(raw) {
+			entry.entry = (FLAC__byte *)field->field;
+		}
+		else if(utf8_encode(field->field, &converted) >= 0) {
+			entry.entry = (FLAC__byte *)converted;
+			needs_free = true;
+		}
+		else {
+			fprintf(stderr, "%s: ERROR: converting comment '%s' to UTF-8\n", filename, field->field);
+			return false;
+		}
+		entry.length = strlen((const char *)entry.entry);
+		if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length)) {
+			if(needs_free)
+				free(converted);
+			/*
+			 * our previous parsing has already established that the field
+			 * name is OK, so it must be the field value
+			 */
+			fprintf(stderr, "%s: ERROR: tag value for '%s' is not valid UTF-8\n", filename, field->field_name);
+			return false;
+		}
+
+		if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/true)) {
+			if(needs_free)
+				free(converted);
+			fprintf(stderr, "%s: ERROR: memory allocation failure\n", filename);
+			return false;
+		}
+
 		*needs_write = true;
 		if(needs_free)
 			free(converted);
@@ -240,6 +309,7 @@
 				Argument_VcField field;
 				*p = '\0';
 				memset(&field, 0, sizeof(Argument_VcField));
+				field.field_value_from_file = false;
 				if(!parse_vorbis_comment_field(line, &field.field, &field.field_name, &field.field_value, &field.field_value_length, &violation)) {
 					FLAC__ASSERT(0 != violation);
 					fprintf(stderr, "%s: ERROR: malformed vorbis comment field \"%s\",\n       %s\n", vc_filename->value, line, violation);
diff --git a/src/metaflac/options.c b/src/metaflac/options.c
index ac6eb33..7e94742 100644
--- a/src/metaflac/options.c
+++ b/src/metaflac/options.c
@@ -63,6 +63,7 @@
 	{ "remove-tag", 1, 0, 0 }, 
 	{ "remove-first-tag", 1, 0, 0 }, 
 	{ "set-tag", 1, 0, 0 }, 
+	{ "set-tag-from-file", 1, 0, 0 }, 
 	{ "import-tags-from", 1, 0, 0 }, 
 	{ "export-tags-to", 1, 0, 0 }, 
 	{ "show-vc-vendor", 0, 0, 0 }, /* deprecated */
@@ -503,6 +504,18 @@
 			fprintf(stderr, "WARNING: --%s is deprecated, the new name is --set-tag\n", opt);
 		op = append_shorthand_operation(options, OP__SET_VC_FIELD);
 		FLAC__ASSERT(0 != option_argument);
+		op->argument.vc_field.field_value_from_file = false;
+		if(!parse_vorbis_comment_field(option_argument, &(op->argument.vc_field.field), &(op->argument.vc_field.field_name), &(op->argument.vc_field.field_value), &(op->argument.vc_field.field_value_length), &violation)) {
+			FLAC__ASSERT(0 != violation);
+			fprintf(stderr, "ERROR (--%s): malformed vorbis comment field \"%s\",\n       %s\n", opt, option_argument, violation);
+			ok = false;
+		}
+	}
+	else if(0 == strcmp(opt, "set-tag-from-file")) {
+		const char *violation;
+		op = append_shorthand_operation(options, OP__SET_VC_FIELD);
+		FLAC__ASSERT(0 != option_argument);
+		op->argument.vc_field.field_value_from_file = true;
 		if(!parse_vorbis_comment_field(option_argument, &(op->argument.vc_field.field), &(op->argument.vc_field.field_name), &(op->argument.vc_field.field_value), &(op->argument.vc_field.field_value_length), &violation)) {
 			FLAC__ASSERT(0 != violation);
 			fprintf(stderr, "ERROR (--%s): malformed vorbis comment field \"%s\",\n       %s\n", opt, option_argument, violation);
diff --git a/src/metaflac/options.h b/src/metaflac/options.h
index b1535d4..4fc2b8c 100644
--- a/src/metaflac/options.h
+++ b/src/metaflac/options.h
@@ -101,6 +101,7 @@
 	/* according to the vorbis spec, field values can contain \0 so simple C strings are not enough here */
 	unsigned field_value_length;
 	char *field_value;
+	FLAC__bool field_value_from_file; /* true if field_value holds a filename for the value, false for plain value */
 } Argument_VcField;
 
 typedef struct {
diff --git a/src/metaflac/usage.c b/src/metaflac/usage.c
index 4f715ea..4ba9f58 100644
--- a/src/metaflac/usage.c
+++ b/src/metaflac/usage.c
@@ -122,6 +122,14 @@
 	fprintf(out, "--set-tag=FIELD       Add a tag.  The FIELD must comply with the Vorbis comment\n");
 	fprintf(out, "                      spec, of the form \"NAME=VALUE\".  If there is currently\n");
 	fprintf(out, "                      no tag block, one will be created.\n");
+	fprintf(out, "--set-tag-from-file=FIELD   Like --set-tag, except the VALUE is a filename\n");
+	fprintf(out, "                      whose contents will be read verbatim to set the tag value.\n");
+	fprintf(out, "                      Unless --no-utf8-convert is specified, the contents will\n");
+	fprintf(out, "                      be converted to UTF-8 from the local charset.  This can\n");
+	fprintf(out, "                      be used to store a cuesheet in a tag (e.g.\n");
+	fprintf(out, "                      --set-tag-from-file=\"CUESHEET=image.cue\").  Do not try to\n");
+	fprintf(out, "                      store binary data in tag fields!  Use APPLICATION blocks\n");
+	fprintf(out, "                      for that.\n");
 	fprintf(out, "--import-tags-from=FILE Import tags from a file.  Use '-' for stdin.  Each line\n");
 	fprintf(out, "                      should be of the form NAME=VALUE.  Multi-line comments\n");
 	fprintf(out, "                      are currently not supported.  Specify --remove-all-tags\n");