Support for DNG file export (for RAW and RGB right now)

test16bit
Stefan Jahn 3 years ago
parent 3182cb51e5
commit 9ee7aa91d8

@ -1,3 +1,6 @@
2022-11-10:
- support for DNG file export
2022-11-09:
- added preliminary SER file implementations, writing seems to work also
with timestamps; reading not yet tested

@ -4,7 +4,7 @@ APP = simpleskycam
-include Makefile.rules
OBJECTS := $(OBJECTS) gui.oo main.oo video.oo videoframe.oo videodev.oo videodev-v4l2.oo convert.oo filter.oo detect.oo json.oo configuration.oo ser.oo
OBJECTS := $(OBJECTS) gui.oo main.oo video.oo videoframe.oo videodev.oo videodev-v4l2.oo convert.oo filter.oo detect.oo json.oo configuration.oo ser.oo dng.oo
DISTNAME=simpleskycam-$(VERSION)

159
dng.cc

@ -0,0 +1,159 @@
/*
DNG file format class based on LibTIFF.
*/
#include <stdint.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);
}
}
/*
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;
}

66
dng.h

@ -0,0 +1,66 @@
#ifndef _DNG_H_
#define _DNG_H_
/*
Example usage of the class:
---------------------------
DNG * dng = new DNG();
dng->setFile((char *)"test.dng");
dng->setWidth(640);
dng->setHeight(480);
dng->setColorID(DNG_COLORID_RGB);
uint8_t * data = (uint8_t *)malloc(dng->getWidth() * dng->getHeight() * 3);
memset(data, 0, dng->getWidth() * dng->getHeight() * 3);
for(int y = 0; y < dng->getHeight()/3; y++) {
for(int x = 0; x < dng->getWidth(); x++) {
data[y*dng->getWidth()*3 + x*3 + 0] = 0xff;
}
}
for(int y = dng->getHeight()/3; y < 2*dng->getHeight()/3; y++) {
for(int x = 0; x < dng->getWidth(); x++) {
data[y*dng->getWidth()*3 + x*3 + 1] = 0xff;
}
}
for(int y = 2*dng->getHeight()/3; y < 3*dng->getHeight()/3; y++) {
for(int x = 0; x < dng->getWidth(); x++) {
data[y*dng->getWidth()*3 + x*3 + 2] = 0xff;
}
}
dng->writeFile(data);
delete dng;
*/
#include <tiffio.h>
enum {
DNG_COLORID_RGB = 100,
DNG_COLORID_RAW16 = 101,
DNG_COLORID_RAW8 = 102
};
class DNG {
private:
TIFF * tif;
int ImageWidth;
int ImageHeight;
int BitsPerSample;
int SamplesPerPixel;
int ColorID;
public:
DNG();
~DNG();
int setWidth(int);
int setHeight(int);
int getWidth(void);
int getHeight(void);
void setColorID(int);
int setFile(char *);
int writeFile(void *);
};
#endif

@ -13,6 +13,7 @@
#include "detect.h"
#include "convert.h"
#include "ser.h"
#include "dng.h"
/**************************************************************************
* global variables

Loading…
Cancel
Save