Skip to content

Commit

Permalink
audtag: Parse PIC (ID3v2.2) frames correctly. Closes: #1030.
Browse files Browse the repository at this point in the history
They are not identical to APIC frames (ID3v2.3 or v2.4).
  • Loading branch information
jlindgren90 committed Oct 23, 2020
1 parent f639fd8 commit e856c92
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 19 deletions.
63 changes: 47 additions & 16 deletions src/libaudtag/id3/id3-common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -303,32 +303,63 @@ void id3_decode_txxx (Tuple & tuple, const char * data, int size)
}
}

Index<char> id3_decode_picture (const char * data, int size)
/* Decodes the common part of a PIC (v2.2) or APIC (v2.3/2.4) frame following
* the "Image format" (PIC) or "MIME type" (APIC) field */
static Index<char> id3_decode_pic_common (const char * data, int size, int encoding)
{
Index<char> buf;

const char * nul;
if (size < 2 || ! (nul = (char *) memchr (data + 1, 0, size - 2)))
if (size < 1)
return buf;

int type = (unsigned char) nul[1];

const char * body = nul + 2;
int body_size = data + size - body;
/* byte 0: picture type */
int type = (unsigned char) data[0];

int before_nul2, after_nul2;
id3_strnlen (body, body_size, data[0], & before_nul2, & after_nul2);
/* ... followed by null-terminated description */
int desc_size, offset;
id3_strnlen (data + 1, size - 1, encoding, & desc_size, & offset);
StringBuf desc = id3_convert (data + 1, desc_size, encoding);

const char * mime = data + 1;
StringBuf desc = id3_convert (body, before_nul2, data[0]);
/* ... followed by image data */
const char * image_data = data + 1 + offset;
int image_size = size - 1 - offset;

int image_size = body_size - after_nul2;

AUDDBG ("Picture: mime = %s, type = %d, desc = %s, size = %d.\n", mime,
type, (const char *) desc, image_size);
AUDDBG ("Picture: type = %d, desc = %s, size = %d.\n", type,
(const char *) desc, image_size);

if (type == 3 || type == 0) /* album cover or iTunes */
buf.insert (body + after_nul2, 0, image_size);
buf.insert (image_data, 0, image_size);

return buf;
}

/* Decodes a PIC frame (v2.2) */
Index<char> id3_decode_pic (const char * data, int size)
{
Index<char> buf;

/* bytes 1..3: 3-character format e.g. "PNG" or "JPG" */
if (size < 4)
return buf;

AUDDBG ("PIC: format = %.3s\n", data + 1);

/* byte 0: text encoding */
return id3_decode_pic_common (data + 4, size - 4, data[0]);
}

/* Decodes an APIC frame (v2.3 or v2.4) */
Index<char> id3_decode_apic (const char * data, int size)
{
Index<char> buf;

/* bytes 1..n: null-terminated MIME type */
const char * nul;
if (size < 1 || ! (nul = (char *) memchr (data + 1, 0, size - 1)))
return buf;

AUDDBG ("APIC: MIME type = %s\n", data + 1);

/* byte 0: text encoding */
return id3_decode_pic_common (nul + 1, data + size - (nul + 1), data[0]);
}
3 changes: 2 additions & 1 deletion src/libaudtag/id3/id3-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ void id3_decode_comment (Tuple & tuple, const char * data, int size);
void id3_decode_rva (Tuple & tuple, const char * data, int size);
void id3_decode_txxx (Tuple & tuple, const char * data, int size);

Index<char> id3_decode_picture (const char * data, int size);
Index<char> id3_decode_pic (const char * data, int size);
Index<char> id3_decode_apic (const char * data, int size);

#endif
2 changes: 1 addition & 1 deletion src/libaudtag/id3/id3v22.cc
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ bool ID3v22TagModule::read_tag (VFSFile & handle, Tuple & tuple, Index<char> * i
break;
case ID3_PIC:
if (image)
* image = id3_decode_picture (& frame[0], frame.len ());
* image = id3_decode_pic (& frame[0], frame.len ());
break;
default:
AUDDBG ("Ignoring unsupported ID3 frame %s.\n", (const char *) frame.key);
Expand Down
2 changes: 1 addition & 1 deletion src/libaudtag/id3/id3v24.cc
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ bool ID3v24TagModule::read_tag (VFSFile & handle, Tuple & tuple, Index<char> * i
break;
case ID3_APIC:
if (image)
* image = id3_decode_picture (& frame[0], frame.len ());
* image = id3_decode_apic (& frame[0], frame.len ());
break;
default:
AUDDBG ("Ignoring unsupported ID3 frame %s.\n", (const char *) frame.key);
Expand Down

0 comments on commit e856c92

Please sign in to comment.