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.
178 lines
4.1 KiB
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;
|
|
}
|