简体   繁体   English

从 C++ 读取 iPhone 上的图像

[英]Read image on iPhone from C++

I am working on a C++ library that shall do image processing.我正在研究一个应该进行图像处理的 C++ 库。 My approach now is to pass two strings to C++ from swift.我现在的方法是将两个字符串从 swift 传递给 C++。 One string is the path to the image and the second is the output directory.第一个字符串是图像的路径,第二个字符串是 output 目录。

All the time I get that the file does not exist.我一直认为该文件不存在。 How can I get the correct path the asset?如何获得资产的正确路径? The image lies in a directory I have created on my own and is called "test.jpg".该图像位于我自己创建的目录中,名为“test.jpg”。 I also have a "test2.jpg" in Assets.我在资产中也有一个“test2.jpg”。 Have not managed to find that either.也没有设法找到。

Swift Code: Swift 代码:

func getGrayImage() -> Image {
    if var resourcePath = Bundle.main.url(forResource: "test", withExtension: "jpg") {
        let dir = resourcePath.deletingLastPathComponent()
        VideoProcessingWrapper().rgb2gray(resourcePath.absoluteString, dir.absoluteString)
    }
    return Image("test2")
}

C++ Code: C++ 代码:

void VideoProcessing::rgb2gray(const std::string& image_path, const std::string& dir) {
  std::cout << "C++: " << std::endl;
  std::cout << image_path << std::endl;
  std::cout << std::endl;
  std::cout << dir << std::endl;
  std::cout << "In directory: " <<std::endl;
  for (const auto& entry : std::filesystem::directory_iterator(dir)) {
        std::cout << entry.path() << std::endl;
  }
  if (std::filesystem::exists(image_path)) {
    std::cout << "File exists" << std::endl;
  } else {
    std::cout << "File does NOT exist" << std::endl;
    return;
  }
  cv::imread(image_path, cv::IMREAD_COLOR);
}

It even crashes when trying to display all files in the directory, stating that the directory does not exist.它甚至在尝试显示目录中的所有文件时崩溃,说明该目录不存在。 But what have I then been given from Bundle.main.url -call?但是,我从Bundle.main.url调用中得到了什么?

This is the printout from the C++ function using a simulator:这是 C++ function 使用模拟器的打印输出:

C++: 
file:///Users/name/Library/Developer/CoreSimulator/Devices/7F438661-8BF5-4A60-B41F-1D4B7FEC6A8E/data/Containers/Bundle/Application/AB3EFF3E-79A4-469C-A3BF-ABDD31A09E61/TestVideoProcess.app/test.jpg

file:///Users/name/Library/Developer/CoreSimulator/Devices/7F438661-8BF5-4A60-B41F-1D4B7FEC6A8E/data/Containers/Bundle/Application/AB3EFF3E-79A4-469C-A3BF-ABDD31A09E61/TestVideoProcess.app/

I get the same behaviour when running on a real iPhone.在真正的 iPhone 上运行时,我得到了相同的行为。

The problem here is that Foundation framework represent paths with URI 's, while C++ standard library filesystem relies on more file-path-specific format which may consist of only the following components :这里的问题是Foundation框架用URI表示路径,而 C++ 标准库文件系统依赖于更多的文件路径特定格式,它可能仅包含以下组件

  1. root-name(optional) : identifies the root on a filesystem with multiple roots (such as "C:" or "//myserver" ). root-name(optional) :标识具有多个根的文件系统上的根(例如"C:""//myserver" )。 In case of ambiguity, the longest sequence of characters that forms a valid root-name is treated as the root-name.在有歧义的情况下,将 forms 有效根名称的最长字符序列视为根名称。 The standard library may define additional root-names besides the ones understood by the OS API.除了 OS API 理解的根名称之外,标准库还可以定义其他根名称。
  2. root-directory(optional) : a directory separator that, if present, marks this path as absolute. root-directory(optional) :一个目录分隔符,如果存在,则将此路径标记为绝对路径。 If it is missing (and the first element other than the root name is a file name), then the path is relative and requires another path as the starting location to resolve to a file name.如果它丢失(并且除根名称之外的第一个元素是文件名),则路径是相对的,并且需要另一个路径作为起始位置才能解析为文件名。
  3. Zero or more of the following:以下零个或多个:
  • file-name : sequence of characters that aren't directory separators or preferred directory separators (additional limitations may be imposed by the OS or file system). file-name :不是目录分隔符或首选目录分隔符的字符序列(操作系统或文件系统可能会施加额外的限制)。 This name may identify a file, a hard link, a symbolic link, or a directory.此名称可以标识文件、硬链接、符号链接或目录。 Two special file-names are recognized:可以识别两个特殊的文件名:
  • dot : the file name consisting of a single dot character . dot :由单个点字符组成的文件名. is a directory name that refers to the current directory dot-dot: the file name consisting of two dot characters .. is a directory name that refers to the parent directory.是指当前目录的目录名 dot-dot:由两个点字符组成的文件名..是指父目录的目录名。
  • directory-separators : the forward slash character / or the alternative character provided as path::preferred_separator. directory-separators :正斜杠字符/或作为 path::preferred_separator 提供的替代字符。 If this character is repeated, it is treated as a single directory separator: /usr///////lib is the same as /usr/lib如果此字符重复,则将其视为单个目录分隔符: /usr///////lib/usr/lib相同

From the rules above I can conclude that the difference of a path from URI is at least that the latter contains scheme .从上面的规则我可以得出结论,路径与 URI 的区别至少在于后者包含scheme One trick you can refer to is to build the path from pathComponents of the URL class:您可以参考的一个技巧是从pathComponentsURL构建路径:

if let resourcePath = Bundle.main.url(forResource: "test", withExtension: "jpg") {
    let dir = resourcePath.deletingLastPathComponent()
    VideoProcessingWrapper().rgb2gray(resourcePath.pathComponents.joined(separator: "/"),
                                      dir.pathComponents.joined(separator: "/"))

}

Alternatively, as suggested by mani in the comments of your question , you can use the path property of the same class, but for some reason it's now deprecated.或者,正如mani在您的问题的评论中所建议的那样,您可以使用同一 class 的path属性,但由于某种原因,它现在已被弃用。

No matter what you do, the bundle directory is inside your application and you have no write access to it.无论您做什么,bundle 目录都在您的应用程序中,您对它没有写入权限。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM