【问题标题】:Read jpeg out of a stream provided by libcurl从 libcurl 提供的流中读取 jpeg
【发布时间】:2012-01-10 10:10:42
【问题描述】:

我有一个 IP 摄像机(哦,惊喜),我想从中获取一些照片。首先,我只想阅读一个 jpeg。由于所有通信都是通过 http 完成的,所以我使用的是 libcurl。所以我的代码看起来很简单:

// Initialize some stuff
CURL * curl;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.147/cgi-bin/mjpeg?mode=single");    curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION, write_test);

现在我很清楚我还需要两件事。我需要声明和定义回调函数( write_test ),我需要使用参数 CURLOPT_WRITEDATA 调用 curl_easy_setopt() 并给他一个流。

现在我不知道该怎么做。如果我只是给他一个普通的文件流并将所有的东西写入一个文件(就像它只是一些文本一样)它不会工作,因为普通的文件流不理解 jpeg。

我该怎么做?我需要像“libjpeg”这样的附加库吗?我将如何处理流?

//编辑:

好的,如上所述,我可以将单个 jpeg 的流转储到文件流中。现在这确实有效:

FILE* pFile = fopen("/home/username/test.jpeg","w");
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.147/cgi-bin/mjpeg?mode=single");
//curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION, write_test);
curl_easy_setopt(curl,CURLOPT_WRITEDATA, pFile);
curl_easy_perform(curl);

如果我不声明回调函数,它可以正常工作 - 但如果我不注释掉 CURLOP_WRITEFUNCTION 并自己声明回调,我不会得到好的结果。

->

size_t write_test(void *ptr, size_t size, size_t nmeb, void *stream)
{
    return fwrite(ptr,size,nmeb,static_cast<FILE*>(stream));
}

这不起作用....?

最好的问候

托比亚斯

【问题讨论】:

  • "因为普通的文件流不理解 jpeg,所以它不起作用。"它需要了解什么?如果您以带有 .jpg 扩展名的二进制模式写出文件,那会不会起作用?或者您是在获取没有 JFIF 标头的数据还是其他什么?还是希望先以某种方式处理文件?还是它给你一个连续的流,你需要剪切成单个图像,或者其他什么?
  • 哦,伙计,有时我觉得我不应该这么早工作——是的,我可以(当我只得到一张照片时)将所有流转储到一个文件中。但我没有注意到别的东西(只是在我上面的问题中指定它)
  • 您的 write_test 回调函数对我来说看起来没问题,因为它除了调用 fwrite 并使用与接收到的完全相同的参数之外没有做任何事情。可能是因为 write_test 是一个 C++ 函数,您需要以某种方式将其声明为 C 函数(即在 extern "C" { } 块内)?我不懂 C++。

标签: c++ http jpeg libcurl


【解决方案1】:

您希望将其转储到磁盘上的文件中,还是希望将其接收到内存缓冲区(或数据库,或其他任何东西)?无论哪种方式,cURL 都可以为您提供帮助。如果您希望它在文件中,那么您可以使用CURLOPT_WRITEDATA,正如您所说的,无需设置任何CURLOPT_WRITEFUNCTION。如果您希望它在内存缓冲区中,则必须同时提供CURLOPT_WRITEDATACURLOPT_WRITEFUNCTION,后者是指向您编写的函数的指针,该函数接受来自远程服务器的数据并将其存储在某处。

您想在获得 JPEG 后做什么?如果我理解正确,那似乎超出了您的问题范围,并且与 cURL 无关。 "libjpeg" 确实可以帮助你。

【讨论】:

    【解决方案2】:

    好的,我发现了问题所在:

    出于调试目的,我的“write_test”函数是这样实现的:

    size_t write_test(void *ptr, size_t size, size_t nmeb, void *stream)
    {
        memcpy(buffer,ptr,size*nmeb);
        size_t no;
    
        no = fwrite(ptr,size,nmeb,static_cast<FILE*>(stream));
        printf("no: %d\tsize: %d\tnmeb: %d\n",no,size,nmeb);
        return no;
    }
    

    现在很遗憾,我没有向您展示 memcpy 的部分(你是我的错......)。现在,如果我将其注释掉,程序就可以工作。现在我没有在那里搜索问题,因为 memcpy 不应该用数据影响我的 ptr。我猜它没有我只分配了 50 个字节的缓冲区。由于每次调用 write_test 函数时我都会得到 2kByte,我猜它有点损坏了内存。

    【讨论】:

      【解决方案3】:

      这是发布在 libcurl 网站上的解决方案。这个功能非常适合我和你一样的目标!

      struct MemoryStruct {
          char *memory;
          size_t size;
      };  
      
      
      size_t MailServer::WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
      {
          size_t realsize = size * nmemb;
          struct MemoryStruct *mem = (struct MemoryStruct *)userp;
      
          mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
          if(mem->memory == NULL) {
              /* out of memory! */ 
              printf("not enough memory (realloc returned NULL)\n");
              return 0;
          }
      
          memcpy(&(mem->memory[mem->size]), contents, realsize);
          mem->size += realsize;
          mem->memory[mem->size] = 0;
      
          return realsize;
      }
      

      希望对你有帮助! :D

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-03
        • 1970-01-01
        • 2014-09-06
        • 1970-01-01
        相关资源
        最近更新 更多