Code provided by Spirit532 on IRC:
```
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);
```