I would like to use TagLib to read/write coverart especially for mp3 AND ogg files, but I couldn't find any examples. Could someone point me to some examples? Where should I look to find more information about this?
How do I use TagLib to read/write coverart in different audio formats?
wikipedia says that mp3 and ogg have different tagging formats so its likely that the code below will only work for mp3. see this article en.wikipedia.org/wiki/ID3 –
Calque
Here is a version for mp3 and m4a.
#include <mpegfile.h>
#include <attachedpictureframe.h>
#include <id3v2tag.h>
#include <mp4file.h>
#include <mp4tag.h>
#include <mp4coverart.h>
#include <iostream>
class ImageFile : public TagLib::File
{
public:
ImageFile(const char *file) : TagLib::File(file)
{
}
TagLib::ByteVector data()
{
return readBlock(length());
}
private:
virtual TagLib::Tag *tag() const { return 0; }
virtual TagLib::AudioProperties *audioProperties() const { return 0; }
virtual bool save() { return false; }
};
int main(int argc, char *argv[])
{
if (argc != 3)
{
std::cout << "Usage: setcover <mp3|m4a> cover.jpg" << std::endl;
return 1;
}
TagLib::String fileName = argv[1];
TagLib::String fileType = fileName.substr(fileName.size() - 3).upper();
ImageFile imageFile(argv[2]);
if (fileType == "M4A")
{
// read the image file
TagLib::MP4::CoverArt coverArt((TagLib::MP4::CoverArt::Format) 0x0D, imageFile.data());
// read the mp4 file
TagLib::MP4::File audioFile(argv[1]);
// get the tag ptr
TagLib::MP4::Tag *tag = audioFile.tag();
// get the items map
TagLib::MP4::ItemListMap itemsListMap = tag->itemListMap();
// create cover art list
TagLib::MP4::CoverArtList coverArtList;
// append instance
coverArtList.append(coverArt);
// convert to item
TagLib::MP4::Item coverItem(coverArtList);
// add item to map
itemsListMap.insert("covr", coverItem);
tag->save();
//audioFile.save();
}
else if (fileType == "MP3")
{
TagLib::MPEG::File audioFile(argv[1]);
TagLib::ID3v2::Tag *tag = audioFile.ID3v2Tag(true);
TagLib::ID3v2::AttachedPictureFrame *frame = new TagLib::ID3v2::AttachedPictureFrame;
frame->setMimeType("image/jpeg");
frame->setPicture(imageFile.data());
tag->addFrame(frame);
audioFile.save();
}
else
{
std::cout << fileType << " is unsupported." << std::endl;
}
}
There's a bug in that code. The line: TagLib::MP4::ItemListMap itemsListMap = tag->itemListMap(); should be: TagLib::MP4::ItemListMap &itemsListMap = tag->itemListMap(); –
Ironsmith
I got it to work for mp3 files. See if you can adapt it for ogg
Good luck.
PS::This tagging stuff is way harder than it should be. We need to find another lib.
/*********************************************************************************************************************************
*Description: A simple program using taglib to extract pictures attached to mp3 id3v2 tags
*Author: Dr Deo [at] stackoverflow *dot* com
*AOB: I hope you will find this useful and are free to use it for anything, but there is no waranty and use at your own risk :)
*********************************************************************************************************************************
*/
#include<iostream>
#include<stdio.h>
/*taglib specific includes*/
#include<tbytevector.h>//ByteVector
#include<mpegfile.h>//mp3 file
#include<id3v2tag.h>//tag
#include<id3v2frame.h>//frame
#include <attachedPictureFrame.h>//attachedPictureFrame
using namespace std ;
using namespace TagLib::ID3v2 ;
int main(int argc, char * argv[])
{
if(argc !=2)
{
cout<<"usage: drag an mp3 file on to the program and it will extract the attached image"<<endl<<endl;
system("pause");//on linux you can replace this with cin.get()
exit(1);
}
TagLib::MPEG::File mp3File(argv[1]);
Tag * mp3Tag;
FrameList listOfMp3Frames;
AttachedPictureFrame * pictureFrame;
mp3Tag= mp3File.ID3v2Tag();
if(mp3Tag)
{
listOfMp3Frames = mp3Tag->frameListMap()["APIC"];//look for picture frames only
if(!listOfMp3Frames.isEmpty())
{
FrameList::ConstIterator it= listOfMp3Frames.begin();
for(; it != listOfMp3Frames.end() ; it++)
{
pictureFrame = static_cast<AttachedPictureFrame *> (*it);//cast Frame * to AttachedPictureFrame*
//Warning. format of picture assumed to be jpg. This may be false, for example it may be png.
FILE * fout;
fopen_s(&fout, "outputFile.jpg", "wb");
cout<<"processing the file "<< argv[1] <<endl<<endl;
fwrite(pictureFrame->picture().data(), pictureFrame->picture().size(), 1, fout);
fclose(fout);
cout<<" The picture has been written to \t outputFile.jpg \nRemember that the file type .jpg is just assumed for simplicity"<<endl<<endl;
}
}
else cerr<<"there seem to be no picture frames (APIC) frames in this file"<<endl<<endl;
}
else cerr<<"the file "<<argv[1]<<"does not appear to have any mp3 tags"<<endl<<endl;
system("pause");//on linux you can replace this with cin.get()
return 0;
}
Ogg Vorbis tags are text-only (and as such don't support cover art). For MP3s, this is somewhat cleaner than the other solution suggested:
using namespace TagLib;
struct Image
{
Image(const String &m = String(), const ByteVector &d = ByteVector()) :
mimeType(m), data(d) {}
String mimeType;
ByteVector data;
};
static Image getImage(const ID3v2::Tag *tag)
{
ID3v2::FrameList frames = tag->frameList("APIC");
if(frames.isEmpty())
{
return Image();
}
ID3v2::AttachedPictureFrame *frame =
static_cast<ID3v2::AttachedPictureFrame *>(frames.front());
return Image(frame->mimeType(), frame->picture());
}
static void setImage(ID3v2::Tag *tag, const Image &image)
{
ID3v2::FrameList frames = tag->frameList("APIC");
ID3v2::AttachedPictureFrame *frame = 0;
if(frames.isEmpty())
{
frame = new TagLib::ID3v2::AttachedPictureFrame;
tag->addFrame(frame);
}
else
{
frame = static_cast<ID3v2::AttachedPictureFrame *>(frames.front());
}
frame->setPicture(image.data);
frame->setMimeType(image.mimeType);
}
I didn't know that there is no official support for cover art in Ogg files. This would explain the problems with a lot media players out there :-( –
Kerrin
Ogg does support album-arts, even though it's 'text-only'. –
Maloy
It's somewhat amusing that I've been down-voted a couple times on this: I am the author of TagLib. At the time I wrote this comment, Xiph tags did not in fact support images (and the spec specifically recommended using a separate meta-data stream). They have since added the base64 text option. –
Rationality
Hi scotchi, your answer is now obsolete, in my opinion. Please see meta.#266249 More specifically: "voting is meant to push good content to the top, and if content become obsolete, it is no longer good. It should be pushed down below more up-to-date content." –
Maloy
Here is a complete solution, including Ogg. The unofficial way of doing it has been to base64 encode the file and embed it in the metadata. There is now a proposed (better) way of base64 encoding a FLAC Picture block (which may include the image data, or a file:// URL).
© 2022 - 2024 — McMap. All rights reserved.