Printing title of mp3 file - c++

I am trying to read id3 tags with id3v2lib
My code is:
ID3v2_tag* tag = load_tag(argv[1]); // Load the full tag from the file
if(!tag){
tag = new_tag();
}
const char * t = "Matej";
ID3v2_frame* artist_frame = tag_get_artist(tag); // Get the full artist frame
ID3v2_frame* title_frame = tag_get_title(tag);
ID3v2_frame_text_content* title_content = parse_text_frame_content(title_frame);
if( title_content){
cout << title_content->data << endl;
}
This does print title of song. However, for some files it prints unreadable garbage.
I am not sure if the file is somehow corrupted. But using
eyeD3 on files that outputs garbage for title works fine.
Has anyone met with same problem? What could be the cause

Related

How to store old txt lines and store new output to new line on iostream (C++)

To begin with C++, I prepare a user registration and log-in program.The program I write records the information into the file.But when I open the program again, it wipes out the old record and re-writes it back.
I tried to define string and get input from text but it failed.
using namespace std;
void saveuser() {
string datausername = "test";//User name to save or read from txt
string datapassword = "pass";//password to save or read from txt
string datarealname = "realname";//Real name of the user
ofstream database;
database.open ("userdatabase.txt");
database << datausername.c_str();
database << " , ";
database << datapassword.c_str();
database << " , ";
database << datarealname.c_str();
database.close();
}
I want to store all users information on separate lines.
Like, User1's details : User1 , Pass1 , UserName1
and in other line User2 , Pass2 , UserName2
Sounds like you would like to append to the file.
To append to a file, pass the mode argument of std::ofstream::app into the open function.
Example:
void saveuser() {
....
ofstream database;
database.open ("userdatabase.txt", std::ofstream::out, | std::ofstream::app);
...
}
This will not overwrite the previous contents of the file.

findAndGetString() in DCMTK returns null for the tag

I am developing a quick DICOM viewer using DCMTK library and I am following the example provided in this link.
The buffer from the API always returns null for any tag ID, eg: DCM_PatientName.
But the findAndGetOFString() API works fine but returns only the first character of the tag in ASCII, is this how this API should work?
Can someone let me know why the buffer is empty the former API?
Also the DicomImage API also the same issue.
Snippet 1:
DcmFileFormat fileformat;
OFCondition status = fileformat.loadFile(test_data_file_path.toStdString().c_str());
if (status.good())
{
OFString patientName;
char* name;
if (fileformat.getDataset()->findAndGetOFString(DCM_PatientName, patientName).good())
{
name = new char[patientName.length()];
strcpy(name, patientName.c_str());
}
else
{
qDebug() << "Error: cannot access Patient's Name!";
}
}
else
{
qDebug() << "Error: cannot read DICOM file (" << status.text() << ")";
}
In the above snippet name has the ASCII value "50" and the actual name is "PATIENT".
Snippet 2:
DcmFileFormat file_format;
OFCondition status = file_format.loadFile(test_data_file_path.toStdString().c_str());
std::shared_ptr<DcmDataset> dataset(file_format.getDataset());
qDebug() << "\nInformation extracted from DICOM file: \n";
const char* buffer = nullptr;
DcmTagKey key = DCM_PatientName;
dataset->findAndGetString(key,buffer);
std::string tag_value = buffer;
qDebug() << "Patient name: " << tag_value.c_str();
In the above snippet, the buffer is null. It doesn't read the name.
NOTE:
This is only a sample. I am just playing around the APIs for learning
purpose.
The following sample method reads the patient name from a DcmDataset object:
std::string getPatientName(DcmDataset& dataset)
{
// Get the tag's value in ofstring
OFString ofstring;
OFCondition condition = dataset.findAndGetOFString(DCM_PatientName, ofstring);
if(condition.good())
{
// Tag found. Put it in a std::string and return it
return std::string(ofstring.c_str());
}
// Tag not found
return ""; // or throw if you need the tag
}
I have tried your code with your datasets. I just replaced the output to QT console classes to std::cout. It works for me - i.e. it prints the correct patient name (e.g. "PATIENT2" for scan2.dcm). Everything seems correct, except for the fact that you apparently want to transfer the ownership for the dataset to a smart pointer.
To obtain the ownership for the DcmDataset from the DcmFileFormat, you must call getAndRemoveDataset() instead of getDataset(). However, I do not think that your issue is related that. You may want to try my modified snippet:
DcmFileFormat file_format;
OFCondition status = file_format.loadFile("d:\\temp\\StackOverflow\\scan2.dcm");
std::shared_ptr<DcmDataset> dataset(file_format.getAndRemoveDataset());
std::cout << "\nInformation extracted from DICOM file: \n";
const char* buffer = nullptr;
DcmTagKey key = DCM_PatientName;
dataset->findAndGetString(key, buffer);
std::string tag_value = buffer;
std::cout << "Patient name: " << tag_value.c_str();
It probably helps you to know that your code and the dcmtk methods you use are correct, but that does not solve your problem. Another thing I would recommend is to verify the result returned by file_format.loadFile(). Maybe there is a surprise in there.
Not sure if I can help you more, but my next step would be to verify your build environment, e.g. the options that you use for building dcmtk. Are you using CMake to build dcmtk?

Overwrite an image/pixel data in the dicom file using dcmtk

I use dcmtk to read a dicom file and extract the image into a .tiff format. After doing some image processing I have an image which I would like to save in the source dicom file.That is overwriting the old image/pixel data with my new ones, while keeping rest of the data(uid,patient name,,etc) same.
I use the following code to read dicom
OFCondition status = src_fileformat.loadFile(src_path);
if (status.good())
{
Sint32 instanceNumber = 0;
if (src_fileformat.getDataset()->findAndGetSint32(DCM_InstanceNumber, instanceNumber).good())
{
cout << "instance Number N: " << instanceNumber << endl;
sprintf(instanceNum, "%d", instanceNumber);
printf("%s\n", instanceNum);
}
else
cerr << "Error: cannot access Instance Number!" << endl;
}
else
cerr << "Error: cannot read DICOM file (" << status.text() << ")" << endl;
src_dcm = new DicomImage(src_path);
if (src_dcm != NULL)
{
if (src_dcm->getStatus() == EIS_Normal)
{
if (src_dcm->isMonochrome())
{
src_dcm->setMinMaxWindow();
Uint8 *pixelData = (Uint8 *)(src_dcm->getOutputData(16 /* bits */));
if (pixelData != NULL)
{
src_dcm->writeBMP("source.tiff", 24); /* do something useful with the pixel data */
}
}
}
else
cerr << "Error: cannot load DICOM image (" << DicomImage::getString(src_dcm->getStatus()) << ")" << endl;
}
After image processing I have an image that I want to overwrite onto this source dicom file. I looked into image2dcm,but I couldn't get the correct syntax/method to do. any one help me out.. :)
Edit-1
Image2Dcm i2d;
I2DOutputPlug *outPlug = new I2DOutputPlugSC();
I2DImgSource *inputPlug = new I2DJpegSource();
E_TransferSyntax writeXfer;
inputPlug->setImageFile(jpgFile);
DcmDataset *dataset = NULL;
OFCondition result = i2d.convert(inputPlug, outPlug, dataset, writeXfer);
// Saving output DICOM image
if (result.good())
{
dataset->putAndInsertString(DCM_PhotometricInterpretation,"RGB");
DcmFileFormat dcmff(dataset);
result = dcmff.saveFile(dcmFile, writeXfer);
}
I tried the above shown syntax,but couldn't exactly understand it
This is the processed image(above)
This is the original dicom image that I want to overwrite. Guys ,any idea or help??
The basic approach should be:
load the DICOM dataset from file
replace the pixel data in the dataset
modify various other element values (e.g. SOP Instance UID)
save the modified DICOM dataset to a new file
In case of uncompressed images, the second step could be performed in the same manner as the third step, i.e. by an appropriate call of a putAndInsertXXX() method on the dataset. Of course, the element value of the Pixel Data attribute should be in correct DICOM format. See DICOM standard part 3 and 5 for details.

Metadata of audio file

hi all i am extracting metadata of an audio file using Taglib library . i am getting many fields properly but not able to extract name of source device by which the audio file has been created. Please suggest any way to get out of it. Code used is as below
MetaData md;
const char * filename = file.c_str();
std::cout<< filename;
FileRef f((FileName(filename)));
md.filepath = file;
//if(f.isNull()) return md;
// if(!f.tag()) return md;
// if(f.tag()->isEmpty()) return md;
string artist = f.tag()->artist().toCString();
string album = f.tag()->album().toCString();
string title = f.tag()->title().toCString();//.to8Bit(true);
uint year = f.tag()->year();
uint track = f.tag()->track();
int bitrate = f.audioProperties()->bitrate();
string comment=f.tag()->comment().toCString();
string genre =f.tag()->genre().toCString();
// length in second
int lenght=f.file()->audioProperties()->length();
int channel = f.file()->audioProperties()->channels();
string name =f.file()->name();
int sampleRate=f.audioProperties()->sampleRate();
What exactly do you mean with "name of source device by which the audio file has been created"? Are you looking for the name of the person or organisation that encoded the audio file, normally saved in the TENC tag?
Could you give us an example, what you want to see?

Using taglib in a Qt application

I'd like to get the length of a media file in a qt application i'm building and so i decided to use taglib. This is the methos that is meant to read the length
void loadMetaData(QString file) {
QByteArray fileName = QFile::encodeName( file );
const char * encodedName = fileName.constData();
TagLib::FileRef fileref = TagLib::FileRef( encodedName );
if (fileref.isNull())
{
qDebug() << "Null";
}
else
{
qDebug() << "Not Null";
}
}
Problem is fileref is always null for some reason and i can't figure out why......
Use the getter audioProperties() on your FileRef object. The returned pointer contains the length of the file in seconds.
TagLib# is able to work with some Theora files. I used it in a project but found it wouldn't work with many Theora videos (I don't think any converted using libtheora 1.1 worked).
TagLib.File file = TagLib.File.Create(#"c:\video.ogv");
string height = file.Properties.VideoHeight;
This is for the .NET, not C++ though.