zoukankan      html  css  js  c++  java
  • 谷歌开源项目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 << "
    出错!" << std::endl;
    		}
    	}
    	std::cout << "处理完毕,按任意键退出." << std::endl;
    	getchar();
    	return 0;
    }
    

    本文只是抛砖引玉一下,若有其他相关问题或者需求也可以邮件联系我探讨。

     邮箱地址是:

    gaozhihan@vip.qq.com

  • 相关阅读:
    bzoj1600 [Usaco2008 Oct]建造栅栏(递推)
    bzoj1607 / P2926 [USACO08DEC]拍头Patting Heads
    bzoj2733 / P3224 [HNOI2012]永无乡(并查集+线段树合并)
    loj2163 / bzoj2212 / P3521 [POI2011]ROT-Tree Rotations(线段树合并)
    UVA11090 Going in Cycle!!(二分判负环)
    【C++】位应用(2)-设置某位的值
    【C++】位应用(2)-设置某位的值
    【C++】位操作的应用
    【C++】位操作的应用
    C++ 强转注意问题
  • 原文地址:https://www.cnblogs.com/cpuimage/p/5143350.html
Copyright © 2011-2022 走看看