openexr-2.3.0-windows编译

        本文操作按照《c&c++开源库编译指南》中内容规范编写,编译环境配置、工具下载、目录规划,及更多其他开源库编译方法请参考该文章。

        c&c++开源库编译指南:https://blog.csdn.net/binary0006/article/details/144086155

        本文章中的源代码已提交到gitee仓库,地址:https://gitee.com/binary0010/depends/tree/master/c/openexr-2.3.0

1.openexr概述

OpenEXR 是由工业光魔(Industrial Light & Magic,ILM)开发的一种用于存储高动态范围(HDR)图像数据的文件格式,同时也是一套实现该格式读写操作的开源库,在影视、动画、游戏等视觉特效领域有着广泛应用。

从技术角度来看,OpenEXR 采用了无损压缩算法,如 PIZ、PXR24 等,能够在有效减小文件体积的同时,最大程度保留图像的原始信息,确保图像的高质量和高保真度。它支持多通道数据存储,除了常见的红、绿、蓝(RGB)通道外,还可以存储深度、法线、透明度等额外信息,为后期制作提供了丰富的数据支持。OpenEXR 库使用 C++ 编写,提供了一套完整的 API,方便开发者进行图像的读写操作。在编译方面,它具有良好的跨平台性,可在 Linux、Windows、macOS 等多种操作系统上编译,不过编译时可能依赖一些其他的库,如 zlib、Imath 等。

在应用场景上,OpenEXR 主要用于影视制作中的合成、渲染和后期处理环节。在渲染过程中,渲染器可以将生成的高动态范围图像保存为 OpenEXR 格式,方便后续的颜色校正、合成等操作。在后期合成阶段,OpenEXR 的多通道数据可以帮助合成师更精确地控制图像的各个部分,实现复杂的特效。此外,在游戏开发中,OpenEXR 也逐渐被用于存储和处理高质量的纹理和光照信息。

在开源社区,OpenEXR 遵循 BSD 许可协议,代码托管在 GitHub 上。社区非常活跃,不断有开发者对其进行维护和更新,添加新的功能、优化性能以及修复潜在的漏洞。许多知名的影视制作公司、动画工作室和游戏开发团队都在使用 OpenEXR,它已经成为了高动态范围图像存储和处理的行业标准之一。

2.openexr编译

2.1.源代码下载

openexr源代码可以在github上下载,源代码下载地址:https://github.com/AcademySoftwareFoundation/openexr/releases,这里我们使用2.3.0版本,使用较低的版本能确保vs2008编译不会出错,在这个界面往后翻直到找到2.3.0版本后,按照下面的截图选择下载openexr-2.3.0.tar.gz

2.2.windows编译

先解压源代码到指定目录,openexr-2.3.0版本已经了提供CMakeLists.txt编译脚步,我们按照规范会对该脚本进行修改。

2.2.1.openexr源代码工程分析

当我们打开 openexr 源代码根目录下的 CMakeLists.txt 文件时,能够清晰地看到其中包含了多个关键子目录,分别为 IlmBase、OpenEXR、PyIlmBase 和 OpenEXR_Viewers,并且每个子目录下又涵盖了多个工程,下面将详细阐述这些子目录及其包含工程的作用。

2.2.1.1.IlmBase 子目录

IlmBase 是 OpenEXR 的基础库,它为 OpenEXR 提供了核心的数据结构和算法支持,是整个 OpenEXR 项目的基石。该子目录下的工程主要实现了一些基础的功能,这些功能对于处理高动态范围图像数据至关重要。

Half 工程:Half 工程主要负责实现半精度浮点数(16 位浮点数)的处理。在处理高动态范围图像时,半精度浮点数可以在减少存储空间的同时,保留足够的精度来表示图像数据。Half 工程提供了半精度浮点数与单精度浮点数(32 位浮点数)之间的转换函数,以及一些基本的数学运算函数,方便开发者在不同精度之间进行切换。

Iex 工程:Iex 工程是一个异常处理库,它为 OpenEXR 提供了统一的异常处理机制。在处理图像数据时,可能会遇到各种错误情况,如文件读取错误、数据格式错误等。Iex 工程定义了一系列的异常类,开发者可以使用这些异常类来捕获和处理不同类型的错误,提高代码的健壮性和可维护性。

Imath 工程:Imath 工程实现了一组数学库,包括向量、矩阵、四元数等基本数学对象的定义和操作。在图像处理中,这些数学对象被广泛用于表示图像的几何信息,如位置、方向、旋转等。Imath 工程提供了丰富的数学运算函数,方便开发者进行图像的变换和处理。

2.2.1.2.OpenEXR 子目录

OpenEXR 子目录是整个项目的核心部分,它实现了 OpenEXR 文件格式的读写功能,以及相关的压缩和解压缩算法。该子目录下的工程主要围绕 OpenEXR 文件的处理展开。

OpenEXR 核心库工程该工程实现了 OpenEXR 文件的读写功能,包括文件头的解析、数据块的读写、通道信息的处理等。它提供了一组 API 接口,开发者可以使用这些接口来创建、读取和修改 OpenEXR 文件。

压缩算法工程OpenEXR 支持多种压缩算法,如 PIZ、PXR24、ZIP 等。压缩算法工程实现了这些压缩算法的具体实现,通过对图像数据进行压缩,可以有效减少文件的存储空间,提高数据传输效率。

测试工程为了确保 OpenEXR 库的正确性和稳定性,测试工程包含了一系列的单元测试和集成测试。这些测试用例覆盖了 OpenEXR 库的各个功能模块,通过运行这些测试用例,可以及时发现和修复潜在的问题。

2.2.1.3.PyIlmBase 子目录

PyIlmBase 子目录提供了 Python 绑定,使得开发者可以在 Python 环境中使用 OpenEXR 的功能。该子目录下的工程主要实现了 Python 与 C++ 代码之间的交互。

Python 绑定工程该工程使用 SWIG(Simplified Wrapper and Interface Generator)工具生成 Python 与 C++ 代码之间的绑定。通过这些绑定,开发者可以在 Python 脚本中直接调用 OpenEXR 的 C++ 库函数,方便地进行图像处理和分析。

示例脚本工程为了帮助开发者快速上手,示例脚本工程提供了一些使用 PyIlmBase 的示例脚本。这些脚本展示了如何在 Python 环境中创建、读取和修改 OpenEXR 文件,以及如何进行简单的图像处理操作。

2.2.1.4.OpenEXR_Viewers 子目录

OpenEXR_Viewers 子目录包含了一些用于查看和显示 OpenEXR 文件的工具。这些工具可以帮助开发者直观地查看 OpenEXR 文件的内容,进行图像的预览和调试。

在实际的 C++ 开发中,通常仅需要将 IlmBase 和 OpenEXR 作为 SDK(软件开发工具包)来使用。IlmBase 提供的基础数据结构和算法,是构建 OpenEXR 相关功能的根基。开发人员在处理图像数据时,会频繁使用到 IlmBase 中定义的半精度浮点数处理、异常处理以及数学运算等功能。而 OpenEXR 则提供了直接操作 OpenEXR 文件的核心功能,开发人员可以利用其提供的 API 接口,轻松实现对 OpenEXR 文件的读写操作,以及进行数据的压缩和解压缩处理。

将 IlmBase 和 OpenEXR 作为 SDK 集成到项目中,能够让开发人员专注于业务逻辑的实现,而无需过多关注底层的细节。通过调用这些 SDK 提供的接口,开发人员可以高效地开发出与 OpenEXR 文件处理相关的应用程序,如影视后期制作软件、图像编辑工具等。而 PyIlmBase 和 OpenEXR_Viewers 子目录中的内容,对于大多数 C++ 开发场景来说并非必需,它们更多地是为 Python 开发者或者需要进行文件查看和调试的人员提供便利。

通过对这些子目录及其包含工程的分析,我们可以全面了解 openexr 源代码的结构和功能,为后续的编译和开发工作打下坚实的基础。

2.2.2.工程预览

OpenEXR的子工程很多,这里先预览一下修改完CMakeLists.txt之后生产的vs工程,一屏幕的高度快放不下了。

2.2.3.修改CMake脚本

上面已经看到OpenEXR的子工程很多,修改关联的CMakeLists.txt脚本也会很多,这里给出其中一个修改的示例。

IlmBase\Half\CMakeLists.txt


# yue.nicholas@gmail.com

ADD_EXECUTABLE(eLut eLut.cpp)
ADD_CUSTOM_COMMAND(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/eLut.h
  COMMAND $<TARGET_FILE:eLut> ARGS > ${CMAKE_CURRENT_BINARY_DIR}/eLut.h
  DEPENDS eLut)
SET_SOURCE_FILES_PROPERTIES(
  ${CMAKE_CURRENT_BINARY_DIR}/eLut.h
  PROPERTIES HEADER_FILE_ONLY TRUE)

ADD_EXECUTABLE(toFloat toFloat.cpp)
ADD_CUSTOM_COMMAND(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/toFloat.h
  COMMAND $<TARGET_FILE:toFloat> ARGS > ${CMAKE_CURRENT_BINARY_DIR}/toFloat.h
  DEPENDS toFloat)

SET_SOURCE_FILES_PROPERTIES(
  ${CMAKE_CURRENT_BINARY_DIR}/toFloat.h
  PROPERTIES HEADER_FILE_ONLY TRUE)

SET_SOURCE_FILES_PROPERTIES(
  half.cpp
  PROPERTIES
  OBJECT_DEPENDS
  "${CMAKE_CURRENT_BINARY_DIR}/eLut.h;${CMAKE_CURRENT_BINARY_DIR}/toFloat.h"
)

SET(ILMBASE_LIB_TARGETS "")

# IF(OPENEXR_BUILD_SHARED)
#   LIST(APPEND ILMBASE_LIB_TARGETS Half)

#   ADD_LIBRARY(Half SHARED
#     half.cpp
#   )

#   TARGET_COMPILE_DEFINITIONS(Half PRIVATE HALF_EXPORTS)
#   IF(WIN32)
#     TARGET_COMPILE_DEFINITIONS(Half PUBLIC OPENEXR_DLL)
#   ENDIF()

#   SET_TARGET_PROPERTIES(Half
#     PROPERTIES
#     VERSION ${OPENEXR_VERSION}
#     SOVERSION ${OPENEXR_SOVERSION}
#     OUTPUT_NAME "Half${ILMBASE_LIBSUFFIX}"
#   )

#   ADD_DEPENDENCIES(Half toFloat eLut)
# ENDIF()

# IF(BUILD_ILMBASE_STATIC)
#   LIST(APPEND ILMBASE_LIB_TARGETS Half_static)

#   ADD_LIBRARY(Half_static STATIC
#     half.cpp
#   )

#   SET_TARGET_PROPERTIES(Half_static
#     PROPERTIES
#     VERSION ${ILMBASE_VERSION_MAJOR}.${ILMBASE_VERSION_MINOR}.${ILMBASE_VERSION_PATCH}
#     OUTPUT_NAME "Half${ILMBASE_LIBSUFFIX}_s"
#   )

#   ADD_DEPENDENCIES(Half_static toFloat eLut)
# ENDIF()

# IF(OPENEXR_BUILD_SHARED OR BUILD_ILMBASE_STATIC)
#   INSTALL(TARGETS
#     ${ILMBASE_LIB_TARGETS}
#     ARCHIVE DESTINATION lib
#     LIBRARY DESTINATION lib
#     RUNTIME DESTINATION ${RUNTIME_DIR}
#   )
# ENDIF()

# INSTALL(
#   FILES
#   half.h
#   halfFunction.h
#   halfExport.h
#   halfLimits.h

#   DESTINATION
#   include/OpenEXR
# )

# if(OPENEXR_BUILD_SHARED)
#   add_library(IlmBase::Half ALIAS Half)
# endif()
# if(BUILD_ILMBASE_STATIC)
#   add_library(IlmBase::Half_static ALIAS Half_static)
# endif()

# 静态库工程
add_library(Halflib STATIC
  half.cpp
)
add_dependencies(Halflib toFloat eLut)
add_library(IlmBase::Halflib ALIAS Halflib)

# 动态库工程
add_library(Halfdll SHARED
  half.cpp
)
target_compile_definitions(Halfdll PRIVATE HALF_EXPORTS)
if(WIN32)
  target_compile_definitions(Halfdll PUBLIC OPENEXR_DLL)
endif()
add_dependencies(Halfdll toFloat eLut)
add_library(IlmBase::Halfdll ALIAS Halfdll)


if(MSVC)
  # 静态库mt工程
  add_library(Halflibmt STATIC
    half.cpp
  )
  set_property(TARGET Halflibmt PROPERTY
    MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
  add_dependencies(Halflibmt toFloat eLut)
  add_library(IlmBase::Halflibmt ALIAS Halflibmt)

  # 动态库mt工程
  add_library(Halfdllmt SHARED
    half.cpp
  )
  set_property(TARGET Halfdllmt PROPERTY
    MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
  target_compile_definitions(Halfdllmt PRIVATE HALF_EXPORTS PUBLIC OPENEXR_DLL)
  add_dependencies(Halfdllmt toFloat eLut)
  add_library(IlmBase::Halfdllmt ALIAS Halfdllmt)

  # 设置静态库pdb文件
  set_lib_pdb_file(Half lib)
  set_lib_pdb_file(Half libmt)

endif(MSVC)

#安装sdk相关文件
#安装头文件
if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL)
  install(
    FILES
    half.h
    halfFunction.h
    halfExport.h
    halfLimits.h
    DESTINATION ${INSTALL_INC_DIR}
  )
endif()

if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
  #安装库文件
  set(Half_targets Halflib Halfdll)
  if(MSVC)
    list(APPEND Half_targets Halflibmt Halfdllmt)
  endif()
  install(TARGETS ${Half_targets}
    RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
    ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
    LIBRARY DESTINATION "${INSTALL_LIB_DIR}")
endif()

#安装pdb文件
if(NOT SKIP_INSTALL_PDB AND NOT SKIP_INSTALL_ALL)
  install(FILES $<TARGET_PDB_FILE:Halfdll> $<TARGET_PDB_FILE:Halfdllmt>
    DESTINATION "${INSTALL_BIN_DIR}"
    OPTIONAL)

  # 静态库pdb调用函数安装
  install_lib_pdb_file(Half lib)
  install_lib_pdb_file(Half libmt)
endif()

2.2.4.vs2008编译

前面我们已经把vs2008编译需要处理的源代码以及CMakeLists.txt脚本按照规范修改完毕,下面我们将使用cmake来构建vs2008的工程和编译。

2.2.4.1.使用cmake构建工程并编译

以前的文章中,已经有很多详细的cmake步骤了,操作流程都是一样的,其实也很简单。这里就不再累述了,注意设置build目录为源代码根目录下的cmake-vs2008绝对路径为D:/x-app/depends/c/libiconv-1.11.1/cmake-vs2008,已经编译器的选择即可。

这里勾选项注意一下,取消不需要的项,否则可能会构建报错。

2.2.4.2.编译工程

使用vs2008打开“OpenEXR.sln”解决方案文件,分别编译Debug和RelWithDebInfo配置。

根据下面截图可以看出来,编译后的库文件还是比较多的。

2.2.4.3.安装库文件、头文件

编译Install工程的Debug和RelWithDebInfo配置,.h文件和编译生成.dll、.lib、pdb文件会拷贝CMakeList.txt中设置的路径下。

2.2.5.vs2015编译

vs2015编译与vs2008相同的,只需要在CMake生成工程时选择vs2015即可,其他版本的vs也是一样的,选择需要使用的vs版本即可,此处只演示一下vs2015的编译。
因为前面生成过vs2008的工程,需要将build目录设置成cmake-vs2015,再“Configure”选择vs2015即可,其他操作就是一样的了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

binary0010

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值