From 72c2bb28bb1bd3fa307d8cea7889325e34fdc10e Mon Sep 17 00:00:00 2001 From: Brad Hards Date: Wed, 14 Feb 2024 20:58:09 +1100 Subject: [PATCH] wip: add support for relative path names This uses a C++-17 library feature for filesystem, which is pretty widely supported but still an additional requirement --- libheif/CMakeLists.txt | 2 ++ libheif/box.cc | 14 ++++++++------ libheif/box.h | 2 ++ libheif/file.cc | 18 ++++++++++++------ libheif/file.h | 2 ++ tests/CMakeLists.txt | 1 + 6 files changed, 27 insertions(+), 12 deletions(-) diff --git a/libheif/CMakeLists.txt b/libheif/CMakeLists.txt index 818a37b5ff..3913797862 100644 --- a/libheif/CMakeLists.txt +++ b/libheif/CMakeLists.txt @@ -116,6 +116,8 @@ target_compile_definitions(heif LIBHEIF_EXPORTS HAVE_VISIBILITY) +target_compile_features(heif PRIVATE cxx_std_17) + if (PLUGIN_LOADING_SUPPORTED_AND_ENABLED) target_compile_definitions(heif PRIVATE ENABLE_PLUGIN_LOADING=1) target_link_libraries(heif PRIVATE ${CMAKE_DL_LIBS}) diff --git a/libheif/box.cc b/libheif/box.cc index 892d8e1b48..7754c90298 100644 --- a/libheif/box.cc +++ b/libheif/box.cc @@ -1255,6 +1255,7 @@ Error Box_iloc::read_data(const Item& item, const std::shared_ptr& istr, const std::shared_ptr& idat, const std::shared_ptr& dinf, + const std::filesystem::path base_path, std::vector* dest) const { // TODO: this function should always append the data to the output vector as this is used when @@ -1313,11 +1314,12 @@ Error Box_iloc::read_data(const Item& item, (void) success; } else { std::string location = urlBox->get_location(); -#if defined(__MINGW32__) || defined(__MINGW64__) || defined(_MSC_VER) - auto input_stream_istr = std::unique_ptr(new std::ifstream(convert_utf8_path_to_utf16(location).c_str(), std::ios_base::binary)); -#else - auto datafile_istr = std::unique_ptr(new std::ifstream(location.c_str(), std::ios_base::binary)); -#endif + // TODO: handle case where its really a URL + std::filesystem::path locationPath(location); + if (locationPath.is_relative()) { + locationPath = base_path / locationPath; + } + auto datafile_istr = std::unique_ptr(new std::ifstream(locationPath, std::ios_base::binary)); if (!datafile_istr->good()) { std::stringstream sstr; sstr << "Error opening file: " << location << ", " << strerror(errno) << " (" << errno << ")\n"; @@ -1331,7 +1333,7 @@ Error Box_iloc::read_data(const Item& item, } } else { std::stringstream sstr; - sstr << "Item construction method 2 with data reference type " << dataentry->get_type_string() << "is not implemented"; + sstr << "Item construction method 2 with data reference type " << dataentry->get_type_string() << " is not implemented"; return Error(heif_error_Unsupported_feature, heif_suberror_Unsupported_item_construction_method, sstr.str()); diff --git a/libheif/box.h b/libheif/box.h index 7b41345d89..75e00556b6 100644 --- a/libheif/box.h +++ b/libheif/box.h @@ -34,6 +34,7 @@ #include #include #include +#include #include "error.h" #include "heif.h" @@ -392,6 +393,7 @@ class Box_iloc : public FullBox const std::shared_ptr& istr, const std::shared_ptr&, const std::shared_ptr&, + const std::filesystem::path base_path, std::vector* dest) const; void set_min_version(uint8_t min_version) { m_user_defined_min_version = min_version; } diff --git a/libheif/file.cc b/libheif/file.cc index 65e5ca8040..929ec4df74 100644 --- a/libheif/file.cc +++ b/libheif/file.cc @@ -27,6 +27,7 @@ #include "libheif/vvc.h" #include +#include #include #include #include @@ -83,7 +84,12 @@ Error HeifFile::read_from_file(const char* input_filename) sstr << "Error opening file: " << strerror(errno) << " (" << errno << ")\n"; return Error(heif_error_Input_does_not_exist, heif_suberror_Unspecified, sstr.str()); } - + std::filesystem::path input_path(input_filename); + if (input_path.has_parent_path()) { + m_base_path = input_path.parent_path(); + } else { + m_base_path.clear(); + } auto input_stream = std::make_shared(std::move(input_stream_istr)); return read(input_stream); } @@ -776,7 +782,7 @@ Error HeifFile::get_compressed_image_data(heif_item_id ID, std::vector* heif_suberror_No_item_data); } - error = m_iloc_box->read_data(*item, m_input_stream, m_idat_box, m_dinf_box, data); + error = m_iloc_box->read_data(*item, m_input_stream, m_idat_box, m_dinf_box, m_base_path, data); } else if (item_type == "av01") { // --- --- --- AV1 @@ -812,7 +818,7 @@ Error HeifFile::get_compressed_image_data(heif_item_id ID, std::vector* heif_suberror_No_item_data); } - error = m_iloc_box->read_data(*item, m_input_stream, m_idat_box, m_dinf_box, data); + error = m_iloc_box->read_data(*item, m_input_stream, m_idat_box, m_dinf_box, m_base_path, data); } else if (item_type == "jpeg" || (item_type == "mime" && get_content_type(ID) == "image/jpeg")) { @@ -838,7 +844,7 @@ Error HeifFile::get_compressed_image_data(heif_item_id ID, std::vector* } } - error = m_iloc_box->read_data(*item, m_input_stream, m_idat_box, m_dinf_box, data); + error = m_iloc_box->read_data(*item, m_input_stream, m_idat_box, m_dinf_box, m_base_path, data); } else if (item_type == "j2k1") { std::vector> properties; @@ -872,7 +878,7 @@ Error HeifFile::get_compressed_image_data(heif_item_id ID, std::vector* // heif_suberror_No_item_data); // } - error = m_iloc_box->read_data(*item, m_input_stream, m_idat_box, m_dinf_box, data); + error = m_iloc_box->read_data(*item, m_input_stream, m_idat_box, m_dinf_box, m_base_path, data); } else if (true || // fallback case for all kinds of generic metadata (e.g. 'iptc') item_type == "grid" || @@ -898,7 +904,7 @@ Error HeifFile::get_compressed_image_data(heif_item_id ID, std::vector* } if (read_uncompressed) { - error = m_iloc_box->read_data(*item, m_input_stream, m_idat_box, m_dinf_box, data); + error = m_iloc_box->read_data(*item, m_input_stream, m_idat_box, m_dinf_box, m_base_path, data); } } diff --git a/libheif/file.h b/libheif/file.h index 2ea8a22f27..c59c4ed377 100644 --- a/libheif/file.h +++ b/libheif/file.h @@ -26,6 +26,7 @@ #include "hevc.h" #include "nclx.h" +#include #include #include #include @@ -206,6 +207,7 @@ class HeifFile #endif std::shared_ptr m_input_stream; + std::filesystem::path m_base_path; std::vector > m_top_level_boxes; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6d619b7070..57fe4f9ee2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,6 +9,7 @@ configure_file(test-config.cc.in ${CMAKE_BINARY_DIR}/generated/test-config.cc) macro(add_libheif_test TEST_FILE) set(TEST_NAME ${TEST_FILE}) add_executable(${TEST_NAME} main.cc catch.hpp ${CMAKE_BINARY_DIR}/generated/test-config.cc test_utils.cc ${TEST_FILE}.cc) + target_compile_features(${TEST_NAME} PRIVATE cxx_std_17) target_link_libraries(${TEST_NAME} PRIVATE heif) add_test(NAME ${TEST_NAME} COMMAND ./${TEST_NAME}) endmacro()