int JpegContent::dotsPerMeter(const QString& keyName) const { Exiv2::ExifKey keyResUnit("Exif.Image.ResolutionUnit"); Exiv2::ExifData::iterator it = d->mExifData.findKey(keyResUnit); if (it == d->mExifData.end()) { return 0; } int res = it->toLong(); QString keyVal = "Exif.Image." + keyName; Exiv2::ExifKey keyResolution(keyVal.toAscii().data()); it = d->mExifData.findKey(keyResolution); if (it == d->mExifData.end()) { return 0; } // The unit for measuring XResolution and YResolution. The same unit is used for both XResolution and YResolution. // If the image resolution in unknown, 2 (inches) is designated. // Default = 2 // 2 = inches // 3 = centimeters // Other = reserved const float INCHESPERMETER = (100. / 2.54); switch (res) { case 3: // dots per cm return int(it->toLong() * 100); default: // dots per inch return int(it->toLong() * INCHESPERMETER); } return 0; }
Orientation JpegContent::orientation() const { Exiv2::ExifKey key("Exif.Image.Orientation"); Exiv2::ExifData::iterator it = d->mExifData.findKey(key); // We do the same checks as in libexiv2's src/crwimage.cpp: // http://dev.exiv2.org/projects/exiv2/repository/entry/trunk/src/crwimage.cpp?rev=2681#L1336 if (it == d->mExifData.end() || it->count() == 0 || it->typeId() != Exiv2::unsignedShort) { return NOT_AVAILABLE; } return Orientation(it->toLong()); }
bool _getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, long & value) { Exiv2::ExifData::iterator itr = exifData.findKey(Exiv2::ExifKey(keyName)); if (itr != exifData.end() && itr->count()) { value = itr->toLong(); return true; } else { return false; }; };
QSize KExiv2::getImageDimensions() const { try { long width=-1, height=-1; // Try to get Exif.Photo tags Exiv2::ExifData exifData(d->exifMetadata()); Exiv2::ExifKey key("Exif.Photo.PixelXDimension"); Exiv2::ExifData::iterator it = exifData.findKey(key); if (it != exifData.end() && it->count()) width = it->toLong(); Exiv2::ExifKey key2("Exif.Photo.PixelYDimension"); Exiv2::ExifData::iterator it2 = exifData.findKey(key2); if (it2 != exifData.end() && it2->count()) height = it2->toLong(); if (width != -1 && height != -1) return QSize(width, height); // Try to get Exif.Image tags width = -1; height = -1; Exiv2::ExifKey key3("Exif.Image.ImageWidth"); Exiv2::ExifData::iterator it3 = exifData.findKey(key3); if (it3 != exifData.end() && it3->count()) width = it3->toLong(); Exiv2::ExifKey key4("Exif.Image.ImageLength"); Exiv2::ExifData::iterator it4 = exifData.findKey(key4); if (it4 != exifData.end() && it4->count()) height = it4->toLong(); if (width != -1 && height != -1) return QSize(width, height); #ifdef _XMP_SUPPORT_ // Try to get Xmp.tiff tags width = -1; height = -1; bool wOk = false; bool hOk = false; QString str = getXmpTagString("Xmp.tiff.ImageWidth"); if (!str.isEmpty()) width = str.toInt(&wOk); str = getXmpTagString("Xmp.tiff.ImageLength"); if (!str.isEmpty()) height = str.toInt(&hOk); if (wOk && hOk) return QSize(width, height); // Try to get Xmp.exif tags width = -1; height = -1; wOk = false; hOk = false; str = getXmpTagString("Xmp.exif.PixelXDimension"); if (!str.isEmpty()) width = str.toInt(&wOk); str = getXmpTagString("Xmp.exif.PixelYDimension"); if (!str.isEmpty()) height = str.toInt(&hOk); if (wOk && hOk) return QSize(width, height); #endif // _XMP_SUPPORT_ } catch( Exiv2::Error& e ) { d->printExiv2ExceptionError("Cannot parse image dimensions tag using Exiv2 ", e); } catch(...) { kError() << "Default exception from Exiv2"; } return QSize(); }
bool KExiv2::setImageOrientation(ImageOrientation orientation, bool setProgramName) const { if (!setProgramId(setProgramName)) return false; try { if (orientation < ORIENTATION_UNSPECIFIED || orientation > ORIENTATION_ROT_270) { kDebug() << "Image orientation value is not correct!"; return false; } // Set Exif values. d->exifMetadata()["Exif.Image.Orientation"] = static_cast<uint16_t>(orientation); kDebug() << "Exif.Image.Orientation tag set to: " << (int)orientation; // Set Xmp values. #ifdef _XMP_SUPPORT_ setXmpTagString("Xmp.tiff.Orientation", QString::number((int)orientation), false); #endif // _XMP_SUPPORT_ // -- Minolta/Sony Cameras ---------------------------------- // Minolta and Sony camera store image rotation in Makernote. // We remove these information to prevent duplicate values. Exiv2::ExifData::iterator it; Exiv2::ExifKey minoltaKey1("Exif.MinoltaCs7D.Rotation"); it = d->exifMetadata().findKey(minoltaKey1); if (it != d->exifMetadata().end()) { d->exifMetadata().erase(it); kDebug() << "Removing Exif.MinoltaCs7D.Rotation tag"; } Exiv2::ExifKey minoltaKey2("Exif.MinoltaCs5D.Rotation"); it = d->exifMetadata().findKey(minoltaKey2); if (it != d->exifMetadata().end()) { d->exifMetadata().erase(it); kDebug() << "Removing Exif.MinoltaCs5D.Rotation tag"; } // -- Exif embedded thumbnail ---------------------------------- Exiv2::ExifKey thumbKey("Exif.Thumbnail.Orientation"); it = d->exifMetadata().findKey(thumbKey); if (it != d->exifMetadata().end() && it->count()) { RotationMatrix operation((KExiv2Iface::KExiv2::ImageOrientation)it->toLong()); operation *= orientation; (*it) = static_cast<uint16_t>(operation.exifOrientation()); } return true; } catch( Exiv2::Error& e ) { d->printExiv2ExceptionError("Cannot set Exif Orientation tag using Exiv2 ", e); } catch(...) { kError() << "Default exception from Exiv2"; } return false; }
KExiv2::ImageOrientation KExiv2::getImageOrientation() const { try { Exiv2::ExifData exifData(d->exifMetadata()); Exiv2::ExifData::iterator it; long orientation; ImageOrientation imageOrient = ORIENTATION_NORMAL; // -- Standard Xmp tag -------------------------------- #ifdef _XMP_SUPPORT_ bool ok = false; QString str = getXmpTagString("Xmp.tiff.Orientation"); if (!str.isEmpty()) { orientation = str.toLong(&ok); if (ok) { kDebug() << "Orientation => Xmp.tiff.Orientation => " << (int)orientation; return (ImageOrientation)orientation; } } #endif // _XMP_SUPPORT_ // Because some camera set a wrong standard exif orientation tag, // We need to check makernote tags in first! // -- Minolta Cameras ---------------------------------- Exiv2::ExifKey minoltaKey1("Exif.MinoltaCs7D.Rotation"); it = exifData.findKey(minoltaKey1); if (it != exifData.end() && it->count()) { orientation = it->toLong(); kDebug() << "Orientation => Exif.MinoltaCs7D.Rotation => " << (int)orientation; switch(orientation) { case 76: imageOrient = ORIENTATION_ROT_90; break; case 82: imageOrient = ORIENTATION_ROT_270; break; } return imageOrient; } Exiv2::ExifKey minoltaKey2("Exif.MinoltaCs5D.Rotation"); it = exifData.findKey(minoltaKey2); if (it != exifData.end() && it->count()) { orientation = it->toLong(); kDebug() << "Orientation => Exif.MinoltaCs5D.Rotation => " << (int)orientation; switch(orientation) { case 76: imageOrient = ORIENTATION_ROT_90; break; case 82: imageOrient = ORIENTATION_ROT_270; break; } return imageOrient; } // -- Standard Exif tag -------------------------------- Exiv2::ExifKey keyStd("Exif.Image.Orientation"); it = exifData.findKey(keyStd); if (it != exifData.end() && it->count()) { orientation = it->toLong(); kDebug() << "Orientation => Exif.Image.Orientation => " << (int)orientation; return (ImageOrientation)orientation; } } catch( Exiv2::Error& e ) { d->printExiv2ExceptionError("Cannot parse Exif Orientation tag using Exiv2 ", e); } catch(...) { kError() << "Default exception from Exiv2"; } return ORIENTATION_UNSPECIFIED; }
long GalleryUtil::GetNaturalRotation(const QString &filePathString) { long rotateAngle = 0; #ifdef EXIF_SUPPORT QByteArray filePathBA = filePathString.toLocal8Bit(); const char *filePath = filePathBA.constData(); try { char *exifvalue = new char[1024]; ExifData *data = exif_data_new_from_file (filePath); if (data) { for (int i = 0; i < EXIF_IFD_COUNT; i++) { ExifEntry *entry = exif_content_get_entry (data->ifd[i], EXIF_TAG_ORIENTATION); ExifByteOrder byteorder = exif_data_get_byte_order (data); if (entry) { ExifShort v_short = exif_get_short (entry->data, byteorder); VERBOSE(VB_GENERAL|VB_EXTRA, QString("Exif entry=%1").arg(v_short)); /* See http://sylvana.net/jpegcrop/exif_orientation.html*/ if (v_short == 8) { rotateAngle = -90; } else if (v_short == 6) { rotateAngle = 90; } break; } } exif_data_free(data); } else { VERBOSE(VB_FILE, LOC_ERR + QString("Could not load exif data from '%1'") .arg(filePath)); } delete [] exifvalue; #if 0 Exiv2::ExifData exifData; int rc = exifData.read(filePath); if (!rc) { Exiv2::ExifKey key = Exiv2::ExifKey("Exif.Image.Orientation"); Exiv2::ExifData::iterator pos = exifData.findKey(key); if (pos != exifData.end()) { long orientation = pos->toLong(); switch (orientation) { case 6: rotateAngle = 90; break; case 8: rotateAngle = -90; break; default: rotateAngle = 0; break; } } } #endif } catch (...) { VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Failed to extract EXIF headers from '%1'") .arg(filePathString)); } #else // Shut the compiler up about the unused argument (void)filePathString; #endif // EXIF_SUPPORT return rotateAngle; }