谷歌开源项目Google Preview Image Extractor(PIEX) (附上完整demo代码)
前天偶然看到谷歌开源项目中有一个近乎无人问津的项目Google Preview Image Extractor(PIEX) 。
项目地址:
https://github.com/google/piex
官方的描述是这样的:
The Preview Image Extractor (PIEX) is designed to find and extract the largest JPEG compressed preview image contained in a RAW file. 也就是说,这个项目是用来提取无损图片格式(RAW格式)中内嵌的JPG预览。阅读代码和实际编写demo后,发现不是所有的无损图片格式(RAW格式)都有内嵌jpg预览,理论上最新的摄像设备应该都支持内嵌预览图了。支持解析载入如下图像格式: ARW, CR2, DNG, NEF, NRW, ORF, PEF, RAF, RW2, SRW感觉支持的格式也挺全面的。 而该项目下面没有example相关的代码,由于感兴趣,故阅读其代码写了demo。 这个项目可以考虑用在特定情况下加速加载无损格式的预览图,提升用户体验。 关于本人采用的一些RAW格式素材的下载,见链接:
http://www.ed2kfile.com/126607注:这些素材有部分是没有内嵌预览jpg的。 贴上对应的提取效果图: [无损格式图片集合].sony_a200_3[www.ed2kfile.com].ARW 电驴下载链接:ed2k://|file|[%E6%97%A0%E6%8D%9F%E6%A0%BC%E5%BC%8F%E5%9B%BE%E7%89%87%E9%9B%86%E5%90%88].sony_a200_3[www.ed2kfile.com].ARW|10689180|c0ed57fc9898e1f75d55cdca62cd8ee8|h=gsggltnbno7emg4l2ns5qyi6pedcnub3|/
预览图:
缩略图:
贴上完整demo代码:
#include <iostream> #include <windows.h> #include "piex/piex.h" #include "piex/piex_types.h" #include <fstream> #include <vector> #if defined(_MSC_VER) || defined(__ANDROID_API__) #define USE_OMP #endif #ifndef USE_OMP #include <chrono> auto const epoch = std::chrono::steady_clock::now(); double now() { return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - epoch).count() / 1000.0; }; #else #include <omp.h> auto const epoch = omp_get_wtime(); double now() { return omp_get_wtime() - epoch; }; #endif template<typename FN> double bench(const FN &fn) { auto took = -now(); return (fn(), took + now()); } #include <chrono> #include <thread> void sleep(double secs) { std::chrono::microseconds duration((int)(secs * 1000000)); std::this_thread::sleep_for(duration); } class FileStream : public piex::StreamInterface { public: FileStream(const std::string & file) { if (file.empty()) { buffer.clear(); bufferSize = 0; return; } std::ifstream ifs(file.c_str(), std::ios::binary); if (!ifs.good()) { buffer.clear(); bufferSize = 0; return; } std::vector<unsigned char> curBuffer((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>())); buffer.swap(curBuffer); bufferSize = buffer.size(); } FileStream(std::vector<unsigned char>& abuffer) { int bufsize = abuffer.size(); if (bufsize > 0) { buffer.resize(bufsize); memcpy(buffer.data(), abuffer.data(), bufsize*sizeof(unsigned char)); bufferSize = bufsize; } } ~FileStream(){ bufferSize = 0; buffer.clear(); }; piex::Error GetData(const size_t offset, const size_t length, unsigned char* data) { if (bufferSize > 0) { unsigned char *readOffset = &buffer[offset]; unsigned char *endBuffer = &buffer[bufferSize - 1]; if ((readOffset + length) <= endBuffer) { memcpy(data, readOffset, length); return piex::kOk; } else { return piex::kFail; } } return piex::kUnsupported; } std::vector<unsigned char>& GetBuffer() { return buffer; } protected: std::vector<unsigned char> buffer; int bufferSize = 0; }; bool writefile(const std::string &filename, const std::vector< char>& buffer) { if (!buffer.empty()) { std::ofstream ofs(filename.c_str(), std::ios::binary); ofs.write(&buffer[0], buffer.size()); return ofs.good(); } return false; } int main(int argc, char **argv) { std::cout << "Google Preview Image Extractor(PIEX) Demo" << std::endl; std::cout << "项目地址:https://github.com/google/piex" << std::endl; std::cout << "-----------------------------------------------------" << std::endl; std::cout << "支持解析载入如下图像格式: " << std::endl; std::cout << "ARW, CR2, DNG, NEF, NRW, " << std::endl; std::cout << "ORF, PEF, RAF, RW2, SRW" << std::endl; std::cout << " 输出JPG图像格式." << std::endl; std::cout << "Demo By Gaozhihan (Build 2016-01-19)" << std::endl; std::cout << "本人博客: http://tntmonks.cnblogs.com/" << std::endl; std::cout << "-----------------------------------------------------" << std::endl; if (argc < 2) { std::cout << "用法: " << argv[0] << " rawImage [rawImage [...]]" << std::endl; return -1; } std::string szfile; std::string savefile; for (int i = 1; i < argc; ++i) { szfile = argv[i]; std::cout << "加载文件: " << std::endl << szfile.c_str() << std::endl; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; _splitpath_s(szfile.c_str(), drive, dir, fname, ext); savefile += drive; savefile += dir; savefile += fname; savefile += "_"; std::vector< char> previewBuffer; std::vector< char> previewThumbnail; try { double costTime = bench([&]{ FileStream fsfile(szfile.c_str()); piex::StreamInterface* data_stream = &fsfile; piex::PreviewImageData rawPreviewImage; piex::Error piexErr = piex::GetPreviewImageData(data_stream, &rawPreviewImage); if (piexErr == piex::Error::kFail) { std::cout << "传入的无损格式文件数据有误." << std::endl; } else if (piexErr == piex::Error::kUnsupported) { std::cout << "传入的无损格式文件数据不支持." << std::endl; } else { std::cout << " 有效raw 格式,提取内嵌预览数据." << std::endl; previewBuffer.resize(rawPreviewImage.preview_length); memcpy(previewBuffer.data(), fsfile.GetBuffer().data() + rawPreviewImage.preview_offset, rawPreviewImage.preview_length); previewThumbnail.resize(rawPreviewImage.thumbnail_length); memcpy(previewThumbnail.data(), fsfile.GetBuffer().data() + rawPreviewImage.thumbnail_offset, rawPreviewImage.thumbnail_length); } }); std::cout << " 处理耗时: " << int(costTime * 1000) << " ms" << std::endl; std::string previewFile = savefile; previewFile += "_preview.jpg"; std::string thumbnailFile = savefile; thumbnailFile += "_thumbnail.jpg"; costTime = bench([&]{ writefile(previewFile, previewBuffer); writefile(thumbnailFile, previewThumbnail); }); std::cout << " 保存耗时: " << int(costTime * 1000) << " ms" << std::endl; ShellExecuteA(NULL, "open", previewFile.c_str(), NULL, NULL, SW_SHOW); } catch (...) { std::cout << "\r出错!" << std::endl; } } std::cout << "处理完毕,按任意键退出." << std::endl; getchar(); return 0; }
本文只是抛砖引玉一下,若有其他相关问题或者需求也可以邮件联系我探讨。
邮箱地址是:
gaozhihan@vip.qq.com
谷歌开源项目Google Preview Image Extractor(PIEX) (附上完整demo代码)的更多相关文章
- 谷歌开源项目Chromium的源码获取与项目构建(Win7+vs10/vs13)
转自:http://blog.csdn.net/kuerjinjin/article/details/23563059 从12年那会儿开始获取源码和构建chromium项目都是按照那时候的官方要求用w ...
- 【转】Android开源项目(非组件)
原文网址:http://blog.csdn.net/feizhixuan46789/article/details/9252887 学习开发一个有效的途径就是借鉴成熟的案例作为学习的对象,下面为大家推 ...
- apache基金会开源项目简介
apache基金会开源项目简介 项目名称 描述 HTTP Server 互联网上首屈一指的HTTP服务器 Abdera Apache Abdera项目的目标是建立一个功能完备,高效能的IETF ...
- Golang优秀开源项目汇总, 10大流行Go语言开源项目, golang 开源项目全集(golang/go/wiki/Projects), GitHub上优秀的Go开源项目
Golang优秀开源项目汇总(持续更新...)我把这个汇总放在github上了, 后面更新也会在github上更新. https://github.com/hackstoic/golang-open- ...
- 如何参与开源项目 - 细说 GitHub 上的 PR 全过程
目录 一.概述 二.为什么要参与开源项目 三.为什么我想介绍如何 PR 四.我想参与开源项目,怎么开始? 4.1.寻找一个合适的开源项目 4.2.寻找贡献点 五.我要提交 PR,怎么上手? 5.1.第 ...
- .NET平台开源项目速览(14)最快的对象映射组件Tiny Mapper
好久没有写文章,工作甚忙,但每日还是关注.NET领域的开源项目.五一休息,放松了一下之后,今天就给大家介绍一个轻量级的对象映射工具Tiny Mapper:号称是.NET平台最快的对象映射组件.那就一起 ...
- Android(java)学习笔记207:开源项目使用之gif view
1. 由于android没有自带的gif动画,我在Android(java)学习笔记198:Android下的帧动画(Drawable Animation) 播客中提到可以使用AnimationVie ...
- 开源项目福利-github开源项目免费使用Azure PipeLine
微软收购Github后,很多人猜想微软可能会砍掉VSTS,然而事实VSTS并没有砍掉,关于Azure Devops的详细信息可以查看 这篇博客,如果想查看原文也可以从链接里提供的原始地址里查看. 今天 ...
- 如何把开源项目发布到Jcenter
转载自:https://www.jianshu.com/p/f66972f0607a 首先我们应该注册一个JFrog Bintray的账号 Jfrog Bintray官网 这里我们可以注意到那个绿色的 ...
随机推荐
- Qt 框架 开发HTTP 服务器 开发记录
最近需求需要开发一款 HTTP ,然后由于先前接触过Qt,就直接用Qt写HTTP服务器了,也是为了当作练手,要不然是直接上HTTP框架的. 后端用C++ Qt框架 前端为了练手 当然是纯生的 js h ...
- Little Jumper---(三分)
Description Little frog Georgie likes to jump. Recently he have discovered the new playground that s ...
- 关于我的OI生涯(AFO){NOIP2016 后}
这篇我就随意写啦~不用统一的“题解”形式.♪(^∀^●)ノ 也分好几次慢慢更吧~ 对于NOIP2016的总结,我本想善始善终back回,但是心情不足以支撑我,那就只能有始有终了......下面进入我的 ...
- PHP Warning: Module 'modulename' already loaded in Unknown on line 0
问题 当在命令行运行PHP的CLI版本时,您可能会收到类似以下错误: [root@myserver /root]$ php -v PHP Warning: Module 'pcre' already ...
- Python语言规范及风格规范
语言规范: http://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/python_language_ ...
- PEM (Privacy Enhanced Mail) Encoding
PEM (Privacy Enhanced Mail) Encoding The moPEM (Privacy Enhanced Mail) Encoding The most commonly us ...
- 将32位MD5摘要串转换为128位二进制字符串
将32为MD5摘要串转换为128位二进制字符串: /// <summary> /// 将字符串转成二进制 /// </summary> /// <param name=& ...
- ajax跨子域请求的两种现代方法
因为面向互联网的性质,我们公司的大部分系统都采用多子域的方式进行开发和部署,以达到松耦合和分布式的目的,因此子系统间的交互不可避免.虽然通过后台的rpc框架解决了大部分的交互问题,但有些情况下,前端直 ...
- ASP.NET MVC 5 学习教程:快速入门
起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 通过控制器访问模型的数据 生成的代码详解 使用 SQL Se ...
- Ajax基本知识
1.创建xhr对象 var xmlhttp; if (window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safari x ...