File indexing completed on 2024-04-21 15:22:27

0001 /*
0002     A command line tool to set faces in Picassa format
0003 
0004     SPDX-FileCopyrightText: 2013 Munteanu Veaceslav <slavuttici at gmail dot com>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 // Qt includes
0010 
0011 #include <QString>
0012 #include <QFile>
0013 #include <QDebug>
0014 
0015 // Local includes
0016 
0017 #include "kexiv2.h"
0018 
0019 using namespace KExiv2Iface;
0020 
0021 bool setFaceTags(KExiv2& meta,const char* xmpTagName,const QMap<QString,QRectF>& faces,
0022                      bool setProgramName)
0023 {
0024 
0025         Q_UNUSED(setProgramName);
0026         meta.setXmpTagString(xmpTagName,QString(),KExiv2::XmpTagType(1),false);
0027 
0028         QString qxmpTagName(QString::fromLatin1(xmpTagName));
0029         QString nameTagKey     = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Name");
0030         QString typeTagKey     = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Type");
0031         QString areaTagKey     = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Area");
0032         QString areaxTagKey    = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Area/stArea:x");
0033         QString areayTagKey    = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Area/stArea:y");
0034         QString areawTagKey    = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Area/stArea:w");
0035         QString areahTagKey    = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Area/stArea:h");
0036         QString areanormTagKey = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Area/stArea:unit");
0037 
0038         QMap<QString,QRectF>::const_iterator it = faces.constBegin();
0039         int i =1;
0040         while(it != faces.constEnd())
0041         {
0042             qreal x,y,w,h;
0043             it.value().getRect(&x,&y,&w,&h);
0044             /** Set tag name **/
0045             meta.setXmpTagString(nameTagKey.arg(i).toLatin1().constData(),it.key(),
0046                                  KExiv2::XmpTagType(0),false);
0047             /** Set tag type as Face **/
0048             meta.setXmpTagString(typeTagKey.arg(i).toLatin1().constData(),QString::fromLatin1("Face"),
0049                                  KExiv2::XmpTagType(0),false);
0050             /** Set tag Area, with xmp type struct **/
0051             meta.setXmpTagString(areaTagKey.arg(i).toLatin1().constData(),QString(),
0052                                  KExiv2::XmpTagType(2),false);
0053             /** Set stArea:x inside Area structure **/
0054             meta.setXmpTagString(areaxTagKey.arg(i).toLatin1().constData(),QString::number(x),
0055                                  KExiv2::XmpTagType(0),false);
0056             /** Set stArea:y inside Area structure **/
0057             meta.setXmpTagString(areayTagKey.arg(i).toLatin1().constData(),QString::number(y),
0058                                  KExiv2::XmpTagType(0),false);
0059             /** Set stArea:w inside Area structure **/
0060             meta.setXmpTagString(areawTagKey.arg(i).toLatin1().constData(),QString::number(w),
0061                                  KExiv2::XmpTagType(0),false);
0062             /** Set stArea:h inside Area structure **/
0063             meta.setXmpTagString(areahTagKey.arg(i).toLatin1().constData(),QString::number(h),
0064                                  KExiv2::XmpTagType(0),false);
0065             /** Set stArea:unit inside Area structure  as normalized **/
0066             meta.setXmpTagString(areanormTagKey.arg(i).toLatin1().constData(),QString::fromLatin1("normalized"),
0067                                  KExiv2::XmpTagType(0),false);
0068 
0069             ++it;
0070             ++i;
0071         }
0072 
0073     return true;
0074 
0075 }
0076 
0077 void removeFaceTags(KExiv2& meta,const char* xmpTagName)
0078 {
0079         QString qxmpTagName(QString::fromLatin1(xmpTagName));
0080         QString regionTagKey   = qxmpTagName + QString::fromLatin1("[%1]");
0081         QString nameTagKey     = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Name");
0082         QString typeTagKey     = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Type");
0083         QString areaTagKey     = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Area");
0084         QString areaxTagKey    = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Area/stArea:x");
0085         QString areayTagKey    = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Area/stArea:y");
0086         QString areawTagKey    = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Area/stArea:w");
0087         QString areahTagKey    = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Area/stArea:h");
0088         QString areanormTagKey = qxmpTagName + QString::fromLatin1("[%1]/mwg-rs:Area/stArea:unit");
0089 
0090         meta.removeXmpTag(xmpTagName,false);
0091         bool dirty = true;
0092         int i      =1;
0093 
0094         while(dirty)
0095         {
0096             dirty = false;
0097             dirty |=meta.removeXmpTag(regionTagKey.arg(i).toLatin1().constData(),false);
0098             dirty |=meta.removeXmpTag(nameTagKey.arg(i).toLatin1().constData(),false);
0099             dirty |=meta.removeXmpTag(typeTagKey.arg(i).toLatin1().constData(),false);
0100             dirty |=meta.removeXmpTag(areaTagKey.arg(i).toLatin1().constData(),false);
0101             dirty |=meta.removeXmpTag(areaxTagKey.arg(i).toLatin1().constData(),false);
0102             dirty |=meta.removeXmpTag(areayTagKey.arg(i).toLatin1().constData(),false);
0103             dirty |=meta.removeXmpTag(areawTagKey.arg(i).toLatin1().constData(),false);
0104             dirty |=meta.removeXmpTag(areahTagKey.arg(i).toLatin1().constData(),false);
0105             dirty |=meta.removeXmpTag(areanormTagKey.arg(i).toLatin1().constData(),false);
0106             i++;
0107         }
0108 }
0109 
0110 int main (int argc, char **argv)
0111 {
0112     if (argc != 3)
0113     {
0114         qDebug() << "Adding a face rectangle to image";
0115         qDebug() << "Usage: <add/remove> <image>";
0116         return -1;
0117     }
0118 
0119     QString filePath(QString::fromLatin1(argv[2]));
0120 
0121     KExiv2Iface::KExiv2::initializeExiv2();
0122     KExiv2 meta;
0123     meta.load(filePath);
0124     meta.setWriteRawFiles(true);
0125 
0126     /** Add a random rectangle with facetag Bob **/
0127     QString name = QString::fromLatin1("Bob Marley");
0128     float x =0.5;
0129     float y =0.5;
0130     float w = 60;
0131     float h = 60;
0132 
0133     QRectF rect(x,y,w,h);
0134 
0135     QMap<QString, QRectF> faces;
0136 
0137     faces[name] = rect;
0138 
0139     QString name2 = QString::fromLatin1("Hello Kitty!");
0140     QRectF rect2(0.4,0.4,30,30);
0141 
0142     faces[name2] = rect2;
0143 
0144     bool g = meta.supportXmp();
0145 
0146     qDebug() << "Image support XMP" << g;
0147 
0148     const QString bag = QString::fromLatin1("Xmp.mwg-rs.Regions/mwg-rs:RegionList");
0149 
0150     QString op(QString::fromLatin1(argv[1]));
0151 
0152     if (op == QString::fromLatin1("add"))
0153         setFaceTags(meta,bag.toLatin1().constData(),faces,false);
0154     else
0155         removeFaceTags(meta,bag.toLatin1().constData());
0156 
0157     meta.applyChanges();
0158 
0159     QString recoverName = QString::fromLatin1("Xmp.mwg-rs.Regions/mwg-rs:RegionList[1]/mwg-rs:Name");
0160 
0161     KExiv2 meta2;
0162     meta2.load(filePath);
0163     meta2.setWriteRawFiles(true);
0164 
0165     QString nameR = meta2.getXmpTagString(recoverName.toLatin1().constData(),false);
0166 
0167     qDebug() << "Saved name is:" << nameR;
0168 
0169     KExiv2Iface::KExiv2::cleanupExiv2();
0170     return 0;
0171 }