Perl ID3::Tag and Errors with Cover Art

Perl ID3::Tag and Errors with Cover Art

First off let me apologize for the stupid graphic on this post. I was getting a little lazy.

Now my question is for anyone who has used the MP3::Tag module on ID3v2 tags. At the moment when I use the module to edit a ID3v2 tag with an embedded cover art image I end up with a corrupt tag. I have not further diagnosed to see what version of ID3v2 it actually is. ID3v2 does have the ability to read these coverart frames so I am confused why this causes an error.

I have searched and found nothing, so if anyone knows the answer why this happens I would appreciate it.

13 thoughts on “Perl ID3::Tag and Errors with Cover Art

  1. I just tested this real quick and it works. Although, at the moment it overwrites the rest of the id3 data.

    Just thought it might help you along in your quest. I’ll be following your progress 🙂

    code below (I tried the actual URL, but your comment script blocked it):

    ======================
    #!/usr/bin/perl -w
    #
    # Copyright 2004, Marcus Thiesen (marcus@thiesen.org)
    #
    # This program is free software; you can redistribute it and/or modify
    # it under the terms of either:
    #
    # a) the GNU General Public License as published by the Free Software
    # Foundation; either version 1, or (at your option) any later
    # version, or
    #
    # b) the “Artistic License” which comes with Perl.
    #
    # On Debian GNU/Linux systems, the complete text of the GNU General
    # Public License can be found in `/usr/share/common-licenses/GPL’ and
    # the Artistic Licence in `/usr/share/common-licenses/Artistic’.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    #
    #########################################################################
    #
    # Put an image into a MP3 File
    # ./id3image image mp3file…
    #
    # Prereq: Image::Magick, MP3::Tag
    # Version: 0.1
    #
    #########################################################################

    use strict;
    use warnings;

    use Image::Magick;
    use MP3::Tag;

    use constant APIC => “APIC”;
    use constant TYPE => “jpg”;
    use constant HEADER => ( chr(0x0) , “image/” . TYPE , chr(0x3), “Cover Image”);
    use constant DEBUG => 0;

    if (@ARGV < 2) { print "Usage: ./$0 image mp3file...\n"; exit 1; } my $imagefile = shift; my $image = new Image::Magick; if (my $x = $image->Read($imagefile)) {
    print “Couldn’t read the image $imagefile: $x\n”;
    }

    my $imagedata = $image->ImageToBlob(magick => TYPE );
    undef $image;

    foreach my $mp3file (@ARGV) {
    if ( ! -r $mp3file || ! -w $mp3file ) {
    print “File $mp3file is not rw\n”;
    next;
    }

    my $mp3 = MP3::Tag->new($mp3file);
    my @retvla = $mp3->get_tags();

    unless ($mp3) {
    print “Couldn’t read MP3 $mp3file: $!\n”;
    next;
    }

    my $id3;
    if (exists $mp3->{ID3v2}) {
    print “Using old ID3v2 tag\n” if DEBUG;
    $id3 = $mp3->{ID3v2};
    } else {
    print “Creating new ID3v2 tag\n” if DEBUG;
    $id3 = $mp3->new_tag(“ID3v2”);
    }

    my $frames = $id3->supported_frames();
    if (!exists $frames->{APIC}) {
    print “Something is wrong, APIC is not a supported frame!\n”;
    exit 2;
    }

    my $frameids = $id3->get_frame_ids();
    if (exists $$frameids{APIC}) {
    print “Replacing existing APIC entry\n” if DEBUG;
    $id3->change_frame(APIC, HEADER, $imagedata);
    } else {
    print “Creating new APIC entry\n” if DEBUG;
    $id3->add_frame(APIC,HEADER, $imagedata);
    }

    $id3->write_tag();
    $mp3->close();
    print “Successfully added Image to $mp3file\n”;

    }

  2. oh yeah, forgot to mention that I had the same corruption problem when messing with the Perl id3 mods.

    I’ll try and mess around with full id3 injection (all tags with image) when I get more time. I’ve been playing with your scripts (had to recode the file finding section of yours as I use a /artist/year-album/track-mp3 file structure.)

    Btw, Tag&Rename has been very good to me for checking that everything is looking good (yeah, we all have to resort to Windows now and then…).

  3. Using the script provided, the album art shows up in iTunes as a solid white picture. I’ve tried a number of ways to try and get cover art images encoded into the ID3v2 tag via perl with no luck. Anyone have a method that works?

  4. I’ve been struggling with this too – trying to embed all my WMP folder.jpg images into the mp3 for iTunes.

    I’ve found that my simple script below works fine for small images eg. AlbumArtSmall.jpg (apx 2kb) but fails for larger images, Folder.jpg (apx 7kb). So my script is missing something…

    use MP3::Tag;
    $mp3 = MP3::Tag->new(’04 Mamma Mia.mp3′);
    $mp3->get_tags;

    open IMG, ‘AlbumArtSmall.jpg’;
    $filesize = (-s IMG);
    binmode IMG;
    read(IMG, $imdata, $filesize);
    close IMG;

    $mp3->{ID3v2}->remove_frame(‘APIC’);
    $mp3->{ID3v2}->add_frame(‘APIC’,’image/jpeg’,”\0″,”Cover (front)”,$imdata);
    $mp3->{ID3v2}->write_tag();

  5. Bit more on this…

    It looks as if the image does get imported, regardless of the size, but iTunes doesn’t display the larger image correctly – try resizing the image window (or clicking in it).

    The images do appear to be corrupted, there are pixels missing on the bottom line when viewed in iTunes.

    Someone *must* know how to do this?!

  6. part of the problem with the writing of the album art (and I know, that’s not what the original post was about!) is this, in write_tag:

    # unsync ? global option should be good
    # unsync only if MPEG 2 layer I, II and III or MPEG 2.5 files.
    # do it twice to do correct unsnyc if several FF are following eachother
    $self->{tag_data} =~ s/\xFF([\x00\xE0-\xFF])/\xFF\x00$1/gos;
    $self->{tag_data} =~ s/\xFF([\xE0-\xFF])/\xFF\x00$1/gos;

    It garbles the jpg data… not sure what the unsynchronisation is about, but I think it should not be applied to the APIC tag….

  7. I did it! I have been successfully able to tag an mp3 file with both id3v1 and id3v2 tags including an image, that can be read in iTunes. I was able to fix the problem by *commenting out* a single line in my “/usr/lib/perl5/site_perl/5.8.0/MP3/Tag/ID3v2.pm” file. In my file it was line 615 which now reads:

    *#* $flags = chr(128) if $tag_data =~ s/\xFF(?=[\x00\xE0-\xFF])/\xFF\x00/g; # sync

    The following code now works with iTunes, provided the module is edited:

    #!/usr/local/bin/perl

    use MP3::Tag;
    use Image::Magick;

    $file = “file.mp3”;
    $jpg = “file.jpg”;

    my $image = new Image::Magick;
    if (my $x = $image->Read($jpg)) {
    print “Couldn’t read image ‘$jpg’\n”;
    }else{
    $imagedata = $image->ImageToBlob(magick => jpg);
    undef $image;
    }

    my $mp3 = MP3::Tag->new($file);
    $mp3->get_tags();

    $mp3->{ID3v2}->remove_tag() if exists $mp3->{ID3v2};
    $mp3->{ID3v1}->remove_tag() if exists $mp3->{ID3v1};

    my $id3v2 = $mp3->new_tag(“ID3v2”);
    $id3v2->add_frame(“TALB”, $album);
    $id3v2->add_frame(“TPE1”, $artist);
    $id3v2->add_frame(“TIT2”, $title);
    $id3v2->add_frame(“APIC”, chr(0x0), ‘image/jpg’, chr(0x0), ‘Cover (front)’, $imagedata);
    $id3v2->write_tag();

    my $id3v1 = $mp3->new_tag(“ID3v1”);
    $id3v1->song($title);
    $id3v1->artist($artist);
    $id3v1->album($album);
    $id3v1->write_tag();
    $mp3->close();

    Michael.

  8. Absolutely top class stuff, mate!

    Been trying to crack this for a while with various means but your solution works great.

    I’m using id3v2 to add all the other tags (via the same perl script) and that combination is working great.

    Thanks for solving this one!

    Steve

  9. In case there more frustrated people like me stumbling across this to find a solution to the MP3::Tag APIC errors with most tag editing software (eg mp3tag or mp3diag)… THERE IS A SOLUTION.
    You do NOT (now) have to hack the module code.
    MP3::Tag->config("id3v23_unsync_size_w",0);
    MP3::Tag->config("id3v23_unsync",0);

    Will fix it. Thanks to…
    Mikeyp

Leave a Reply

Your email address will not be published. Required fields are marked *