From 9ee7aa91d8e84d24b0c568faea3a5670e102bb66 Mon Sep 17 00:00:00 2001 From: Stefan Jahn Date: Fri, 11 Nov 2022 00:06:21 +0100 Subject: [PATCH] Support for DNG file export (for RAW and RGB right now) --- ChangeLog | 3 ++ Makefile | 2 +- dng.cc | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ dng.h | 66 +++++++++++++++++++++++ main.cc | 1 + 5 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 dng.cc create mode 100644 dng.h diff --git a/ChangeLog b/ChangeLog index c2eed0e..0df678a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/Makefile b/Makefile index cbf7f1c..6c33aa1 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/dng.cc b/dng.cc new file mode 100644 index 0000000..30c9a32 --- /dev/null +++ b/dng.cc @@ -0,0 +1,159 @@ +/* + 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; +} diff --git a/dng.h b/dng.h new file mode 100644 index 0000000..950e0a2 --- /dev/null +++ b/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 + +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 diff --git a/main.cc b/main.cc index a2893d2..e75c0e7 100644 --- a/main.cc +++ b/main.cc @@ -13,6 +13,7 @@ #include "detect.h" #include "convert.h" #include "ser.h" +#include "dng.h" /************************************************************************** * global variables