XMP-Toolkit-SDK编译和使用

MirrorYuChen
MirrorYuChen
发布于 2024-11-27 / 34 阅读
0
0

XMP-Toolkit-SDK编译和使用

0.内容概览

1.下载源码

>> git clone --recursive git@github.com:adobe/XMP-Toolkit-SDK.git

2.下载第三方库

2.1 expat

  • (1) 下载expat库:下载地址:expat源码
  • (2) 进入工程对应目录:
>> cd XMP-Toolkit-SDK/third-party/expat
  • (3) 解压到当前目录
# 1.源码解压缩
>> tar -xf expat-2.6.4.tar.xz
# 2.移动解压文件到根目录
>> cd expat-2.6.4 && mv * ../
# 3.删除无用文件及目录
>> cd .. && rm -r expat-2.6.4 && rm expat-2.6.4.tar.xz

2.2 zlib

# 1.进入zlib目录
>> cd XMP-Toolkit-SDK/third-party/zlib
# 2.下载zlib源码
>> wget https://www.zlib.net/zlib-1.3.1.tar.gz
# 3.源代码解压
>> tar -xf zlib-1.3.1.tar.gz
# 4.移动解压文件到根目录
>> cd zlib-1.3.1 && mv * ../
# 5.删除无用文件及目录
>> cd .. && rm -r zlib-1.3.1 && rm zlib-1.3.1.tar.gz

3.修改相关脚本配置

  • (1) build/shared/SharedConfig_Common.cmake文件,注释掉下面行,修改为如下内容:
		# workaround for visibility problem and gcc 4.1.x
		# if(${${COMPONENT}_VERSIONING_GCC_VERSION} LESS 413)
			# only remove inline hidden...
			string(REGEX REPLACE "-fvisibility-inlines-hidden" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
		# endif()
		# if(${${COMPONENT}_VERSIONING_GCC_VERSION} EQUAL 482)
			#include path -I ${GNU_BASE}/include/c++/4.8.2/x86_64-unknown-linux-gnu
			set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I ${CMAKE_FIND_ROOT_PATH}/include/c++/4.8.2/x86_64-unknown-linux-gnu")
		# endif()
  • (2) build/ProductConfig.cmake文件,171行修改为如下内容:
set(XMP_PLATFORM_LINK "-z defs -Xlinker -Bsymbolic -Wl,--no-undefined  ${XMP_EXTRA_LINK_FLAGS} ${XMP_TOOLCHAIN_LINK_FLAGS} -lrt -Wl,--no-as-needed -ldl -lpthread")

​ 注意:下面的修改是为了适配Visual Studio 2019,如果你按照了Visual Studio 2022,就无需对下面内容进行修改

  • (3) 全局搜索 Visual Studio 17 2022并修改为 Visual Studio 16 2019
  • (4) 全局搜索 vc17 并修改为 vc16

4.源码编译

4.1 Windows平台

  • (1) 进入 XMP-Toolkit-SDK/build文件夹,双击 cmake_all.bat文件生成vc工程
  • (2) 进入 XMP-Toolkit-SDK/build/vc16/dynamic/windows_x64打开 XMPToolkitSDK64.sln进行编译即可
  • (3) 编译生成的头文件和库文件分别位于:
XMP-Toolkit-SDK/public/include
XMP-Toolkit-SDK/public/libraries

4.2 Linux平台

  • (1) 工程编译,生成动态库:
>> cd XMP-Toolkit-SDK/build
>> make DynamicAll
  • (2) 头文件和库文件目录:
XMP-Toolkit-SDK/public/include
XMP-Toolkit-SDK/public/libraries

5.测试代码

// =================================================================================================
// Copyright 2008 Adobe
// All Rights Reserved.
//
// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
// of the Adobe license agreement accompanying it. 
// =================================================================================================

/**
* Tutorial solution for the Walkthrough 1 in the XMP Programmers Guide, Opening files and reading XMP.
* Demonstrates the basic use of the XMPFiles and XMPCore components, obtaining read-only XMP from a file 
* and examining it through the XMP object.
*/

#include <cstdio>
#include <vector>
#include <string>
#include <cstring>

//#define ENABLE_XMP_CPP_INTERFACE 1

// Must be defined to instantiate template classes
#define TXMP_STRING_TYPE std::string 

// Must be defined to give access to XMPFiles
#define XMP_INCLUDE_XMPFILES 1 

// Ensure XMP templates are instantiated
#include "public/include/XMP.incl_cpp"

// Provide access to the API
#include "public/include/XMP.hpp"

#include <iostream>
#include <fstream>

using namespace std; 


/**
* Client defined callback function to dump XMP to a file.  In this case an output file stream is used
* to write a buffer, of length bufferSize, to a text file.  This callback is called multiple 
* times during the DumpObject() operation.  See the XMP API reference for details of 
* XMP_TextOutputProc() callbacks.
*/
XMP_Status DumpXMPToFile(void * refCon, XMP_StringPtr buffer, XMP_StringLen bufferSize)
{
	XMP_Status status = 0;

	try
	{
		ofstream * outFile = static_cast<ofstream*>(refCon);
		(*outFile).write(buffer, bufferSize);
	}
	catch(XMP_Error & e)
	{
		cout << e.GetErrMsg() << endl;
		return -1;  // Return a bad status
	}

	return status;
}

/**
*	Initializes the toolkit and attempts to open a file for reading metadata.  Initially
* an attempt to open the file is done with a handler, if this fails then the file is opened with
* packet scanning. Once the file is open several properties are read and displayed in the console.  
* The XMP object is then dumped to a text file and the resource file is closed.
*/
int main ( int argc, const char * argv[] )
{
	if ( argc != 2 ) // 2 := command and 1 parameter
	{
		cout << "usage: ReadingXMP (filename)" << endl;
		return 0;
	}

	string filename = string( argv[1] );

	if(!SXMPMeta::Initialize())
	{
		cout << "Could not initialize toolkit!";
		return -1;
	}
	XMP_OptionBits options = 0;
	#if UNIX_ENV
		options |= kXMPFiles_ServerMode;
	#endif
	// Must initialize SXMPFiles before we use it
	if ( ! SXMPFiles::Initialize ( options ) )
	{
		cout << "Could not initialize SXMPFiles.";
		return -1;
	}

	try
	{
		// Options to open the file with - read only and use a file handler
		XMP_OptionBits opts = kXMPFiles_OpenForRead | kXMPFiles_OpenUseSmartHandler;

		bool ok;
		SXMPFiles myFile;
		std::string status = "";

		// First we try and open the file
		ok = myFile.OpenFile(filename, kXMP_UnknownFile, opts);
		if( ! ok )
		{
			status += "No smart handler available for " + filename + "\n";
			status += "Trying packet scanning.\n";

			// Now try using packet scanning
			opts = kXMPFiles_OpenForUpdate | kXMPFiles_OpenUsePacketScanning;
			ok = myFile.OpenFile(filename, kXMP_UnknownFile, opts);
		}


		// If the file is open then read the metadata
		if(ok)
		{
			cout << status << endl;
			cout << filename << " is opened successfully" << endl;
			// Create the xmp object and get the xmp data
			SXMPMeta meta;
			myFile.GetXMP(&meta);

			bool exists;

			// Read a simple property
			string simpleValue;  //Stores the value for the property
			exists = meta.GetProperty(kXMP_NS_XMP, "CreatorTool", &simpleValue, NULL);
			if(exists)
				cout << "CreatorTool = " << simpleValue << endl;
			else
				simpleValue.clear();

			// Get the first element in the dc:creator array
			string elementValue;
			exists = meta.GetArrayItem(kXMP_NS_DC, "creator", 1, &elementValue, NULL);
			if(exists)
				cout << "dc:creator = " << elementValue << endl;
			else
				elementValue.clear();

			// Get the the entire dc:subject array 
			string propValue;
			int arrSize = meta.CountArrayItems(kXMP_NS_DC, "subject");
			for(int i = 1; i <= arrSize;i++)
			{
				meta.GetArrayItem(kXMP_NS_DC, "subject", i, &propValue, 0);
				cout << "dc:subject[" << i << "] = " << propValue << endl;
			}

			// Get the dc:title for English and French
			string itemValue;
			string actualLang;
			meta.GetLocalizedText(kXMP_NS_DC, "title", "en", "en-US", NULL, &itemValue, NULL);
			cout << "dc:title in English = " << itemValue << endl;

			meta.GetLocalizedText(kXMP_NS_DC, "title", "fr", "fr-FR", NULL, &itemValue, NULL);
			cout << "dc:title in French = " << itemValue << endl;

			// Get dc:MetadataDate
			XMP_DateTime myDate;
			if(meta.GetProperty_Date(kXMP_NS_XMP, "MetadataDate", &myDate, NULL))
			{
				// Convert the date struct into a convenient string and display it
				string myDateStr;
				SXMPUtils::ConvertFromDate(myDate, &myDateStr);
				cout << "meta:MetadataDate = " << myDateStr << endl;						 
			}

			// See if the flash struct exists and see if it was used
			string path, value;
			exists = meta.DoesStructFieldExist(kXMP_NS_EXIF, "Flash", kXMP_NS_EXIF,"Fired");
			if(exists)
			{
				bool flashFired;
				SXMPUtils::ComposeStructFieldPath(kXMP_NS_EXIF, "Flash", kXMP_NS_EXIF, "Fired", &path);
				meta.GetProperty_Bool(kXMP_NS_EXIF, path.c_str(), &flashFired, NULL);
				string flash = (flashFired) ? "True" : "False";

				cout << "Flash Used = " << flash << endl;
			}



			// Dump the current xmp object to a file
			ofstream dumpFile;
			dumpFile.open("XMPDump.txt", ios::out);
			meta.DumpObject(DumpXMPToFile, &dumpFile);
			dumpFile.close();
			cout << endl << "XMP dumped to XMPDump.txt" << endl;

			// Close the SXMPFile.  The resource file is already closed if it was
			// opened as read only but this call must still be made.
			myFile.CloseFile();
		}
		else
		{
			cout << "Unable to open " << filename << endl;
		}
	}
	catch(XMP_Error & e)
	{
		cout << "ERROR: " << e.GetErrMsg() << endl;
	}

	// Terminate the toolkit
	SXMPFiles::Terminate();
	SXMPMeta::Terminate();

	return 0;
}

6.项目结构

.
├── 3rdLibs
│   ├── XMP-Toolkit-SDK
│       ├── include
│       │   ├── TXMPFiles.hpp
│       │   ├── TXMPIterator.hpp
│       │   ├── TXMPMeta.hpp
│       │   ├── TXMPUtils.hpp
│       │   ├── XMP.hpp
│       │   ├── XMP.incl_cpp
│       │   ├── XMPCommon
│       │   │   ├── Interfaces
│       │   │   │   ├── BaseInterfaces
│       │   │   │   │   ├── IConfigurable.h
│       │   │   │   │   ├── ISharedObject.h
│       │   │   │   │   ├── IThreadSafe.h
│       │   │   │   │   └── IVersionable.h
│       │   │   │   ├── IConfigurationManager.h
│       │   │   │   ├── IError.h
│       │   │   │   ├── IErrorNotifier.h
│       │   │   │   ├── IMemoryAllocator.h
│       │   │   │   ├── IObjectFactory.h
│       │   │   │   └── IUTF8String.h
│       │   │   ├── Utilities
│       │   │   │   ├── TWrapperFunctions.h
│       │   │   │   └── TWrapperFunctions2.h
│       │   │   ├── XMPCommonDefines.h
│       │   │   ├── XMPCommonErrorCodes.h
│       │   │   ├── XMPCommonFwdDeclarations.h
│       │   │   ├── XMPCommonLatestInterfaceVersions.h
│       │   │   └── source
│       │   │       ├── IConfigurable.cpp
│       │   │       ├── IConfigurationManager.cpp
│       │   │       ├── IError.cpp
│       │   │       ├── IErrorNotifier.cpp
│       │   │       └── IUTF8String.cpp
│       │   ├── XMPCore
│       │   │   ├── Interfaces
│       │   │   │   ├── IArrayNode.h
│       │   │   │   ├── IClientDOMParser.h
│       │   │   │   ├── IClientDOMSerializer.h
│       │   │   │   ├── ICompositeNode.h
│       │   │   │   ├── ICoreConfigurationManager.h
│       │   │   │   ├── ICoreObjectFactory.h
│       │   │   │   ├── IDOMImplementationRegistry.h
│       │   │   │   ├── IDOMParser.h
│       │   │   │   ├── IDOMSerializer.h
│       │   │   │   ├── IMetadata.h
│       │   │   │   ├── IMetadataConverterUtils.h
│       │   │   │   ├── INameSpacePrefixMap.h
│       │   │   │   ├── INode.h
│       │   │   │   ├── INodeIterator.h
│       │   │   │   ├── IPath.h
│       │   │   │   ├── IPathSegment.h
│       │   │   │   ├── ISimpleNode.h
│       │   │   │   └── IStructureNode.h
│       │   │   ├── XMPCoreDefines.h
│       │   │   ├── XMPCoreErrorCodes.h
│       │   │   ├── XMPCoreFwdDeclarations.h
│       │   │   ├── XMPCoreLatestInterfaceVersions.h
│       │   │   └── source
│       │   │       ├── IArrayNode.cpp
│       │   │       ├── IClientDOMParser.cpp
│       │   │       ├── IClientDOMSerializer.cpp
│       │   │       ├── ICompositeNode.cpp
│       │   │       ├── ICoreConfigurationManager.cpp
│       │   │       ├── ICoreObjectFactory.cpp
│       │   │       ├── IDOMImplementationRegistry.cpp
│       │   │       ├── IDOMParser.cpp
│       │   │       ├── IDOMSerializer.cpp
│       │   │       ├── IMetadata.cpp
│       │   │       ├── IMetadataConverterUtils.cpp
│       │   │       ├── INameSpacePrefixMap.cpp
│       │   │       ├── INode.cpp
│       │   │       ├── INodeIterator.cpp
│       │   │       ├── IPath.cpp
│       │   │       ├── IPathSegment.cpp
│       │   │       ├── ISimpleNode.cpp
│       │   │       └── IStructureNode.cpp
│       │   ├── XMP_Const.h
│       │   ├── XMP_Environment.h
│       │   ├── XMP_IO.hpp
│       │   ├── XMP_Version.h
│       │   └── client-glue
│       │       ├── TXMPFiles.incl_cpp
│       │       ├── TXMPIterator.incl_cpp
│       │       ├── TXMPMeta.incl_cpp
│       │       ├── TXMPUtils.incl_cpp
│       │       ├── WXMPFiles.hpp
│       │       ├── WXMPIterator.hpp
│       │       ├── WXMPMeta.hpp
│       │       ├── WXMPUtils.hpp
│       │       └── WXMP_Common.hpp
│       └── libs
│           ├── XMPCore.dll
│           ├── XMPCore.exp
│           ├── XMPCore.lib
│           ├── XMPCore.map
│           ├── XMPCore.pdb
│           ├── XMPFiles.dll
│           ├── XMPFiles.exp
│           ├── XMPFiles.lib
│           ├── XMPFiles.map
│           ├── XMPFiles.pdb
│           ├── libXMPCore.so
│           └── libXMPFiles.so
│   
├── CMakeLists.txt
├── ReadMe.md
├── source
    └── XMPModify.cc

7.CMake工程

cmake_minimum_required(VERSION 3.1...3.26)

project(XMPEditor LANGUAGES CXX C)

# Set C and C++ standard version
set(CMAKE_C_STANDARD_REQUIRED True)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

include_directories(
  ${CMAKE_CURRENT_LIST_DIR}/3rdLibs/XMP-Toolkit-SDK/include
)

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  set(CMAKE_BUILD_TYPE "Release")
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release")
endif()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")

set (OBJECTS_TO_LINK "")

if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux")
  message("-- current platform: Linux ")
  file (GLOB libs ${CMAKE_CURRENT_LIST_DIR}/3rdLibs/XMP-Toolkit-SDK/libs/*.so)
  list (APPEND OBJECTS_TO_LINK ${libs})
  add_compile_definitions(-DUNIX_ENV)
elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
  message("-- current platform: Windows ")
  file (GLOB libs ${CMAKE_CURRENT_LIST_DIR}/3rdLibs/XMP-Toolkit-SDK/libs/*.lib)
  list (APPEND OBJECTS_TO_LINK ${libs})
  add_compile_definitions(-DWIN_ENV)
endif()

add_executable(TestXMPModify source/TestXMPModify.cc)
target_link_libraries(TestXMPModify ${OBJECTS_TO_LINK})

评论