diff --git a/cexif.cpp b/cexif.cpp index 41df91b..0ca62ce 100644 --- a/cexif.cpp +++ b/cexif.cpp @@ -32,66 +32,179 @@ bool cEXIF::fromFile(const QString& szFileName) m_szFileName = ""; - Exiv2::Image::UniquePtr image = Exiv2::ImageFactory::open(szFileName.toLocal8Bit().toStdString()); - if(!image.get()) - return(false); - - image->readMetadata(); - - Exiv2::ExifData& exifData = image->exifData(); - - m_iWidth = image->pixelWidth(); - m_iHeight = image->pixelHeight(); - m_szFileName = szFileName; - - if(!exifData.empty()) + try { - Exiv2::ExifData::const_iterator end = exifData.end(); - for(Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) - { - cEXIFTag* lpTag = m_exifTagList.find(i->tag(), i->ifdId()); + Exiv2::Image::UniquePtr image = Exiv2::ImageFactory::open(szFileName.toLocal8Bit().toStdString()); + if(!image.get()) + return(false); - if(lpTag) + image->readMetadata(); + + Exiv2::ExifData& exifData = image->exifData(); + Exiv2::IptcData& iptcData = image->iptcData(); + Exiv2::XmpData& xmpData = image->xmpData(); + + m_iWidth = image->pixelWidth(); + m_iHeight = image->pixelHeight(); + + m_szFileName = szFileName; + + if(!iptcData.empty()) + { + Exiv2::IptcData::const_iterator end = iptcData.end(); + + for(Exiv2::IptcData::const_iterator i = iptcData.begin(); i != end; ++i) { - cEXIFValue* lpValue = m_exifValueList.add(lpTag); - if(lpValue) - lpValue->setValue(QString::fromStdString(i->value().toString()), i->typeId(), i->count()); + cIPTCTag* lpTag = m_iptcTagList.find(i->tag()); + + if(lpTag) + { + cIPTCValue* lpValue = m_iptcValueList.add(lpTag); + if(lpValue) + lpValue->setValue(QString::fromStdString(i->value().toString()), i->typeId(), i->count()); + } + } + + Exiv2::PreviewManager previewManager(*image); + Exiv2::PreviewPropertiesList previewPropertiesList = previewManager.getPreviewProperties(); + + for(Exiv2::PreviewPropertiesList::const_iterator i = previewPropertiesList.begin();i != previewPropertiesList.end();i++) + { + Exiv2::PreviewImage previewImage = previewManager.getPreviewImage(*i); + QImage image; + image.loadFromData(static_cast(previewImage.pData()), static_cast(previewImage.size())); + + QTransform rotation; + int angle = 0; + + switch(imageOrientation()) + { + case 8: + angle = 270; + break; + case 3: + angle = 180; + break; + case 6: + angle = 90; + break; + } + + if(angle != 0) + { + rotation.rotate(angle); + image = image.transformed(rotation); + } + + m_previewList.append(image); } } - Exiv2::PreviewManager previewManager(*image); - Exiv2::PreviewPropertiesList previewPropertiesList = previewManager.getPreviewProperties(); - - for(Exiv2::PreviewPropertiesList::const_iterator i = previewPropertiesList.begin();i != previewPropertiesList.end();i++) + if(!xmpData.empty()) { - Exiv2::PreviewImage previewImage = previewManager.getPreviewImage(*i); - QImage image; - image.loadFromData(static_cast(previewImage.pData()), static_cast(previewImage.size())); + Exiv2::XmpData::const_iterator end = xmpData.end(); - QTransform rotation; - int angle = 0; - - switch(imageOrientation()) + for(Exiv2::XmpData::const_iterator i = xmpData.begin(); i != end; ++i) { - case 8: - angle = 270; - break; - case 3: - angle = 180; - break; - case 6: - angle = 90; - break; + cXMPTag* lpTag = m_xmpTagList.find(QString::fromStdString(i->key())); + + if(lpTag) + { + cXMPValue* lpValue = m_xmpValueList.add(lpTag); + if(lpValue) + lpValue->setValue(QString::fromStdString(i->value().toString()), i->typeId(), i->count()); + } } - if(angle != 0) - { - rotation.rotate(angle); - image = image.transformed(rotation); - } + Exiv2::PreviewManager previewManager(*image); + Exiv2::PreviewPropertiesList previewPropertiesList = previewManager.getPreviewProperties(); - m_previewList.append(image); + for(Exiv2::PreviewPropertiesList::const_iterator i = previewPropertiesList.begin();i != previewPropertiesList.end();i++) + { + Exiv2::PreviewImage previewImage = previewManager.getPreviewImage(*i); + QImage image; + image.loadFromData(static_cast(previewImage.pData()), static_cast(previewImage.size())); + + QTransform rotation; + int angle = 0; + + switch(imageOrientation()) + { + case 8: + angle = 270; + break; + case 3: + angle = 180; + break; + case 6: + angle = 90; + break; + } + + if(angle != 0) + { + rotation.rotate(angle); + image = image.transformed(rotation); + } + + m_previewList.append(image); + } } + + if(!exifData.empty()) + { + Exiv2::ExifData::const_iterator end = exifData.end(); + for(Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) + { + cEXIFTag* lpTag = m_exifTagList.find(i->tag(), i->ifdId()); + + if(lpTag) + { + cEXIFValue* lpValue = m_exifValueList.add(lpTag); + if(lpValue) + lpValue->setValue(QString::fromStdString(i->value().toString()), i->typeId(), i->count()); + } + } + + Exiv2::PreviewManager previewManager(*image); + Exiv2::PreviewPropertiesList previewPropertiesList = previewManager.getPreviewProperties(); + + for(Exiv2::PreviewPropertiesList::const_iterator i = previewPropertiesList.begin();i != previewPropertiesList.end();i++) + { + Exiv2::PreviewImage previewImage = previewManager.getPreviewImage(*i); + QImage image; + image.loadFromData(static_cast(previewImage.pData()), static_cast(previewImage.size())); + + QTransform rotation; + int angle = 0; + + switch(imageOrientation()) + { + case 8: + angle = 270; + break; + case 3: + angle = 180; + break; + case 6: + angle = 90; + break; + } + + if(angle != 0) + { + rotation.rotate(angle); + image = image.transformed(rotation); + } + + m_previewList.append(image); + } + } + } + catch (Exiv2::AnyError& e) + { + qDebug() << "Caught Exiv2 exception '" << e.what(); + return(false); } if(!m_previewList.count()) @@ -174,7 +287,12 @@ qint32 cEXIF::imageWidth() if(m_iWidth) return(m_iWidth); - return(getTag(0x0100, 1).value()); + qint32 iWidth = getEXIFTag(0x0100, 1).value(); + + if(iWidth) + return(iWidth); + + return(getXMPTag("Xmp.video.Width").value()); } qint32 cEXIF::imageHeight() @@ -182,69 +300,91 @@ qint32 cEXIF::imageHeight() if(m_iHeight) return(m_iHeight); - return(getTag(0x0101, 1).value()); + qint32 iHeight = getEXIFTag(0x0101, 1).value(); + + if(iHeight) + return(iHeight); + + return(getXMPTag("Xmp.video.Height").value()); } qint16 cEXIF::imageOrientation() { - return(getTag(0x0112, 1).value()); + return(getEXIFTag(0x0112, 1).value()); } QString cEXIF::cameraMake() { - return(getTag(0x010f, 1).value()); + QString szCameraMake = getEXIFTag(0x010f, 1).toString(); + + if(!szCameraMake.isEmpty()) + return(szCameraMake); + + return(getXMPTag("Xmp.video.MajorBrand").toString()); } QString cEXIF::cameraModel() { - return(getTag(0x0110, 1).value()); + QString szCameraModel = getEXIFTag(0x0110, 1).toString(); + + if(!szCameraModel.isEmpty()) + return(szCameraModel); + + return(getXMPTag("Xmp.video.MajorBrand").toString()); } QDateTime cEXIF::dateTime() { - QDateTime dateTime = QDateTime::fromString(getTag(0x0132, 1).value(), "yyyy:MM:dd hh:mm:ss"); + QDateTime dateTime = QDateTime::fromString(getEXIFTag(0x0132, 1).value(), "yyyy:MM:dd hh:mm:ss"); + if(dateTime.isValid()) + return(dateTime); - return(dateTime); + dateTime = QDateTime::fromString(getXMPTag("Xmp.video.DateTimeDigitized").toString(), "yyyy-MM-ddThh:mm:ssZ"); + if(dateTime.isValid()) + return(dateTime); + + QFileInfo info(m_szFileName); + return(info.birthTime()); } QString cEXIF::fNumber() { - return(getTag(0x829d, 5).value()); + return(getEXIFTag(0x829d, 5).value()); } qint32 cEXIF::iso() { - return(getTag(0x8827, 5).value()); + return(getEXIFTag(0x8827, 5).value()); } QString cEXIF::flash() { - return(m_exifFlashList.flash(getTag(0x9209, 5).value())); + return(m_exifFlashList.flash(getEXIFTag(0x9209, 5).value())); } qint32 cEXIF::flashID() { - return(getTag(0x9209, 5).value()); + return(getEXIFTag(0x9209, 5).value()); } qreal cEXIF::focalLength() { - return(getTag(0x920a, 5).value()); + return(getEXIFTag(0x920a, 5).value()); } QString cEXIF::lensMake() { - return(getTag(0xa433, 5).value()); + return(getEXIFTag(0xa433, 5).value()); } QString cEXIF::lensModel() { - return(getTag(0xa434, 5).value()); + return(getEXIFTag(0xa434, 5).value()); } QString cEXIF::exposureTime() { - qreal value = getTag(0x829a, 5).value(); + qreal value = getEXIFTag(0x829a, 5).value(); if(value == 0.0) return("error"); @@ -257,32 +397,32 @@ QString cEXIF::exposureTime() qint32 cEXIF::exposureBias() { - return(getTag(0x9204, 5).value()); + return(getEXIFTag(0x9204, 5).value()); } QString cEXIF::exifVersion() { - return(getTag(0x9000, 5).value()); + return(getEXIFTag(0x9000, 5).value()); } QDateTime cEXIF::dateTimeOriginal() { - return(QDateTime::fromString(getTag(0x9003, 5).value(), "yyyy:MM:dd hh:mm:ss")); + return(QDateTime::fromString(getEXIFTag(0x9003, 5).value(), "yyyy:MM:dd hh:mm:ss")); } QDateTime cEXIF::dateTimeDigitized() { - return(QDateTime::fromString(getTag(0x9004, 5).value(), "yyyy:MM:dd hh:mm:ss")); + return(QDateTime::fromString(getEXIFTag(0x9004, 5).value(), "yyyy:MM:dd hh:mm:ss")); } qint32 cEXIF::whiteBalance() { - return(getTag(0xa403, 5).value()); + return(getEXIFTag(0xa403, 5).value()); } qreal cEXIF::focalLength35() { - return(getTag(0xa405, 5).value()); + return(getEXIFTag(0xa405, 5).value()); } QString cEXIF::gps() @@ -295,7 +435,7 @@ QString cEXIF::gps() if(eList.count() != 3) return(""); - QString szGPS = QString("%1 %2° %3' %4\" %5 %6° %7' %8\"").arg(getTag(0x0001, 6).value()).arg(nList[0].value()).arg(nList[1].value()).arg(nList[2].value()).arg(getTag(0x0001, 6).value()).arg(eList[0].value()).arg(eList[1].value()).arg(eList[2].value()); + QString szGPS = QString("%1 %2° %3' %4\" %5 %6° %7' %8\"").arg(getEXIFTag(0x0001, 6).value()).arg(nList[0].value()).arg(nList[1].value()).arg(nList[2].value()).arg(getEXIFTag(0x0001, 6).value()).arg(eList[0].value()).arg(eList[1].value()).arg(eList[2].value()); return(szGPS); } @@ -314,7 +454,7 @@ QImage cEXIF::thumbnail() return(m_thumbnail); } -QVariant cEXIF::getTag(qint32 iTAGID, qint32 iIFDID) +QVariant cEXIF::getEXIFTag(qint32 iTAGID, qint32 iIFDID) { cEXIFTag* lpTag = m_exifTagList.find(iTAGID, iIFDID); @@ -329,6 +469,36 @@ QVariant cEXIF::getTag(qint32 iTAGID, qint32 iIFDID) return(lpValue->value()); } +QVariant cEXIF::getIPTCTag(qint32 iTAGID) +{ + cIPTCTag* lpTag = m_iptcTagList.find(iTAGID); + + if(!lpTag) + return(QVariant()); + + cIPTCValue* lpValue = m_iptcValueList.find(lpTag); + + if(!lpValue) + return(QVariant()); + + return(lpValue->value()); +} + +QVariant cEXIF::getXMPTag(const QString& szTAGName) +{ + cXMPTag* lpTag = m_xmpTagList.find(szTAGName); + + if(!lpTag) + return(QVariant()); + + cXMPValue* lpValue = m_xmpValueList.find(lpTag); + + if(!lpValue) + return(QVariant()); + + return(lpValue->value()); +} + QList cEXIF::getTagList(qint32 iTAGID, qint32 iIFDID) { cEXIFTag* lpTag = m_exifTagList.find(iTAGID, iIFDID); @@ -1015,3 +1185,363 @@ cEXIFValue* cEXIFValueList::find(cEXIFTag* lpEXIFTag) } return(nullptr); } + +cIPTCTag::cIPTCTag(const qint32& iTAGID, const QString& szTAGName, const qint32& iTypeID, const QString& szDescription) : + m_iTAGID(iTAGID), + m_szTAGName(szTAGName), + m_iTypeID(iTypeID), + m_szDescription(szDescription) +{ +} + +cIPTCTagList::cIPTCTagList() +{ +// add(0x000b, QObject::tr("ProcessingSoftware"), 1, 2, QObject::tr("The name and version of the software used to post-process the picture.")); +} + +cIPTCTag* cIPTCTagList::add(const qint32& iTAGID, const QString& szTAGName, const qint32& iTypeID, const QString& szDescription) +{ + cIPTCTag* lpNew = find(iTAGID); + + if(lpNew) + return(nullptr); + + lpNew = new cIPTCTag(iTAGID, szTAGName, iTypeID, szDescription); + append(lpNew); + return(lpNew); +} + +cIPTCTag* cIPTCTagList::find(const qint32& iTAGID) +{ + for(int x = 0;x < count();x++) + { + cIPTCTag* lpTag = at(x); + + if(lpTag->m_iTAGID == iTAGID) + return(lpTag); + } + return(nullptr); +} + +cIPTCTag* cIPTCValue::iptcTag() +{ + return(m_lpIPTCTag); +} + +cIPTCValue::cIPTCValue(cIPTCTag* lpIPTCTag) : + m_lpIPTCTag(lpIPTCTag) +{ +} + +QVariant cIPTCValue::convertValue(const QString& szValue, qint32 iTypeId) +{ + QVariant variant; + + switch(iTypeId) + { + case 1: //byte + case 3: //short + case 4: //long + case 8: //signed short + variant = QVariant::fromValue(szValue.toLong()); + break; + case 5: //rational + case 10: //signed rational + case 11: //float + if(szValue.contains("/")) + { + QStringList tmp = szValue.split("/"); + variant = QVariant::fromValue(tmp[0].toDouble()/tmp[1].toDouble()); + } + else + variant = QVariant::fromValue(szValue.toDouble()); + break; + default: + variant = szValue; + } + return(variant); +} + +void cIPTCValue::setValue(const QString& szValue, qint32 iTypeId, qint32 iCount) +{ + if(iCount == 1 || iTypeId == 2 || iTypeId == 7) + { + m_valueList.append(convertValue(szValue, iTypeId)); + return; + } + + QStringList valueList = szValue.split(" "); + + if(valueList.count() != iCount) + return; + + for(int x = 0;x < iCount;x++) + m_valueList.append(convertValue(valueList[x], iTypeId)); +} + +QVariant cIPTCValue::value() +{ + if(m_valueList.count()) + return(m_valueList[0]); + + return(QVariant()); +} + +QList cIPTCValue::valueList() +{ + return(m_valueList); +} + +cIPTCValueList::cIPTCValueList() +{ +} + +cIPTCValue* cIPTCValueList::add(cIPTCTag* lpIPTCTag) +{ + cIPTCValue* lpNew = find(lpIPTCTag); + + if(lpNew) + return(nullptr); + + lpNew = new cIPTCValue(lpIPTCTag); + + append(lpNew); + return(lpNew); +} + +cIPTCValue* cIPTCValueList::find(cIPTCTag* lpIPTCTag) +{ + for(int x = 0;x < count();x++) + { + cIPTCValue* lpValue = at(x); + if(lpValue->iptcTag() == lpIPTCTag) + return(lpValue); + } + return(nullptr); +} + +cXMPTag::cXMPTag(const QString& szTAGName, const qint32& iTypeID, const QString& szDescription) : + m_szTAGName(szTAGName), + m_iTypeID(iTypeID), + m_szDescription(szDescription) +{ +} + +cXMPTagList::cXMPTagList() +{ + add("Xmp.video.FileSize", 65541, QObject::tr("File Size")); + add("Xmp.video.FileName", 65541, QObject::tr("File Name")); + add("Xmp.video.MimeType", 65541, QObject::tr("Mime Type")); + add("Xmp.video.Container", 65541, QObject::tr("Container Type")); + add("Xmp.video.FileType", 65541, QObject::tr("File Type")); + add("Xmp.video.MicroSecPerFrame", 65541, QObject::tr("Micro Seconds Per Frame")); + add("Xmp.video.MaxDataRate", 65541, QObject::tr("Maximum Data Rate")); + add("Xmp.video.FrameCount", 65541, QObject::tr("Frame Count")); + add("Xmp.video.StreamCount", 65541, QObject::tr("Stream Count")); + add("Xmp.video.Width", 65541, QObject::tr("Video Width")); + add("Xmp.video.Height", 65541, QObject::tr("Video Height")); + add("Xmp.video.AspectRatio", 65541, QObject::tr("Video Aspect Ratio")); + add("Xmp.video.FileDataRate", 65541, QObject::tr("File Data Rate")); + add("Xmp.video.Duration", 65541, QObject::tr("Duration")); + add("Xmp.video.Codec", 65541, QObject::tr("Video Codec")); + add("Xmp.video.FrameRate", 65541, QObject::tr("Video Frame Rate")); + add("Xmp.video.VideoQuality", 65541, QObject::tr("Video Quality")); + add("Xmp.video.VideoSampleSize", 65541, QObject::tr("Video Sample Size")); + add("Xmp.video.Planes", 65541, QObject::tr("Planes")); + add("Xmp.video.PixelDepth", 65541, QObject::tr("Video Pixel Depth")); + add("Xmp.video.Compressor", 65541, QObject::tr("Compressor")); + add("Xmp.video.ImageLength", 65541, QObject::tr("Image Length")); + add("Xmp.video.PixelPerMeterX", 65541, QObject::tr("Pixels Per Meter X")); + add("Xmp.video.PixelPerMeterY", 65541, QObject::tr("Pixels Per Meter Y")); + add("Xmp.video.NumOfColours", 65541, QObject::tr("Number Of Colours")); + add("Xmp.video.NumOfImpColours", 65541, QObject::tr("Number Of Important Colours")); + add("Xmp.audio.Codec", 65541, QObject::tr("Audio Codec")); + add("Xmp.audio.SampleRate", 65541, QObject::tr("Audio Sample Rate")); + add("Xmp.audio.SampleCount", 65541, QObject::tr("Audio Sample Count")); + add("Xmp.audio.Compressor", 65541, QObject::tr("Audio Compressor")); + add("Xmp.audio.ChannelType", 65541, QObject::tr("Audio Channel Type")); + add("Xmp.audio.SampleType", 65541, QObject::tr("Audio Sample Type")); + add("Xmp.audio.BitsPerSample", 65541, QObject::tr("Bits Per Sample/ Bit Rate")); + add("Xmp.video.TotalFrameCount", 65541, QObject::tr("Total Frame Count")); + add("Xmp.video.DateTimeDigitized", 65541, QObject::tr("Date and Time Digitized")); + add("Xmp.video.Junk", 65541, QObject::tr("Junk Data")); + add("Xmp.video.MajorBrand", 65541, QObject::tr("QTime Major FileType Brand")); + add("Xmp.video.MinorVersion", 65541, QObject::tr("QTime Minor FileType Version")); + add("Xmp.video.CompatibleBrands", 65544, QObject::tr("QTime Compatible FileType Brand")); + add("Xmp.video.CompressorVersion", 65541, QObject::tr("Compressor Version")); + add("Xmp.video.HandlerType", 65541, QObject::tr("Handler Type")); + add("Xmp.video.PreviewDate", 65541, QObject::tr("Preview Date")); + add("Xmp.video.PreviewVersion", 65541, QObject::tr("Preview Version")); + add("Xmp.video.PreviewAtomType", 65541, QObject::tr("Preview Atom Type")); + add("Xmp.video.MovieHeaderVersion", 65541, QObject::tr("Movie Header Version")); + add("Xmp.video.DateUTC", 65541, QObject::tr("Date")); + add("Xmp.video.ModificationDate", 65541, QObject::tr("Modification Date")); + add("Xmp.video.TimeScale", 65541, QObject::tr("Time Scale")); + add("Xmp.video.PreferredRate", 65541, QObject::tr("Preferred Rate")); + add("Xmp.video.PreferredVolume", 65541, QObject::tr("Preferred Volume")); + add("Xmp.video.PreviewTime", 65541, QObject::tr("Preview Time")); + add("Xmp.video.PreviewDuration", 65541, QObject::tr("Preview Duration")); + add("Xmp.video.PosterTime", 65541, QObject::tr("Poster Time")); + add("Xmp.video.SelectionTime", 65541, QObject::tr("Selection Time")); + add("Xmp.video.SelectionDuration", 65541, QObject::tr("Selection Duration")); + add("Xmp.video.CurrentTime", 65541, QObject::tr("Current Time")); + add("Xmp.video.NextTrackID", 65541, QObject::tr("Next Track ID")); + add("Xmp.video.TrackHeaderVersion", 65541, QObject::tr("Track Header Version")); + add("Xmp.video.TrackCreateDate", 65541, QObject::tr("Video Track Create Date")); + add("Xmp.video.TrackModifyDate", 65541, QObject::tr("Video Track Modify Date")); + add("Xmp.video.TrackID", 65541, QObject::tr("Track ID")); + add("Xmp.video.TrackDuration", 65541, QObject::tr("Video Track Duration")); + add("Xmp.video.TrackLayer", 65541, QObject::tr("Video Track Layer")); + add("Xmp.video.TrackVolume", 65541, QObject::tr("Track Volume")); + add("Xmp.video.MediaHeaderVersion", 65541, QObject::tr("Media Header Version")); + add("Xmp.video.MediaCreateDate", 65541, QObject::tr("Media Track Create Date")); + add("Xmp.video.MediaModifyDate", 65541, QObject::tr("Media Track Modify Date")); + add("Xmp.video.MediaTimeScale", 65541, QObject::tr("Media Time Scale")); + add("Xmp.video.MediaDuration", 65541, QObject::tr("Media Track Duration")); + add("Xmp.video.MediaLangCode", 65541, QObject::tr("Media Language Code")); + add("Xmp.video.HandlerClass", 65541, QObject::tr("Handler Class")); + add("Xmp.video.GraphicsMode", 65541, QObject::tr("Graphics Mode")); + add("Xmp.video.OpColor", 65541, QObject::tr("Operation Colours")); + add("Xmp.video.SourceImageWidth", 65541, QObject::tr("Source Image Width")); + add("Xmp.video.SourceImageHeight", 65541, QObject::tr("Source Image Height")); + add("Xmp.video.XResolution", 65541, QObject::tr("X Resolution")); + add("Xmp.video.YResolution", 65541, QObject::tr("Y Resolution")); + add("Xmp.video.BitDepth", 65541, QObject::tr("Bit Depth")); + add("Xmp.audio.TrackHeaderVersion", 65541, QObject::tr("Track Header Version")); + add("Xmp.audio.TrackCreateDate", 65541, QObject::tr("Audio Track Create Date")); + add("Xmp.audio.TrackModifyDate", 65541, QObject::tr("Audio Track Modify Date")); + add("Xmp.audio.TrackID", 65541, QObject::tr("Track ID")); + add("Xmp.audio.TrackDuration", 65541, QObject::tr("Audio Track Duration")); + add("Xmp.audio.TrackLayer", 65541, QObject::tr("Audio Track Layer")); + add("Xmp.audio.MediaHeaderVersion", 65541, QObject::tr("Media Header Version")); + add("Xmp.audio.MediaCreateDate", 65541, QObject::tr("Media Track Create Date")); + add("Xmp.audio.MediaModifyDate", 65541, QObject::tr("Media Track Modify Date")); + add("Xmp.audio.MediaTimeScale", 65541, QObject::tr("Media Time Scale")); + add("Xmp.audio.MediaDuration", 65541, QObject::tr("Media Track Duration")); + add("Xmp.audio.MediaLangCode", 65541, QObject::tr("Media Language Code")); + add("Xmp.audio.HandlerClass", 65541, QObject::tr("Handler Class")); + add("Xmp.audio.HandlerType", 65541, QObject::tr("Handler Type")); + add("Xmp.audio.Balance", 65541, QObject::tr("Balance")); +} + +cXMPTag* cXMPTagList::add(const QString& szTAGName, const qint32& iTypeID, const QString& szDescription) +{ + cXMPTag* lpNew = find(szTAGName); + + if(lpNew) + return(nullptr); + + lpNew = new cXMPTag(szTAGName, iTypeID, szDescription); + append(lpNew); + return(lpNew); +} + +cXMPTag* cXMPTagList::find(const QString& szTAGName) +{ + for(int x = 0;x < count();x++) + { + cXMPTag* lpTag = at(x); + + if(lpTag->m_szTAGName == szTAGName) + return(lpTag); + } + return(nullptr); +} + +cXMPTag* cXMPValue::xmpTag() +{ + return(m_lpXMPTag); +} + +cXMPValue::cXMPValue(cXMPTag* lpXMPTag) : + m_lpXMPTag(lpXMPTag) +{ +} + +QVariant cXMPValue::convertValue(const QString& szValue, qint32 iTypeId) +{ + QVariant variant; + + switch(iTypeId) + { + case 1: //byte + case 3: //short + case 4: //long + case 8: //signed short + variant = QVariant::fromValue(szValue.toLong()); + break; + case 5: //rational + case 10: //signed rational + case 11: //float + if(szValue.contains("/")) + { + QStringList tmp = szValue.split("/"); + variant = QVariant::fromValue(tmp[0].toDouble()/tmp[1].toDouble()); + } + else + variant = QVariant::fromValue(szValue.toDouble()); + break; + default: + variant = szValue; + } + return(variant); +} + +void cXMPValue::setValue(const QString& szValue, qint32 iTypeId, qint32 iCount) +{ +// if(iCount == 1 || iTypeId == 2 || iTypeId == 7) +// { +// m_valueList.append(convertValue(szValue, iTypeId)); +// return; +// } + +// QStringList valueList = szValue.split(" "); + +// if(valueList.count() != iCount) +// return; + +// for(int x = 0;x < iCount;x++) +// m_valueList.append(convertValue(valueList[x], iTypeId)); + m_valueList.append(convertValue(szValue, iTypeId)); +} + +QVariant cXMPValue::value() +{ + if(m_valueList.count()) + return(m_valueList[0]); + + return(QVariant()); +} + +QList cXMPValue::valueList() +{ + return(m_valueList); +} + +cXMPValueList::cXMPValueList() +{ +} + +cXMPValue* cXMPValueList::add(cXMPTag* lpXMPTag) +{ + cXMPValue* lpNew = find(lpXMPTag); + + if(lpNew) + return(nullptr); + + lpNew = new cXMPValue(lpXMPTag); + + append(lpNew); + return(lpNew); +} + +cXMPValue* cXMPValueList::find(cXMPTag* lpXMPTag) +{ + for(int x = 0;x < count();x++) + { + cXMPValue* lpValue = at(x); + if(lpValue->xmpTag() == lpXMPTag) + return(lpValue); + } + return(nullptr); +} diff --git a/cexif.h b/cexif.h index d323c62..d6bd808 100644 --- a/cexif.h +++ b/cexif.h @@ -317,6 +317,270 @@ public: cEXIFValue* find(cEXIFTag* lpEXIFTag); }; +/** + * @brief + * + */ +class cIPTCTag +{ +public: + cIPTCTag(const qint32& iTAGID, const QString& szTAGName, const qint32& iTypeID, const QString& szDescription); + + qint32 m_iTAGID; /*!< TODO: describe */ + QString m_szTAGName; /*!< TODO: describe */ + qint32 m_iTypeID; /*!< TODO: describe */ + QString m_szDescription; /*!< TODO: describe */ +}; + +Q_DECLARE_METATYPE(cIPTCTag*) + +/*! + \brief + + \class cIPTCTagList cexif.h "cexif.h" +*/ +class cIPTCTagList : public QList +{ +public: + cIPTCTagList(); + + /*! + \brief + + \fn add + \param iTAGID + \param szTAGName + \param iTypeID + \param szDescription + \return cIPTCTag + */ + cIPTCTag* add(const qint32& iTAGID, const QString& szTAGName, const qint32& iTypeID, const QString& szDescription); + /*! + \brief + + \fn find + \param iTAGID + \return cIPTCTag + */ + cIPTCTag* find(const qint32& iTAGID); +}; + +/*! + \brief + +*/ +class cIPTCValue +{ +public: + cIPTCValue(cIPTCTag* lpIPTCTag); + + /*! + \brief + + \fn iptcTag + \return cIPTCTag + */ + cIPTCTag* iptcTag(); + /*! + \brief + + \fn setValue + \param szValue + \param iTypeId + \param iCount + */ + void setValue(const QString& szValue, qint32 iTypeId, qint32 iCount = 1); + /*! + \brief + + \fn value + \return QVariant + */ + QVariant value(); + /*! + \brief + + \fn valueList + \return QList + */ + QList valueList(); + +private: + cIPTCTag* m_lpIPTCTag; /*!< TODO: describe */ + QList m_valueList; /*!< TODO: describe */ + + /*! + \brief + + \fn convertValue + \param szValue + \param iTypeId + \return QVariant + */ + QVariant convertValue(const QString& szValue, qint32 iTypeId); +}; + +Q_DECLARE_METATYPE(cIPTCValue*) + +/*! + \brief + + \class cIPTCValueList cexif.h "cexif.h" +*/ +class cIPTCValueList : public QList +{ +public: + cIPTCValueList(); + + /*! + \brief + + \fn add + \param lpIPTCTag + \return cIPTCValue + */ + cIPTCValue* add(cIPTCTag* lpIPTCTag); + /*! + \brief + + \fn find + \param lpIPTCTag + \return cIPTCValue + */ + cIPTCValue* find(cIPTCTag* lpIPTCTag); +}; + +/** + * @brief + * + */ +class cXMPTag +{ +public: + cXMPTag(const QString& szTAGName, const qint32& iTypeID, const QString& szDescription); + + QString m_szTAGName; /*!< TODO: describe */ + qint32 m_iTypeID; /*!< TODO: describe */ + QString m_szDescription; /*!< TODO: describe */ +}; + +Q_DECLARE_METATYPE(cXMPTag*) + +/*! + \brief + + \class cXMPTagList cexif.h "cexif.h" +*/ +class cXMPTagList : public QList +{ +public: + cXMPTagList(); + + /*! + \brief + + \fn add + \param szTAGName + \param iTypeID + \param szDescription + \return cXMPTag + */ + cXMPTag* add(const QString& szTAGName, const qint32& iTypeID, const QString& szDescription); + /*! + \brief + + \fn find + \param szTAGName + \return cXMPTag + */ + cXMPTag* find(const QString& szTAGName); +}; + +/*! + \brief + +*/ +class cXMPValue +{ +public: + cXMPValue(cXMPTag* lpXMPTag); + + /*! + \brief + + \fn exifTag + \return cXMPTag + */ + cXMPTag* xmpTag(); + /*! + \brief + + \fn setValue + \param szValue + \param iTypeId + \param iCount + */ + void setValue(const QString& szValue, qint32 iTypeId, qint32 iCount = 1); + /*! + \brief + + \fn value + \return QVariant + */ + QVariant value(); + /*! + \brief + + \fn valueList + \return QList + */ + QList valueList(); + +private: + cXMPTag* m_lpXMPTag; /*!< TODO: describe */ + QList m_valueList; /*!< TODO: describe */ + + /*! + \brief + + \fn convertValue + \param szValue + \param iTypeId + \return QVariant + */ + QVariant convertValue(const QString& szValue, qint32 iTypeId); +}; + +Q_DECLARE_METATYPE(cXMPValue*) + +/*! + \brief + + \class cXMPValueList cexif.h "cexif.h" +*/ +class cXMPValueList : public QList +{ +public: + cXMPValueList(); + + /*! + \brief + + \fn add + \param lpXMPTag + \return cXMPValue + */ + cXMPValue* add(cXMPTag* lpXMPTag); + /*! + \brief + + \fn find + \param lpXMPTag + \return cXMPValue + */ + cXMPValue* find(cXMPTag* lpXMPTag); +}; + /*! \brief @@ -507,6 +771,8 @@ public: private: cEXIFValueList m_exifValueList; /*!< TODO: describe */ + cIPTCValueList m_iptcValueList; /*!< TODO: describe */ + cXMPValueList m_xmpValueList; /*!< TODO: describe */ qint32 m_iWidth; /*!< TODO: describe */ qint32 m_iHeight; /*!< TODO: describe */ QString m_szFileName; /*!< TODO: describe */ @@ -518,15 +784,35 @@ private: cEXIFFlashList m_exifFlashList; /*!< TODO: describe */ cEXIFTagList m_exifTagList; /*!< TODO: describe */ + cIPTCTagList m_iptcTagList; /*!< TODO: describe */ + + cXMPTagList m_xmpTagList; /*!< TODO: describe */ + /*! \brief - \fn getTag + \fn getEXIFTag \param iTAGID \param iIFDID \return QVariant */ - QVariant getTag(qint32 iTAGID, qint32 iIFDID); + QVariant getEXIFTag(qint32 iTAGID, qint32 iIFDID); + /*! + \brief + + \fn getIPTCTag + \param iTAGID + \return QVariant + */ + QVariant getIPTCTag(qint32 iTAGID); + /*! + \brief + + \fn getXMPTag + \param szTAGName + \return QVariant + */ + QVariant getXMPTag(const QString& szTAGName); /*! \brief diff --git a/cimportdialog.cpp b/cimportdialog.cpp index 147b8c0..27d9f5b 100644 --- a/cimportdialog.cpp +++ b/cimportdialog.cpp @@ -90,6 +90,9 @@ void cImportDialog::initUI() ui->m_lpCopy->setChecked(true); else ui->m_lpMove->setChecked(true); + + ui->m_lpPictures->setChecked(settings.value("import/pictures", QVariant::fromValue(true)).toBool()); + ui->m_lpVideos->setChecked(settings.value("import/videos", QVariant::fromValue(true)).toBool()); ui->m_lpDetectHDR->setChecked(settings.value("import/detectHDR", QVariant::fromValue(true)).toBool()); ui->m_lpDetectJPG_RAW->setChecked(settings.value("import/detectJPG_RAW", QVariant::fromValue(true)).toBool()); } @@ -185,6 +188,8 @@ void cImportDialog::savePosition() settings.setValue(QString("main/splitter%1").arg(x+1), QVariant::fromValue(sizes[x])); settings.setValue("import/recursive", QVariant::fromValue(ui->m_lpRecursive->isChecked())); + settings.setValue("import/pictures", QVariant::fromValue(ui->m_lpRecursive->isChecked())); + settings.setValue("import/videos", QVariant::fromValue(ui->m_lpRecursive->isChecked())); settings.setValue("import/copy", QVariant::fromValue(ui->m_lpCopy->isChecked())); settings.setValue("import/detectHDR", QVariant::fromValue(ui->m_lpDetectHDR->isChecked())); settings.setValue("import/detectJPG_RAW", QVariant::fromValue(ui->m_lpDetectJPG_RAW->isChecked())); @@ -274,9 +279,11 @@ void cImportDialog::readDirectory(const QString& szPath, bool bRecursive) { QMimeDatabase mimeDB; QDir dir(szPath); - QStringList szDirs = dir.entryList(QDir::Dirs); - QFileInfoList szFiles = dir.entryInfoList(QDir::Files); + QStringList szDirs = dir.entryList(QDir::Dirs); + QFileInfoList szFiles = dir.entryInfoList(QDir::Files); QDateTime oldDateTime; + bool bPictures = ui->m_lpPictures->isChecked(); + bool bVideos = ui->m_lpVideos->isChecked(); if(bRecursive) { @@ -292,7 +299,7 @@ void cImportDialog::readDirectory(const QString& szPath, bool bRecursive) QFileInfo fileInfo = szFiles[x]; QMimeType mimeType = mimeDB.mimeTypeForFile(szFiles[x]); - if(mimeType.name().startsWith("image")) + if((mimeType.name().startsWith("image") && bPictures) || (mimeType.name().startsWith("video") && bVideos)) { ui->m_lpStatusText->setText(QString(tr("found %1")).arg(fileInfo.fileName())); qApp->processEvents(); diff --git a/cimportdialog.ui b/cimportdialog.ui index f96cc31..4ee1723 100644 --- a/cimportdialog.ui +++ b/cimportdialog.ui @@ -7,7 +7,7 @@ 0 0 697 - 510 + 536 @@ -15,7 +15,7 @@ - + @@ -40,11 +40,39 @@ - - - recursive - - + + + + + recursive + + + + + + + + + + + pictures + + + true + + + + + + + videos + + + true + + + + @@ -194,7 +222,7 @@ 0 0 69 - 316 + 342 @@ -257,6 +285,22 @@ 1 + + m_lpPath + m_lpPathSelect + m_lpRecursive + m_lpPictures + m_lpVideos + m_lpCopy + m_lpMove + m_lpDetectHDR + m_lpDetectJPG_RAW + m_lpRead + m_lpImport + m_lpFolderView + m_lpThumbnailView + scrollArea + diff --git a/cmainwindow.cpp b/cmainwindow.cpp index d570e5d..f04e3e8 100644 --- a/cmainwindow.cpp +++ b/cmainwindow.cpp @@ -41,7 +41,6 @@ cMainWindow::cMainWindow(cSplashScreen* lpSplashScreen, QWidget *parent) : { initUI(); createActions(); - loadData(); updateRecentFileActions(); diff --git a/cpicture.cpp b/cpicture.cpp index a849b20..56397aa 100644 --- a/cpicture.cpp +++ b/cpicture.cpp @@ -58,16 +58,16 @@ bool cPicture::fromFile(const QString& szFileName) m_imageWidth = exif.imageWidth(); m_imageHeight = exif.imageHeight(); m_imageOrientation = exif.imageOrientation(); - m_cameraMake = exif.cameraMake(); - m_cameraModel = exif.cameraModel(); + m_cameraMake = exif.cameraMake().simplified(); + m_cameraModel = exif.cameraModel().simplified(); m_dateTime = exif.dateTime(); m_fNumber = exif.fNumber(); m_iso = exif.iso(); - m_flash = exif.flash(); + m_flash = exif.flash().simplified(); m_flashID = exif.flashID(); m_focalLength = exif.focalLength(); - m_lensMake = exif.lensMake(); - m_lensModel = exif.lensModel(); + m_lensMake = exif.lensMake().simplified(); + m_lensModel = exif.lensModel().simplified(); m_exposureTime = exif.exposureTime(); m_exposureBias = exif.exposureBias(); m_exifVersion = exif.exifVersion(); @@ -414,6 +414,206 @@ QImage cPicture::thumbnail() return(m_thumbnail); } +bool cPicture::operator==(const cPicture& other) const +{ + if(this->m_szFileName != other.m_szFileName) + return(false); + if(this->m_iFileSize != other.m_iFileSize) + return(false); + if(this->m_imageWidth != other.m_imageWidth) + return(false); + if(this->m_imageHeight != other.m_imageHeight) + return(false); + if(this->m_imageOrientation != other.m_imageOrientation) + return(false); + if(this->m_cameraMake != other.m_cameraMake) + return(false); + if(this->m_cameraModel != other.m_cameraModel) + return(false); + if(this->m_dateTime != other.m_dateTime) + return(false); + if(this->m_fNumber != other.m_fNumber) + return(false); + if(this->m_iso != other.m_iso) + return(false); + if(this->m_flashID != other.m_flashID) + return(false); + if(this->m_focalLength != other.m_focalLength) + return(false); + if(this->m_lensMake != other.m_lensMake) + return(false); + if(this->m_lensModel != other.m_lensModel) + return(false); + if(this->m_exposureTime != other.m_exposureTime) + return(false); + if(this->m_exposureBias != other.m_exposureBias) + return(false); + if(this->m_exifVersion != other.m_exifVersion) + return(false); + if(this->m_dateTimeOriginal != other.m_dateTimeOriginal) + return(false); + if(this->m_dateTimeDigitized != other.m_dateTimeDigitized) + return(false); + if(this->m_whiteBalance != other.m_whiteBalance) + return(false); + if(this->m_focalLength35 != other.m_focalLength35) + return(false); + if(this->m_gps != other.m_gps) + return(false); + + return(true); +} + +bool cPicture::operator==(const cPicture*& other) const +{ + if(this->m_szFileName != other->m_szFileName) + return(false); + if(this->m_iFileSize != other->m_iFileSize) + return(false); + if(this->m_imageWidth != other->m_imageWidth) + return(false); + if(this->m_imageHeight != other->m_imageHeight) + return(false); + if(this->m_imageOrientation != other->m_imageOrientation) + return(false); + if(this->m_cameraMake != other->m_cameraMake) + return(false); + if(this->m_cameraModel != other->m_cameraModel) + return(false); + if(this->m_dateTime != other->m_dateTime) + return(false); + if(this->m_fNumber != other->m_fNumber) + return(false); + if(this->m_iso != other->m_iso) + return(false); + if(this->m_flashID != other->m_flashID) + return(false); + if(this->m_focalLength != other->m_focalLength) + return(false); + if(this->m_lensMake != other->m_lensMake) + return(false); + if(this->m_lensModel != other->m_lensModel) + return(false); + if(this->m_exposureTime != other->m_exposureTime) + return(false); + if(this->m_exposureBias != other->m_exposureBias) + return(false); + if(this->m_exifVersion != other->m_exifVersion) + return(false); + if(this->m_dateTimeOriginal != other->m_dateTimeOriginal) + return(false); + if(this->m_dateTimeDigitized != other->m_dateTimeDigitized) + return(false); + if(this->m_whiteBalance != other->m_whiteBalance) + return(false); + if(this->m_focalLength35 != other->m_focalLength35) + return(false); + if(this->m_gps != other->m_gps) + return(false); + + return(true); +} + +bool cPicture::operator==(const cPicture* other) const +{ + if(this->m_szFileName != other->m_szFileName) + return(false); + if(this->m_iFileSize != other->m_iFileSize) + return(false); + if(this->m_imageWidth != other->m_imageWidth) + return(false); + if(this->m_imageHeight != other->m_imageHeight) + return(false); + if(this->m_imageOrientation != other->m_imageOrientation) + return(false); + if(this->m_cameraMake != other->m_cameraMake) + return(false); + if(this->m_cameraModel != other->m_cameraModel) + return(false); + if(this->m_dateTime != other->m_dateTime) + return(false); + if(this->m_fNumber != other->m_fNumber) + return(false); + if(this->m_iso != other->m_iso) + return(false); + if(this->m_flashID != other->m_flashID) + return(false); + if(this->m_focalLength != other->m_focalLength) + return(false); + if(this->m_lensMake != other->m_lensMake) + return(false); + if(this->m_lensModel != other->m_lensModel) + return(false); + if(this->m_exposureTime != other->m_exposureTime) + return(false); + if(this->m_exposureBias != other->m_exposureBias) + return(false); + if(this->m_exifVersion != other->m_exifVersion) + return(false); + if(this->m_dateTimeOriginal != other->m_dateTimeOriginal) + return(false); + if(this->m_dateTimeDigitized != other->m_dateTimeDigitized) + return(false); + if(this->m_whiteBalance != other->m_whiteBalance) + return(false); + if(this->m_focalLength35 != other->m_focalLength35) + return(false); + if(this->m_gps != other->m_gps) + return(false); + + return(true); +} + +bool cPicture::operator==(cPicture* other) +{ + if(this->m_szFileName != other->m_szFileName) + return(false); + if(this->m_iFileSize != other->m_iFileSize) + return(false); + if(this->m_imageWidth != other->m_imageWidth) + return(false); + if(this->m_imageHeight != other->m_imageHeight) + return(false); + if(this->m_imageOrientation != other->m_imageOrientation) + return(false); + if(this->m_cameraMake != other->m_cameraMake) + return(false); + if(this->m_cameraModel != other->m_cameraModel) + return(false); + if(this->m_dateTime != other->m_dateTime) + return(false); + if(this->m_fNumber != other->m_fNumber) + return(false); + if(this->m_iso != other->m_iso) + return(false); + if(this->m_flashID != other->m_flashID) + return(false); + if(this->m_focalLength != other->m_focalLength) + return(false); + if(this->m_lensMake != other->m_lensMake) + return(false); + if(this->m_lensModel != other->m_lensModel) + return(false); + if(this->m_exposureTime != other->m_exposureTime) + return(false); + if(this->m_exposureBias != other->m_exposureBias) + return(false); + if(this->m_exifVersion != other->m_exifVersion) + return(false); + if(this->m_dateTimeOriginal != other->m_dateTimeOriginal) + return(false); + if(this->m_dateTimeDigitized != other->m_dateTimeDigitized) + return(false); + if(this->m_whiteBalance != other->m_whiteBalance) + return(false); + if(this->m_focalLength35 != other->m_focalLength35) + return(false); + if(this->m_gps != other->m_gps) + return(false); + + return(true); +} + cPictureList::cPictureList(QObject *parent) : QObject(parent) { @@ -558,3 +758,13 @@ cPicture* cPictureList::find(qint32 iID) } return(nullptr); } + +cPicture* cPictureList::find(cPicture* lpPicture) +{ + for(int i = 0;i < count();i++) + { + if(*lpPicture == *at(i)) + return(at(i)); + } + return(nullptr); +} diff --git a/cpicture.h b/cpicture.h index 0bf0aab..d3ef5a6 100644 --- a/cpicture.h +++ b/cpicture.h @@ -443,6 +443,42 @@ public: */ QImage thumbnail(); + /*! + \brief + + \fn operator== + \param other + \return bool + */ + bool operator==(const cPicture& other) const; + + /*! + \brief + + \fn operator== + \param other + \return bool + */ + bool operator==(const cPicture*& other) const; + + /*! + \brief + + \fn operator== + \param other + \return bool + */ + bool operator==(const cPicture* other) const; + + /*! + \brief + + \fn operator== + \param other + \return bool + */ + bool operator==(cPicture* other); + signals: public slots: @@ -523,6 +559,7 @@ public: \return bool */ bool add(cPicture* lpPicture, bool bNoCheck = false); + /*! \brief @@ -531,6 +568,14 @@ public: \return cPicture */ cPicture* find(qint32 iID); + /*! + \brief + + \fn find + \param iID + \return cPicture + */ + cPicture* find(cPicture* lpPicture); signals: diff --git a/pictureLibrary.pro b/pictureLibrary.pro index 4606c57..ab60ec4 100644 --- a/pictureLibrary.pro +++ b/pictureLibrary.pro @@ -10,7 +10,7 @@ QMAKE_TARGET_PRODUCT = pictureLibrary QMAKE_TARGET_DESCRIPTION = pictureLibrary QMAKE_TARGET_COPYRIGHT = (c) 2019 WIN-DESIGN -QT += core gui sql +QT += core gui sql multimedia greaterThan(QT_MAJOR_VERSION, 4): QT += widgets