void KMLGPSDataParser::CreateTrackPoints(QDomElement& parent, QDomDocument& root, int timeZone, int altitudeMode) { kmlDocument = &root; //kDebug(AREA_CODE_LOADING) << "creation d'un trackpoint" ; // create the points QDomElement kmlPointsFolder = addKmlElement(parent, QLatin1String("Folder")); addKmlTextElement(kmlPointsFolder, QLatin1String("name"), i18n("Points")); addKmlTextElement(kmlPointsFolder, QLatin1String("visibility"), QLatin1String("0")); addKmlTextElement(kmlPointsFolder, QLatin1String("open"), QLatin1String("0")); int i = 0; // cache the end to not recalculate it with large number of points GPSDataMap::ConstIterator end (m_GPSDataMap.constEnd()); for (GPSDataMap::ConstIterator it = m_GPSDataMap.constBegin(); it != end; ++it, ++i) { QDomElement kmlPointPlacemark = addKmlElement(kmlPointsFolder, QLatin1String("Placemark")); addKmlTextElement(kmlPointPlacemark, QLatin1String("name"), QString::fromUtf8("%1 %2 ").arg(i18n("Point")).arg(i)); addKmlTextElement(kmlPointPlacemark, QLatin1String("styleUrl"), QLatin1String("#track")); QDomElement kmlTimeStamp = addKmlElement(kmlPointPlacemark, QLatin1String("TimeStamp")); // GPS device are sync in time by satellite using GMT time. // If the camera time is different than GMT time, we want to // convert the GPS time to localtime of the picture to be display // in the same timeframe QDateTime GPSLocalizedTime = it.key().addSecs(timeZone*3600); addKmlTextElement(kmlTimeStamp, QLatin1String("when"), GPSLocalizedTime.toString(QLatin1String("yyyy-MM-ddThh:mm:ssZ"))); QDomElement kmlGeometry = addKmlElement(kmlPointPlacemark, QLatin1String("Point")); addKmlTextElement(kmlPointPlacemark, QLatin1String("visibility"), QLatin1String("0")); if (it.value().latitude()) { addKmlTextElement(kmlGeometry, QLatin1String("coordinates"), QString::fromUtf8("%1,%2,%3 ") .arg(it.value().longitude()).arg(it.value().latitude()).arg(it.value().altitude())); } else { addKmlTextElement(kmlGeometry, QLatin1String("coordinates"), QString::fromUtf8("%1,%2 ").arg(it.value().longitude()).arg(it.value().latitude())); } if (altitudeMode == 2 ) { addKmlTextElement(kmlGeometry, QLatin1String("altitudeMode"), QLatin1String("absolute")); } else if (altitudeMode == 1 ) { addKmlTextElement(kmlGeometry, QLatin1String("altitudeMode"), QLatin1String("relativeToGround")); } else { addKmlTextElement(kmlGeometry, QLatin1String("altitudeMode"), QLatin1String("clampToGround")); } } }
/*! \fn KmlExport::addTrack(QDomElement &kmlAlbum) */ void KmlExport::addTrack(QDomElement& kmlAlbum) { if( m_GPXFile.isEmpty() ) { logWarning(i18n("No GPX file chosen.")); return; } m_gpxParser.clear(); bool ret = m_gpxParser.loadGPXFile(m_GPXFile); if (!ret) { logError(i18n("Cannot parse %1 GPX file.",m_GPXFile)); return; } if (m_gpxParser.numPoints() <= 0) { logError(i18n("The %1 GPX file do not have a date-time track to use.", m_GPXFile)); return; } // create a folder that will contain tracks and points QDomElement kmlFolder = addKmlElement(kmlAlbum, "Folder"); addKmlTextElement(kmlFolder, "name", i18n("Tracks")); if (!m_optimize_googlemap) { // style of points and track QDomElement kmlTrackStyle = addKmlElement(kmlAlbum, "Style"); kmlTrackStyle.setAttribute("id","track"); QDomElement kmlIconStyle = addKmlElement(kmlTrackStyle, "IconStyle"); QDomElement kmlIcon = addKmlElement(kmlIconStyle, "Icon"); //! FIXME is there a way to be sure of the location of the icon? addKmlTextElement(kmlIcon, "href", "http://maps.google.com/mapfiles/kml/pal4/icon60.png"); m_gpxParser.CreateTrackPoints(kmlFolder, *m_kmlDocument, m_TimeZone - 12, m_GPXAltitudeMode); } // linetrack style QDomElement kmlLineTrackStyle = addKmlElement(kmlAlbum, "Style"); kmlLineTrackStyle.setAttribute("id","linetrack"); QDomElement kmlLineStyle = addKmlElement(kmlLineTrackStyle, "LineStyle"); // the KML color is not #RRGGBB but AABBGGRR QString KMLColorValue = QString("%1%2%3%4") .arg((int)m_GPXOpacity*256/100, 2, 16) .arg((&m_GPXColor)->blue(), 2, 16) .arg((&m_GPXColor)->green(), 2, 16) .arg((&m_GPXColor)->red(), 2, 16); addKmlTextElement(kmlLineStyle, "color", KMLColorValue); addKmlTextElement(kmlLineStyle, "width", QString("%1").arg(m_LineWidth) ); m_gpxParser.CreateTrackLine(kmlAlbum, *m_kmlDocument, m_GPXAltitudeMode); }
void KMLGPSDataParser::CreateTrackLine(QDomElement& parent, QDomDocument& root, int altitudeMode) { kmlDocument = &root; // add the linetrack QDomElement kmlPlacemark = addKmlElement(parent, QLatin1String("Placemark")); addKmlTextElement(kmlPlacemark, QLatin1String("name"), i18n("Track")); QDomElement kmlLineString = addKmlElement(kmlPlacemark, QLatin1String("LineString")); addKmlTextElement(kmlLineString, QLatin1String("coordinates"), lineString()); addKmlTextElement(kmlPlacemark, QLatin1String("styleUrl"), QLatin1String("#linetrack")); if (altitudeMode == 2 ) { addKmlTextElement(kmlLineString, QLatin1String("altitudeMode"), QLatin1String("absolute")); } else if (altitudeMode == 1 ) { addKmlTextElement(kmlLineString, QLatin1String("altitudeMode"), QLatin1String("relativeToGround")); } else { addKmlTextElement(kmlLineString, QLatin1String("altitudeMode"), QLatin1String("clampToGround")); } }
/*! \fn KmlExport::generate() */ void KmlExport::generate() { //! @todo perform a test here before continuing. createDir(QString(m_tempDestDir + m_imageDir)); m_progressDialog->show(); ImageCollection selection = m_interface->currentSelection(); ImageCollection album = m_interface->currentAlbum(); // create the document, and it's root m_kmlDocument = new QDomDocument(""); QDomImplementation impl; QDomProcessingInstruction instr = m_kmlDocument->createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""); m_kmlDocument->appendChild(instr); QDomElement kmlRoot = m_kmlDocument->createElementNS("http://www.opengis.net/kml/2.2", "kml"); m_kmlDocument->appendChild( kmlRoot ); QDomElement kmlAlbum = addKmlElement(kmlRoot, "Document"); QDomElement kmlName = addKmlTextElement(kmlAlbum, "name", album.name()); QDomElement kmlDescription = addKmlHtmlElement(kmlAlbum, "description", "Created with kmlexport <a href=\"http://www.digikam.org/\">kipi-plugin</a>"); if (m_GPXtracks) { addTrack(kmlAlbum); } KPMetadata meta; KUrl::List images = selection.images(); int defectImage = 0; int pos = 1; int count = images.count(); KUrl::List::ConstIterator imagesEnd (images.constEnd()); for( KUrl::List::ConstIterator selIt = images.constBegin(); selIt != imagesEnd; ++selIt, ++pos) { double alt, lat, lng; KUrl url = *selIt; KPImageInfo info(url); bool hasGPSInfo = info.hasGeolocationInfo(); if (hasGPSInfo) { lat = info.latitude(); lng = info.longitude(); alt = info.altitude(); } else { meta.load(url.path()); hasGPSInfo = meta.getGPSInfo(alt, lat, lng); } if ( hasGPSInfo ) { // generation de l'image et de l'icone generateImagesthumb(url, kmlAlbum); } else { logWarning(i18n("No position data for '%1'", info.name())); defectImage++; } m_progressDialog->progressWidget()->setProgress(pos, count); kapp->processEvents(); } if (defectImage) { /** @todo if defectImage==count there are no pictures exported, does is it worth to continue? */ KMessageBox::information(kapp->activeWindow(), i18np("No position data for 1 picture", "No position data for %1 pictures", defectImage)); } /** @todo change to kml or kmz if compressed */ QFile file( m_tempDestDir + m_KMLFileName + ".kml"); /** @todo handle file opening problems */ file.open( QIODevice::WriteOnly ); QTextStream stream( &file ); // we will serialize the data into the file stream << m_kmlDocument->toString(); file.close(); delete m_kmlDocument; m_kmlDocument = 0; KIO::moveAs(m_tempDestDir, m_baseDestDir, KIO::HideProgressInfo | KIO::Overwrite); logInfo(i18n("Move to final directory")); m_progressDialog->close(); }
/*! \fn KmlExport::generateImagesthumb(const KUrl& imageURL, QDomElement& kmlAlbum ) */ void KmlExport::generateImagesthumb(const KUrl& imageURL, QDomElement& kmlAlbum ) { KPImageInfo info(imageURL); // Load image QString path = imageURL.path(); QFile imageFile(path); if (!imageFile.open(QIODevice::ReadOnly)) { logWarning(i18n("Could not read image '%1'",path)); return; } QImageReader reader(&imageFile); QString imageFormat = reader.format(); if (imageFormat.isEmpty()) { logWarning(i18n("Format of image '%1' is unknown",path)); return; } imageFile.close(); imageFile.open(QIODevice::ReadOnly); QByteArray imageData = imageFile.readAll(); QImage image; if (!image.loadFromData(imageData) ) { logWarning(i18n("Error loading image '%1'",path)); return; } // Process images if ( info.orientation() != KPMetadata::ORIENTATION_UNSPECIFIED ) { QMatrix matrix = RotationMatrix::toMatrix(info.orientation()); image = image.transformed( matrix ); } image = image.scaled(m_size, m_size, Qt::KeepAspectRatioByExpanding); QImage icon; if (m_optimize_googlemap) { icon = generateSquareThumbnail(image,m_googlemapSize); } else { // icon = image.smoothScale(m_iconSize, m_iconSize, QImage::ScaleMax); icon = generateBorderedThumbnail(image, m_iconSize); } // Save images /** @todo remove the extension of the file * it's appear with digikam but not with gwenview * which already seems to strip the extension */ QString baseFileName = webifyFileName(info.name()); //baseFileName = mUniqueNameHelper.makeNameUnique(baseFileName); QString fullFileName; fullFileName = baseFileName + '.' + imageFormat.toLower(); QString destPath = m_tempDestDir + m_imageDir + fullFileName; if (!image.save(destPath, imageFormat.toAscii(), 85)) { // if not able to save the image, it's pointless to create a placemark logWarning(i18n("Could not save image '%1' to '%2'",path,destPath)); } else { //logInfo(i18n("Creation of picture '%1'").arg(fullFileName)); double alt, lat, lng; KPMetadata meta; if (info.hasGeolocationInfo()) { lat = info.latitude(); lng = info.longitude(); alt = info.altitude(); } else { meta.load(imageURL.path()); meta.getGPSInfo(alt, lat, lng); } QDomElement kmlPlacemark = addKmlElement(kmlAlbum, "Placemark"); addKmlTextElement(kmlPlacemark,"name",fullFileName); // location and altitude QDomElement kmlGeometry = addKmlElement(kmlPlacemark, "Point"); if (alt) { addKmlTextElement(kmlGeometry, "coordinates", QString("%1,%2,%3 ") .arg(lng, 0, 'f', 8) .arg(lat, 0, 'f', 8) .arg(alt, 0, 'f', 8)); } else { addKmlTextElement(kmlGeometry, "coordinates", QString("%1,%2 ") .arg(lng, 0, 'f', 8) .arg(lat, 0, 'f', 8)); } if (m_altitudeMode == 2 ) { addKmlTextElement(kmlGeometry, "altitudeMode", "absolute"); } else if (m_altitudeMode == 1 ) { addKmlTextElement(kmlGeometry, "altitudeMode", "relativeToGround"); } else { addKmlTextElement(kmlGeometry, "altitudeMode", "clampToGround"); } addKmlTextElement(kmlGeometry, "extrude", "1"); // we try to load exif value if any otherwise, try the application db /** we need to take the DateTimeOriginal * if we refer to http://www.exif.org/Exif2-2.PDF * (standard)DateTime: is The date and time of image creation. In this standard it is the date and time the file was changed * DateTimeOriginal: The date and time when the original image data was generated. * For a DSC the date and time the picture was taken are recorded. * DateTimeDigitized: The date and time when the image was stored as digital data. * So for: * - a DSC: the right time is the DateTimeDigitized which is also DateTimeOriginal * if the picture has been modified the (standard)DateTime should change. * - a scanned picture, the right time is the DateTimeOriginal which should also be the DateTime * the (standard)DateTime should be the same except if the picture is modified * - a panorama created from several pictures, the right time is the DateTimeOriginal (average of DateTimeOriginal actually) * The (standard)DateTime is the creation date of the panorama. * it's seems the time to take into acccount is the DateTimeOriginal. * but the KPMetadata::getImageDateTime() return the (standard)DateTime first * KPMetadata seems to take Original dateTime first so it shoul be alright now. */ QDateTime datetime = meta.getImageDateTime(); if (datetime.isValid()) { QDomElement kmlTimeStamp = addKmlElement(kmlPlacemark, "TimeStamp"); addKmlTextElement(kmlTimeStamp, "when", datetime.toString("yyyy-MM-ddThh:mm:ssZ")); } else if (m_interface->hasFeature(ImagesHasTime)) { QDomElement kmlTimeStamp = addKmlElement(kmlPlacemark, "TimeStamp"); addKmlTextElement(kmlTimeStamp, "when", (info.date()).toString("yyyy-MM-ddThh:mm:ssZ")); } QString my_description; if (m_optimize_googlemap) { my_description = "<img src=\"" + m_UrlDestDir + m_imageDir + fullFileName + "\">"; } else { my_description = "<img src=\"" + m_imageDir + fullFileName + "\">"; } if ( m_interface->hasFeature( ImagesHasComments ) ) { my_description += "<br/>" + info.description() ; } addKmlTextElement(kmlPlacemark, "description", my_description); logInfo(i18n("Creation of placemark '%1'", fullFileName)); // Save icon QString iconFileName = "thumb_" + baseFileName + '.' + imageFormat.toLower(); QString destPath = m_tempDestDir + m_imageDir + iconFileName; if (!icon.save(destPath, imageFormat.toAscii(), 85)) { logWarning(i18n("Could not save icon for image '%1' to '%2'",path,destPath)); } else { //logInfo(i18n("Creation of icon '%1'").arg(iconFileName)); // style et icon QDomElement kmlStyle = addKmlElement(kmlPlacemark, "Style"); QDomElement kmlIconStyle = addKmlElement(kmlStyle, "IconStyle"); QDomElement kmlIcon = addKmlElement(kmlIconStyle, "Icon"); if (m_optimize_googlemap) { addKmlTextElement(kmlIcon, "href", m_UrlDestDir + m_imageDir + iconFileName); } else { addKmlTextElement(kmlIcon, "href", m_imageDir + iconFileName); } QDomElement kmlBallonStyle = addKmlElement(kmlStyle, "BalloonStyle"); addKmlTextElement(kmlBallonStyle, "text", "$[description]"); } } }