LIBTIFF DNG export
Open, Needs TriagePublic

Description

Code provided by Spirit532 on IRC:

Output example:

	TIFF *tif;

	static const short bayerPatternDimensions[] = { 2, 2 };

	static const double sRGB[] = { 
		3.6156, -0.8100, -0.0837,
		-0.3094, 1.5500, -0.5439,
		0.0967, -0.4700, 1.9805 }; // sRGB profile

	static const float AsShotNeutral[] =
	{
		1.0, 1.0, 1.0,
	}; // needs this

	unsigned short curve[256];

	static const float cam_xyz[] =
	{ 2.005,-0.771,-0.269, -0.752,1.688,0.064, -0.149,0.283,0.745 }; // xyz
	
	static const float neutral[] = { 0.807133, 1.0, 0.913289 };
		
		
		tif = TIFFOpen("C:\image.dng", "w");

		for (int i = 0; i < 256; i++)
			curve[i] = 0x3fff * pow(i / 255.0, 100 / 80) + 0.5;

		int bpp = 8; // bits per pixel, integer
		TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 1); // preview
		TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (int)uiWidth >> 4);
		TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (int)uiHeight >> 4);
		TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); // should be 8, this is the preview part
		TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
		TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
		TIFFSetField(tif, TIFFTAG_MAKE, "indeed a make");
		TIFFSetField(tif, TIFFTAG_MODEL, "...");
		TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
		TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3); 
		TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
		TIFFSetField(tif, TIFFTAG_SOFTWARE, "Software");
		//TIFFSetField(tif, TIFFTAG_DATETIME, datetime); // not needed, unless embedded FS
		TIFFSetField(tif, TIFFTAG_SUBIFD, 1, &sub_offset);
		TIFFSetField(tif, TIFFTAG_DNGVERSION, "\001\001\0\0");
		TIFFSetField(tif, TIFFTAG_DNGBACKWARDVERSION, "\001\0\0\0");
		TIFFSetField(tif, TIFFTAG_UNIQUECAMERAMODEL, "Camera");
		TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, cam_xyz);
		TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, neutral);
		TIFFSetField(tif, TIFFTAG_CALIBRATIONILLUMINANT1, 21);
		TIFFSetField(tif, TIFFTAG_ORIGINALRAWFILENAME, "image.dng"); // haven't seen any software use the
		{
			unsigned char *buf = (unsigned char *)malloc((int)uiWidth >> 4);
			memset(buf, 0, (int)uiWidth >> 4);
			for (row = 0; row < (int)uiHeight >> 4; row++)
				TIFFWriteScanline(tif, buf, row, 0); // just leave it black, no software uses the built-in preview, builds off real image.
		}
		TIFFWriteDirectory(tif);

		TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 0); // image
		TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (int)uiWidth); // in pixels
		TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (int)uiHeight); // in pixels
		TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bpp); // int
		TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA);
		TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); 
		TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
		TIFFSetField(tif, TIFFTAG_CFAREPEATPATTERNDIM, bayerPatternDimensions);
		TIFFSetField(tif, TIFFTAG_CFAPATTERN, 4, "\001\002\000\001"); // the ", 4," is important, crashes otherwise, didn't investigate
		TIFFSetField(tif, TIFFTAG_LINEARIZATIONTABLE, 256, curve);
		TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &white);

		// bit depth
		if (rPic.m_eDataType == extypeUInt8)
		{
			quint8 *pLine;
			for (uint row = 0; row < uiHeight; row++)
			{
				pLine = ROW_U8(rPic, row);
				TIFFWriteScanline(tif, pLine, row, 0); // this writes a single complete row
			}
		}
		// bit depth
		else if (rPic.m_eDataType == extypeUInt16)
		{
			quint16 *pLine;
			for (uint row = 0; row < uiHeight; row++)
			{
				pLine = ROW_U16(rPic, row);
				TIFFWriteScanline(tif, pLine, row, 0);
			}
		}
		TIFFClose(tif);
BAndiT1983 updated the task description. (Show Details)
BAndiT1983 raised the priority of this task from to Needs Triage.
BAndiT1983 added a project: Open Cine.
BAndiT1983 moved this task to Input/Output on the Open Cine board.
BAndiT1983 added a subscriber: BAndiT1983.
BAndiT1983 renamed this task from LIBTIFF DNG read/write to LIBTIFF DNG export.Mar 3 2017, 7:45 PM
BAndiT1983 updated the task description. (Show Details)