/* DNG file format class based on LibTIFF. */ #include #include #include #include "dng.h" DNG::DNG() { /* initialize public data */ ImageWidth = 0; ImageHeight = 0; BitsPerSample = 0; SamplesPerPixel = 0; ColorID = 0; /* initialize internal data */ tif = NULL; } DNG::~DNG() { /* close file if necessary */ if(tif) { TIFFClose(tif); } } /* Sets the file name of the DNG file to be written. Returns -1 on failure, 0 on success. */ int DNG::setFile(char * file) { if (!(tif = TIFFOpen(file, "w"))) { return -1; } return 0; } /* Sets the color ID. Only few formats are supported right now. */ void DNG::setColorID(int id) { switch(id) { case DNG_COLORID_RGB: BitsPerSample = 8; SamplesPerPixel = 3; ColorID = id; break; case DNG_COLORID_RAW16: BitsPerSample = 16; SamplesPerPixel = 1; ColorID = id; break; case DNG_COLORID_RAW8: BitsPerSample = 8; SamplesPerPixel = 1; ColorID = id; break; default: fprintf(stderr, "Error: DNG color ID #%d not supported\n", id); break; } } /* Sets the image width. */ int DNG::setWidth(int width) { ImageWidth = width; return 0; } /* Gets the image width. */ int DNG::getWidth(void) { return ImageWidth; } /* Sets the image height. */ int DNG::setHeight(int height) { ImageHeight = height; return 0; } /* Gets the image height. */ int DNG::getHeight(void) { return ImageHeight; } /* Saves given sample data into the DNG file according to the color ID and image size specifications. */ int DNG::writeFile(void * data) { /* create timestamp */ time_t abs_ts; struct tm tm; char timestamp[64]; time (&abs_ts); gmtime_r (&abs_ts, &tm); sprintf(timestamp, "%04d:%02d:%02d %02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); /* set general meta data */ TIFFSetField(tif, TIFFTAG_MAKE, "Svbony"); TIFFSetField(tif, TIFFTAG_MODEL, "Svbony SV305"); TIFFSetField(tif, TIFFTAG_SOFTWARE, "SimpleSkyCam v0.0.1"); TIFFSetField(tif, TIFFTAG_ARTIST, "Steffen Pohle"); TIFFSetField(tif, TIFFTAG_DATETIME, timestamp); TIFFSetField(tif, TIFFTAG_DNGVERSION, "\001\001\0\0"); TIFFSetField(tif, TIFFTAG_DNGBACKWARDVERSION, "\001\0\0\0"); /* set image meta data */ TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 0); // image TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, ImageWidth); // in pixels TIFFSetField(tif, TIFFTAG_IMAGELENGTH, ImageHeight); // in pixels TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, BitsPerSample); // int TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, SamplesPerPixel); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); if(ColorID == DNG_COLORID_RAW8 || ColorID == DNG_COLORID_RAW8) { static const short CFARepeatPattern[] = { 2,2 }; // 2x2 CFA TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA); TIFFSetField(tif, TIFFTAG_CFAREPEATPATTERNDIM, CFARepeatPattern); // 0 = Red, 1 = Green, 2 = Blue TIFFSetField(tif, TIFFTAG_CFAPATTERN, "\001\000\002\001"); // GRGB } else if(ColorID == DNG_COLORID_RGB) { TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); } // go through all lines for(int y = 0; y < ImageHeight; y++) { // calculate offset into source image based on color ID settings int offset = y * (ImageWidth * BitsPerSample/8 * SamplesPerPixel); // write complete scanline TIFFWriteScanline(tif, &((uint8_t *)data)[offset], y, 0); } return 0; }