You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
SimpleSkyCam/dng.cc

178 lines
4.1 KiB

/*
DNG file format class based on LibTIFF.
*/
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <tiffio.h>
#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);
}
}
/*
Run-time detection if we are little- or big-endian.
*/
int DNG::IsBigEndian(void) {
int i = 1;
return ! *((char *)&i);
}
/*
Sets the file name of the DNG file to be written. Returns -1 on
failure, 0 on success.
*/
int DNG::setFile(char * file) {
/*
w = write
l = little endian
b = big endian
-> if neither l or b is given, data is written in native CPU format
*/
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];
/* get time stamp */
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_RAW16) {
static const short CFARepeatPattern[] = { 2,2 }; // 2x2 CFA
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA);
TIFFSetField(tif, TIFFTAG_CFAREPEATPATTERNDIM, CFARepeatPattern);
TIFFSetField(tif, TIFFTAG_CFALAYOUT, 1);
TIFFSetField(tif, TIFFTAG_CFAPLANECOLOR, 3, "\000\001\002"); // RGB
// 0 = Red, 1 = Green, 2 = Blue
TIFFSetField(tif, TIFFTAG_CFAPATTERN, "\001\000\002\001"); // GRBG
}
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;
}