zoukankan      html  css  js  c++  java
  • bayer转dng实现过程记录

    前言

      项目中需要将imx185出来的raw数据转成dng格式,一开始认为很简单的事情,后面才发现还是挺复杂的!!!首先考虑的是不写任何代码,直接用adobe提供的转换工具来转,结果发现,不仅是adobe的工具,网上能够找到的工具(所谓的raw转dng)都是针对各大厂商的raw,而不能支持最原始的bayer raw。于是又考虑了两种解决方式,第一种就是将bayer raw随便转换成某一个厂商的raw(CR2, CRW, DNG, MRW, NEF, ORF, RAF, DCR, ARW中的一种),然后用所谓的raw转dng工具再转dng,结果发现厂商的raw一般都是不开放的,网上虽然有一些逆向工程,但不完整,没办法,只好用第二种方案了。第二种方案是考虑基于adobe提供的dng_sdk开发一个bayer转dng的程序,但是这个工作量真的很大,首先得完全弄懂dng格式,其次,adobe的sdk没有任何文档(html文件夹下有点点,但那个没多大作用),网上也找到不任何关于该sdk的说明!没办法,只好边看dng_spec_1.4.0.0边一步步解决。幸运的时,偶然在论坛上发现了两个关于bayer转dng的讨论,根据他们的代码,实现了转换。

    dng_sdk linux移植具体步骤

      adobe官方提供的dng_sdk只有windows和mac版本,而我用的是linux系统,所以得想办法将其移植到linux里去。网上有有两种方案可以参考,方案一,一步一步按照他说的移植就ok了,方案二,也是一步一步根据他里面的文档并结合dng_sdk文档来移植。两种方案我都有试过,都是可行的,下面我主要基于第二种方案来说说具体的实践过程。

    安装依赖jpeg

    在ubuntu下,要安装jpeg依赖很简单,一条命令搞定

    sudo apt-get install cmake libjpeg8-dev uuid-dev
    

    安装依赖xmp sdk

    下载xmp_sdk

    wget http://download.macromedia.com/pub/developer/xmp/sdk/XMP-Toolkit-SDK-CC-201306.zip
    unzip XMP-Toolkit-SDK-CC-201306.zip
    mv XMP-Toolkit-SDK-CC201306 xmp_sdk
    

    然后根据xmp_sdk/third-party下各子目录里的ReadMe.txt安装其他一些依赖

    zlib

    cd xmp_sdk/third-party/zlib
    wget http://zlib.net/zlib-1.2.8.tar.gz
    tar xzf zlib-1.2.8.tar.gz
    cp zlib-1.2.8/*.h zlib-1.2.8/*.c .
    

    expat

    cd xmp_sdk/third-party/expat
    Download here the source at http://sourceforge.net/projects/expat/files/expat/2.1.0/expat-2.1.0.tar.gz/download.
    tar xzf expat-2.1.0.tar.gz
    cp -R expat-2.1.0/lib .
    

    dng sdk编译

    在xmp_sdk文件夹所在的目录下执行以下命令获取源码

    git clone https://github.com/yanburman/dng_sdk.git
    

    进入目录projects/linux/,执行make即可编译生成dng_validate,该工具用于校验dng文件,后面生成的文件可以通过该工具来检测。

    bayer转dng编译

    拷贝下面的代码并命名为bayer2dng.cpp,

    #include <iostream>
    
    #include "dng_color_space.h"
    #include "dng_date_time.h"
    #include "dng_exceptions.h"
    #include "dng_file_stream.h"
    #include "dng_globals.h"
    #include "dng_host.h"
    #include "dng_ifd.h"
    #include "dng_image_writer.h"
    #include "dng_info.h"
    #include "dng_linearization_info.h"
    #include "dng_mosaic_info.h"
    #include "dng_negative.h"
    #include "dng_preview.h"
    #include "dng_render.h"
    #include "dng_simple_image.h"
    #include "dng_tag_codes.h"
    #include "dng_tag_types.h"
    #include "dng_tag_values.h"
    #include "dng_xmp.h"
    #include "dng_xmp_sdk.h"
    #include "dng_camera_profile.h"
    // --------------------------------------------------------------------------------
    //
    // MakeDNGSample
    //
    int main(int argc, char *argv[])
    {
    	// Sample BAYER image at ISO100 and tEXP 1/10 on f/4.0 and focal length 10mm
    	std::string m_szInputFile = "pic6";
    	uint16 m_unISO = 100;
    	double m_dExposureTime = 0.1;
    	double m_dLensAperture = 4.0;
    	double m_dFocalLength = 10.0;
    
    	// SETTINGS: 12-Bit RGGB BAYER PATTERN
    	uint8 m_unColorPlanes = 3;
    	uint8 m_unBitDepth = 12;
    	uint16 m_unBayerType = 1;    // RGGB
    	uint32 m_ulWidth = 1920;
    	uint32 m_ulHeight = 1225;
    	uint32 m_ulBlackLevel = 200;
    
    	// SETTINGS: Whitebalance D65, Orientation "normal"
    	dng_orientation m_oOrientation = dng_orientation::Normal();
    	dng_xy_coord m_oWhitebalanceDetectedXY = D65_xy_coord();
    
    	// SETTINGS: Names
    	std::string m_szMake = "My Company";
    	std::string m_szCameraModel = "My Camera";
    	std::string szProfileName = m_szCameraModel;
    	std::string szProfileCopyright = m_szMake;
    
    	// Calculate bit limit
    	uint16 m_unBitLimit = 0x01 << m_unBitDepth;
    
    	// Form output filenames
    	std::string szBaseFilename = "";
    	std::string m_szOutputFile = "";
    	std::string m_szRenderFile = "";
    	std::string m_szPathPrefixInput = "";
    	std::string m_szPathPrefixOutput = "";
    	std::string m_szPathPrefixProfiles = "";
    	size_t unIndex = m_szInputFile.find_last_of(".");
    	if (unIndex == std::string::npos)
    	{
    		szBaseFilename = m_szInputFile;
    	}
    	else
    	{
    		szBaseFilename = m_szInputFile.substr(0, unIndex);
    	}
    	m_szInputFile = m_szPathPrefixInput + m_szInputFile;
    	m_szOutputFile = m_szPathPrefixOutput + szBaseFilename + ".dng";
    	m_szRenderFile = m_szPathPrefixOutput + szBaseFilename + ".tiff";
    
    	// Create DNG
    	try
    	{
    		dng_host oDNGHost;
    
    		// -------------------------------------------------------------
    		// Print settings
    		// -------------------------------------------------------------
    
    		printf("
    ");
    		printf("===============================================================================
    ");
    		printf("Simple DNG converter
    ");
    		printf("===============================================================================
    
    ");
    		printf("
    ");
    		printf("BAYER:
    ");
    		printf("%s
    ", m_szInputFile.c_str());
    
    		printf("
    Converting...
    ");
    
    		// -------------------------------------------------------------
    		// BAYER input file settings
    		// -------------------------------------------------------------
    		dng_file_stream oBayerStream(m_szInputFile.c_str());
            //oBayerStream.SetLittleEndian(false);
    
    		uint32 ullBayerSize = (uint32)oBayerStream.Length();
    
    		AutoPtr<dng_memory_block> oBayerData(oDNGHost.Allocate(ullBayerSize));
    
    		oBayerStream.SetReadPosition(0);
    
    		oBayerStream.Get(oBayerData->Buffer(), ullBayerSize);
    
    		// -------------------------------------------------------------
    		// DNG Host Settings
    		// -------------------------------------------------------------
    
    		// Set DNG version
    		// Remarks: Tag [DNGVersion] / [50706]
    		oDNGHost.SetSaveDNGVersion(dngVersion_SaveDefault);
    
    		// Set DNG type to RAW DNG
    		// Remarks: Store Bayer CFA data and not already processed data
    		oDNGHost.SetSaveLinearDNG(false);
    
    		// -------------------------------------------------------------
    		// DNG Image Settings
    		// -------------------------------------------------------------
    
    		dng_rect vImageBounds(m_ulHeight, m_ulWidth);
    
    		AutoPtr<dng_image> oImage(oDNGHost.Make_dng_image(vImageBounds, m_unColorPlanes, ttShort));
    
    		dng_pixel_buffer oBuffer;
    
    		oBuffer.fArea      = vImageBounds;
    		oBuffer.fPlane     = 0;
    		oBuffer.fPlanes    = 1;
    		oBuffer.fRowStep   = oBuffer.fPlanes * m_ulWidth;
    		oBuffer.fColStep   = oBuffer.fPlanes;
    		oBuffer.fPlaneStep = 1;
    		oBuffer.fPixelType = ttShort;
    		oBuffer.fPixelSize = TagTypeSize(ttShort);
    		oBuffer.fData      = oBayerData->Buffer();
    
    		oImage->Put(oBuffer);
    
    
    		// -------------------------------------------------------------
    		// DNG Negative Settings
    		// -------------------------------------------------------------
    
    		AutoPtr<dng_negative> oNegative(oDNGHost.Make_dng_negative());
    
    		// Set camera model
    		// Remarks: Tag [UniqueCameraModel] / [50708]
    		oNegative->SetModelName(m_szCameraModel.c_str());
    
    		// Set localized camera model
    		// Remarks: Tag [UniqueCameraModel] / [50709]
    		oNegative->SetLocalName(m_szCameraModel.c_str());
    
    		// Set bayer pattern information
    		// Remarks: Tag [CFAPlaneColor] / [50710] and [CFALayout] / [50711]
    		oNegative->SetColorKeys(colorKeyRed, colorKeyGreen, colorKeyBlue);
    
    		// Set bayer pattern information
    		// Remarks: Tag [CFAPlaneColor] / [50710] and [CFALayout] / [50711]
    		oNegative->SetBayerMosaic(m_unBayerType);
    
    		// Set bayer pattern information
    		// Remarks: Tag [CFAPlaneColor] / [50710] and [CFALayout] / [50711]
    		oNegative->SetColorChannels(m_unColorPlanes);
    
    		// Set linearization table
    		// Remarks: Tag [LinearizationTable] / [50712]
    		AutoPtr<dng_memory_block> oCurve(oDNGHost.Allocate(sizeof(uint16)*m_unBitLimit));
    		for ( int32 i=0; i<m_unBitLimit; i++ )
    		{
    			uint16 *pulItem = oCurve->Buffer_uint16() + i;
    			*pulItem = (uint16)(i);
    		}
    		oNegative->SetLinearization(oCurve);
    
    		// Set black level to auto black level of sensor
    		// Remarks: Tag [BlackLevel] / [50714]
    		oNegative->SetBlackLevel(m_ulBlackLevel);
    
    		// Set white level
    		// Remarks: Tag [WhiteLevel] / [50717]
    		oNegative->SetWhiteLevel(m_unBitLimit-1);
    
    		// Set scale to square pixel
    		// Remarks: Tag [DefaultScale] / [50718]
    		oNegative->SetDefaultScale(dng_urational(1,1), dng_urational(1,1));
    
    		// Set scale to square pixel
    		// Remarks: Tag [BestQualityScale] / [50780]
    		oNegative->SetBestQualityScale(dng_urational(1,1));
    
    		// Set pixel area
    		// Remarks: Tag [DefaultCropOrigin] / [50719]
    		oNegative->SetDefaultCropOrigin(0, 0);
    
    		// Set pixel area
    		// Remarks: Tag [DefaultCropSize] / [50720]
    		oNegative->SetDefaultCropSize(m_ulWidth, m_ulHeight);
    
    		// Set base orientation
    		// Remarks: See Restriction / Extension tags chapter
    		oNegative->SetBaseOrientation(m_oOrientation);
    
    		// Set camera white XY coordinates
    		// Remarks: Tag [AsShotWhiteXY] / [50729]
    		oNegative->SetCameraWhiteXY(m_oWhitebalanceDetectedXY);
    
    		// Set baseline exposure
    		// Remarks: Tag [BaselineExposure] / [50730]
    		oNegative->SetBaselineExposure(0);
    
    		// Set if noise reduction is already applied on RAW data
    		// Remarks: Tag [NoiseReductionApplied] / [50935]
    		oNegative->SetNoiseReductionApplied(dng_urational(0,1));
    
    		// Set baseline sharpness
    		// Remarks: Tag [BaselineSharpness] / [50732]
    		oNegative->SetBaselineSharpness(1);
    
    		// -------------------------------------------------------------
    		// DNG EXIF Settings
    		// -------------------------------------------------------------
    
    		dng_exif *poExif = oNegative->GetExif();
    
    		// Set Camera Make
    		// Remarks: Tag [Make] / [EXIF]
    		poExif->fMake.Set_ASCII(m_szMake.c_str());
    
    		// Set Camera Model
    		// Remarks: Tag [Model] / [EXIF]
    		poExif->fModel.Set_ASCII(m_szCameraModel.c_str());
    
    		// Set ISO speed
    		// Remarks: Tag [ISOSpeed] / [EXIF]
    		poExif->fISOSpeedRatings[0] = m_unISO;
    		poExif->fISOSpeedRatings[1] = 0;
    		poExif->fISOSpeedRatings[2] = 0;
    
    		// Set WB mode
    		// Remarks: Tag [WhiteBalance] / [EXIF]
    		poExif->fWhiteBalance = 0;
    
    		// Set metering mode
    		// Remarks: Tag [MeteringMode] / [EXIF]
    		poExif->fMeteringMode = 2;
    
    		// Set metering mode
    		// Remarks: Tag [ExposureBiasValue] / [EXIF]
    		poExif->fExposureBiasValue = dng_srational(0, 0);
    
    		// Set aperture value
    		// Remarks: Tag [ApertureValue] / [EXIF]
    		poExif->SetFNumber(m_dLensAperture);
    
    		// Set exposure time
    		// Remarks: Tag [ExposureTime] / [EXIF]
    		poExif->SetExposureTime(m_dExposureTime);
    
    		// Set focal length
    		// Remarks: Tag [FocalLength] / [EXIF]
    		poExif->fFocalLength.Set_real64(m_dFocalLength, 1000);
    
    		// Set lens info
    		// Remarks: Tag [LensInfo] / [EXIF]
    		poExif->fLensInfo[0].Set_real64(m_dFocalLength, 10);
    		poExif->fLensInfo[1].Set_real64(m_dFocalLength, 10);
    		poExif->fLensInfo[2].Set_real64(m_dLensAperture, 10);
    		poExif->fLensInfo[3].Set_real64(m_dLensAperture, 10);
    
    		// -------------------------------------------------------------
    		// DNG Profile Settings: Simple color calibration
    		// -------------------------------------------------------------
    
    		// Camera space RGB to XYZ matrix with D65 illumination
    		// Remarks: Derived from MATLAB using least square linear regression with
    		//          MacBeth ColorChecker classic
    		dng_matrix_3by3 oCameraRGB_to_XYZ_D65 = dng_matrix_3by3( 2.3150, 0.0711, 0.1455,
    				0.9861, 0.7815,-0.2192,
    				0.2082,-0.3349, 1.6432 );
    		uint32 ulCalibrationIlluminant1 = lsD65;
    
    		// Camera space RGB to XYZ matrix with StdA illumination
    		// Remarks: Derived from MATLAB using least square linear regression with
    		//          MacBeth ColorChecker classic
    		dng_matrix_3by3 oCameraRGB_to_XYZ_A = dng_matrix_3by3(   1.6335, 0.4718,-0.0656,
    				0.5227, 1.0298,-0.3416,
    				0.0475,-0.2020 ,1.2522 );
    
    		uint32 ulCalibrationIlluminant2 = lsStandardLightA;
    
    		AutoPtr<dng_camera_profile> oProfile(new dng_camera_profile);
    
    		// Set first illuminant color calibration if available
    		if ( ulCalibrationIlluminant1!=0 )
    		{
    			// Set calibration illuminant 1
    			// Remarks: Tag [CalibrationIlluminant1] / [50778]
    			oProfile->SetCalibrationIlluminant1(ulCalibrationIlluminant1);
    
    			// Set color matrix 1
    			// Remarks: Tag [ColorMatrix1] / [50721]
    			oProfile->SetColorMatrix1(Invert(oCameraRGB_to_XYZ_D65));
    		}
    
    		// Set second illuminant color calibration if available
    		if ( ulCalibrationIlluminant2!=0 )
    		{
    			// Set calibration illuminant 2
    			// Remarks: Tag [CalibrationIlluminant2] / [50779]
    			oProfile->SetCalibrationIlluminant2(ulCalibrationIlluminant2);
    
    			// Set color matrix 1
    			// Remarks: Tag [ColorMatrix2] / [50722]
    			oProfile->SetColorMatrix2(Invert(oCameraRGB_to_XYZ_A));
    		}
    
    		// Set name of profile
    		// Remarks: Tag [ProfileName] / [50936]
    		oProfile->SetName(szProfileName.c_str());
    
    		// Set copyright of profile
    		// Remarks: Tag [ProfileCopyright] / [50942]
    		oProfile->SetCopyright(szProfileCopyright.c_str());
    
    		// Force flag read from DNG to make sure this profile will be embedded
    		oProfile->SetWasReadFromDNG(true);
    
    		// Set policy for profile
    		// Remarks: Tag [ProfileEmbedPolicy] / [50941]
    		oProfile->SetEmbedPolicy(pepAllowCopying);
    
    		// Add camera profile to negative
    		oNegative->AddProfile(oProfile);
    
    		// -------------------------------------------------------------
    		// Write DNG file
    		// -------------------------------------------------------------
    
    		// Assign Raw image data.
    		oNegative->SetStage1Image(oImage);
    
    		// Compute linearized and range mapped image
    		oNegative->BuildStage2Image(oDNGHost);
    
    		// Compute demosaiced image (used by preview and thumbnail)
    		oNegative->BuildStage3Image(oDNGHost);
    
    		// Update XMP / EXIF
    		oNegative->SynchronizeMetadata();
    
    		// Update IPTC
    		oNegative->RebuildIPTC(true);
    
    		// Create stream writer for output file
    		dng_file_stream oDNGStream(m_szOutputFile.c_str(), true);
            //oDNGStream.SetSwapBytes(1);
    
    		// Write DNG file to disk
    		AutoPtr<dng_image_writer> oWriter(new dng_image_writer());
    		oWriter->WriteDNG(oDNGHost, oDNGStream, *oNegative.Get(), NULL, ccUncompressed);
    
     #if 0
    		// -------------------------------------------------------------
    		// Write TIFF file
    		// -------------------------------------------------------------
    
    		// Create stream writer for output file
    		dng_file_stream oTIFFStream(m_szRenderFile.c_str(), true);
    
    		// Create render object
    		dng_render oRender (oDNGHost, *oNegative);
    
    		// Set exposure compensation
    		oRender.SetExposure(0.0);
    
    		// Create final image
    		AutoPtr<dng_image> oFinalImage;
    
    		// Render image
    		oFinalImage.Reset (oRender.Render ());
    		oFinalImage->Rotate(oNegative->Orientation());
    
    		// Write TIFF file to disk
    		oWriter->WriteTIFF(oDNGHost, oTIFFStream, *oFinalImage.Get(), piRGB, ccUncompressed, oNegative.Get(), &oRender.FinalSpace ());
    #endif
    
    	}
    
    	catch (const dng_exception &except)
    	{
    
    		return except.ErrorCode ();
    
    	}
    
    	catch (...)
    	{
    
    		return dng_error_unknown;
    
    	}
    
    	printf ("Conversion complete
    ");
    
    	return 0;
    }
    

    保存,然后执行下面命令编译

    g++ bayer2dng.cpp -I../../../xmp_sdk/public/include -I../../source libdng_sdk.a -ljpeg -lz -lpthread -ldl ../../../xmp_sdk/public/libraries/i80386linux_x64/release//staticXMPFiles.ar ../../../xmp_sdk/public/libraries/i80386linux_x64/release//staticXMPCore.ar -ldl -o bayer2dng
    

    即可生成bayer转rgb的工具bayer2dng了。

    总结

      上面的bayer2dng.cpp仅仅是将1920 1225分辨率 12bit RGGB格式的raw转为dng格式的文件,里面很多参数都需要根据实际情况调整,比如曝光时间、iso、光圈大小、焦距、线性表等等,所以继续研究dng格式是避免不了的_

    引用

    完!
    2016年12月

  • 相关阅读:
    制作OSGB数据索引
    汤臣一品
    Python 库/模块的安装、查看
    ezdxf包下autocad的开发
    python3.7安装pylint
    航拍全景图补天
    电脑百科
    使用Excel批量提取文件名
    利用爬虫实现网上的图片自动下载
    MarkDown&思维导图
  • 原文地址:https://www.cnblogs.com/rongpmcu/p/7662813.html
Copyright © 2011-2022 走看看