mirror of
https://github.com/eddyem/SBIG_340.git
synced 2025-12-06 10:45:10 +03:00
Add debayer via libraw
This commit is contained in:
parent
d123815433
commit
ae4b511542
47
Makefile
47
Makefile
@ -1,37 +1,46 @@
|
|||||||
# run `make DEF=...` to add extra defines
|
# run `make DEF=...` to add extra defines
|
||||||
LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all
|
LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all
|
||||||
LDFLAGS += -lm -pthread
|
LDFLAGS += -lm -pthread
|
||||||
|
LDIMG := $(shell pkg-config --libs libraw) -lgd $(shell pkg-config --libs cfitsio) -ltiff
|
||||||
SRCS := $(wildcard *.c)
|
SRCS := $(wildcard *.c)
|
||||||
#GCC_GE_4_9_3 := $(shell g++ -dumpversion | gawk '{print $$1>=4.9.3?"1":"0"}')
|
DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111
|
||||||
DEFINES := $(DEF) -D_XOPEN_SOURCE=1111
|
|
||||||
#ifeq ($(GCC_GE_4_9_3),1)
|
|
||||||
DEFINES += -D_DEFAULT_SOURCE
|
|
||||||
#else
|
|
||||||
# DEFINES += -D_BSD_SOURCE
|
|
||||||
#endif
|
|
||||||
#DEFINES += -DEBUG
|
#DEFINES += -DEBUG
|
||||||
CFLAGS += -Wall -Wextra -O2 -std=gnu99
|
CFLAGS += -Wall -Wextra -O2
|
||||||
CC = gcc
|
CFLAGS += $(shell pkg-config --cflags libraw)
|
||||||
|
OBJS := $(SRCS:%.c=%.o)
|
||||||
|
CC = gcc
|
||||||
|
CPP = g++
|
||||||
|
|
||||||
all : sbig340 daemon client
|
all : sbig340 daemon client
|
||||||
|
|
||||||
sbig340 : $(SRCS)
|
debayer.o : debayer.cpp
|
||||||
@echo -e "\t\tLD sbig340"
|
@echo -e "\t\tG++ debayer"
|
||||||
$(CC) $(CFLAGS) $(DEFINES) $(LDFLAGS) $(shell pkg-config --libs cfitsio) -ltiff $(SRCS) -o sbig340
|
$(CPP) $(CFLAGS) $(DEFINES) debayer.cpp -c
|
||||||
|
|
||||||
|
sbig340 : $(SRCS) debayer.o
|
||||||
|
@echo -e "\t\tBuild sbig340"
|
||||||
|
$(CC) -DDAEMON $(CFLAGS) -std=gnu99 $(DEFINES) $(LDFLAGS) $(LDIMG) $(SRCS) -o $@
|
||||||
|
|
||||||
|
# $(CC) -c $(CFLAGS) -std=gnu99 $(DEFINES) $(SRCS)
|
||||||
|
# $(CPP) $(LDFLAGS) $(OBJS) debayer.o -o $@
|
||||||
|
|
||||||
daemon : $(SRCS)
|
daemon : $(SRCS)
|
||||||
@echo -e "\t\tLD daemon"
|
@echo -e "\t\tBuild daemon"
|
||||||
$(CC) -DDAEMON $(CFLAGS) $(DEFINES) $(LDFLAGS) $(SRCS) -o daemon
|
$(CC) -DDAEMON $(CFLAGS) -std=gnu99 $(DEFINES) $(LDFLAGS) $(SRCS) -o $@
|
||||||
|
|
||||||
client : $(SRCS)
|
client : $(SRCS) debayer.o
|
||||||
@echo -e "\t\tLD client"
|
@echo -e "\t\tBuild client"
|
||||||
$(CC) -DCLIENT $(CFLAGS) $(DEFINES) $(LDFLAGS) $(shell pkg-config --libs cfitsio) -ltiff $(SRCS) -o client
|
$(CC) -DCLIENT $(CFLAGS) -std=gnu99 $(DEFINES) $(LDFLAGS) $(LDIMG) $(SRCS) debayer.o -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo -e "\t\tCLEAN"
|
@echo -e "\t\tCLEAN"
|
||||||
|
@rm -f $(OBJS) debayer.o
|
||||||
|
|
||||||
|
xclean: clean
|
||||||
|
@echo -e "\t\tRM binaries"
|
||||||
@rm -f sbig340 daemon client
|
@rm -f sbig340 daemon client
|
||||||
|
|
||||||
gentags:
|
gentags:
|
||||||
CFLAGS="$(CFLAGS) $(DEFINES)" geany -g $(PROGRAM).c.tags *[hc] 2>/dev/null
|
CFLAGS="$(CFLAGS) $(DEFINES)" geany -g $(PROGRAM).c.tags *[hc] *.cpp 2>/dev/null
|
||||||
|
|
||||||
.PHONY: gentags clean
|
.PHONY: gentags clean xclean
|
||||||
|
|||||||
107
debayer.cpp
Normal file
107
debayer.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* debayer.cpp - debayer image using libraw
|
||||||
|
* based on openbayer_sample.cpp from LibRaw samples
|
||||||
|
*
|
||||||
|
* Copyright 2017 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <libraw/libraw.h>
|
||||||
|
#include <gd.h>
|
||||||
|
|
||||||
|
#include "debayer.h"
|
||||||
|
#include "usefull_macros.h"
|
||||||
|
|
||||||
|
static int write_jpeg(const char *fname, const uint8_t *data, imstorage *img){
|
||||||
|
if(!img) return 1;
|
||||||
|
size_t nx = img->W, ny = img->H;
|
||||||
|
gdImagePtr im = gdImageCreateTrueColor(nx, ny);
|
||||||
|
if(!im) return 4;
|
||||||
|
//for(size_t y = 0; y < ny; ++y)for(size_t x = 0; x < nx; ++x) im->tpixels[y][x] = 0XFF0000;
|
||||||
|
size_t x, y;
|
||||||
|
for(y = 0; y < ny; ++y){
|
||||||
|
for(x = 0; x < nx; ++x){
|
||||||
|
im->tpixels[y][x] = (data[0] << 16) | (data[1] << 8) | data[2] ;
|
||||||
|
data += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FILE *fp = fopen(fname, "w");
|
||||||
|
if(!fp){
|
||||||
|
fprintf(stderr, "Can't save jpg image %s\n", fname);
|
||||||
|
gdImageDestroy(im);
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
char date[256];
|
||||||
|
strftime(date, 256, "%d/%m/%y\n%H:%M:%S", localtime(&img->exposetime));
|
||||||
|
gdFTUseFontConfig(1);
|
||||||
|
char *ret = gdImageStringFT(im, NULL, 0xffffff, "monotype", 10, 0., 2, 12, date);
|
||||||
|
if(ret) fprintf(stderr, "Error: %s\n", ret);
|
||||||
|
im->tpixels[10][10] = 0XFF0000;
|
||||||
|
im->tpixels[15][15] = 0XFF0000;
|
||||||
|
gdImageJpeg(im, fp, 90);
|
||||||
|
fclose(fp);
|
||||||
|
gdImageDestroy(im);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debayer image `img` and store it
|
||||||
|
* @param black - black level (minimum on image)
|
||||||
|
* @return 0 if all OK
|
||||||
|
*/
|
||||||
|
int write_debayer(imstorage *img, uint16_t black){
|
||||||
|
char *name = make_filename(img, SUFFIX_JPEG);
|
||||||
|
if(!name) return 1;
|
||||||
|
int r = 0;
|
||||||
|
size_t fsz = img->W * img->H * sizeof(uint16_t);
|
||||||
|
LibRaw rp;
|
||||||
|
rp.imgdata.params.output_tiff = 1;
|
||||||
|
int ret = rp.open_bayer((unsigned char*)img->imdata, fsz, img->W, img->H,
|
||||||
|
0,0,0,0,0, LIBRAW_OPENBAYER_BGGR, 0,0, black);
|
||||||
|
if(ret != LIBRAW_SUCCESS) return 2;
|
||||||
|
if ((ret = rp.unpack()) != LIBRAW_SUCCESS){
|
||||||
|
WARNX(_("Unpack error: %d"), ret);
|
||||||
|
rp.recycle();
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if((ret = rp.dcraw_process()) != LIBRAW_SUCCESS){
|
||||||
|
WARNX(_("Processing error: %d"), ret);
|
||||||
|
rp.recycle();
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
libraw_processed_image_t *image = rp.dcraw_make_mem_image(&ret);
|
||||||
|
if(!image){
|
||||||
|
WARNX(_("Can't make memory image: %d"), ret);
|
||||||
|
rp.recycle();
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
if(image->type != LIBRAW_IMAGE_BITMAP){
|
||||||
|
r = 6; goto retn;
|
||||||
|
}
|
||||||
|
if(image->colors != 3){
|
||||||
|
r = 7; goto retn;
|
||||||
|
}
|
||||||
|
write_jpeg(name, image->data, img);
|
||||||
|
retn:
|
||||||
|
LibRaw::dcraw_clear_mem(image);
|
||||||
|
rp.recycle();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
38
debayer.h
Normal file
38
debayer.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* debayer.h
|
||||||
|
*
|
||||||
|
* Copyright 2017 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef __DEBAYER_H__
|
||||||
|
#define __DEBAYER_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "imfunctions.h"
|
||||||
|
int write_debayer(imstorage *img, uint16_t black);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // __DEBAYER_H__
|
||||||
@ -28,6 +28,7 @@
|
|||||||
#include <math.h> // sqrt
|
#include <math.h> // sqrt
|
||||||
#include <time.h> // time, gmtime etc
|
#include <time.h> // time, gmtime etc
|
||||||
#ifndef DAEMON
|
#ifndef DAEMON
|
||||||
|
#include "debayer.h"
|
||||||
#include <fitsio.h> // save fits
|
#include <fitsio.h> // save fits
|
||||||
#include <tiffio.h> // save tiff
|
#include <tiffio.h> // save tiff
|
||||||
#endif
|
#endif
|
||||||
@ -51,20 +52,16 @@ void modifytimestamp(char *filename, imstorage *img){
|
|||||||
if(utimensat(AT_FDCWD, filename, times, 0)) WARN(_("Can't change timestamp for %s"), filename);
|
if(utimensat(AT_FDCWD, filename, times, 0)) WARN(_("Can't change timestamp for %s"), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
// image type suffixes
|
|
||||||
#define SUFFIX_FITS "fits"
|
|
||||||
#define SUFFIX_RAW "bin"
|
|
||||||
#define SUFFIX_TIFF "tiff"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NON THREAD-SAFE!
|
* NON THREAD-SAFE!
|
||||||
* make filename for given name, suffix and storage type
|
* make filename for given name, suffix and storage type
|
||||||
* @return filename or NULL if can't create it
|
* @return filename or NULL if can't create it
|
||||||
*/
|
*/
|
||||||
static char *make_filename(imstorage *img, const char *suff){
|
char *make_filename(imstorage *img, const char *suff){
|
||||||
struct stat filestat;
|
struct stat filestat;
|
||||||
static char buff[FILENAME_MAX];
|
static char buff[FILENAME_MAX];
|
||||||
store_type st = img->st;
|
store_type st = img->st;
|
||||||
|
DBG("Make filename from %s with suffix %s", img->imname, suff);
|
||||||
char fnbuf[FILENAME_MAX], *outfile = img->imname;
|
char fnbuf[FILENAME_MAX], *outfile = img->imname;
|
||||||
if(img->timestamp){
|
if(img->timestamp){
|
||||||
struct tm *stm = localtime(&img->exposetime);
|
struct tm *stm = localtime(&img->exposetime);
|
||||||
@ -107,6 +104,7 @@ static char *make_filename(imstorage *img, const char *suff){
|
|||||||
* Check image to store
|
* Check image to store
|
||||||
* @param filename (i) - output file name (or prefix with suffix)
|
* @param filename (i) - output file name (or prefix with suffix)
|
||||||
* @param store (i) - "overwrite" (or "rewrite"), "normal" (or NULL), "enumerate" (or "numerate")
|
* @param store (i) - "overwrite" (or "rewrite"), "normal" (or NULL), "enumerate" (or "numerate")
|
||||||
|
* @param format (i) - image format (ft[rd])
|
||||||
*/
|
*/
|
||||||
imstorage *chk_storeimg(char *filename, char* store, char *format){
|
imstorage *chk_storeimg(char *filename, char* store, char *format){
|
||||||
FNAME();
|
FNAME();
|
||||||
@ -124,6 +122,7 @@ imstorage *chk_storeimg(char *filename, char* store, char *format){
|
|||||||
char *nm = strdup(filename);
|
char *nm = strdup(filename);
|
||||||
if(!nm) ERRX("strdup");
|
if(!nm) ERRX("strdup");
|
||||||
char *pt = strrchr(nm, '.');
|
char *pt = strrchr(nm, '.');
|
||||||
|
DBG("input format: %s", format);
|
||||||
image_format fbysuff = FORMAT_NONE;
|
image_format fbysuff = FORMAT_NONE;
|
||||||
// check if name's suffix is filetype
|
// check if name's suffix is filetype
|
||||||
if(pt){
|
if(pt){
|
||||||
@ -151,7 +150,7 @@ imstorage *chk_storeimg(char *filename, char* store, char *format){
|
|||||||
if(fbysuff != FORMAT_NONE) fmt = fbysuff;
|
if(fbysuff != FORMAT_NONE) fmt = fbysuff;
|
||||||
DBG("fmt: %d", fmt);
|
DBG("fmt: %d", fmt);
|
||||||
}
|
}
|
||||||
|
DBG("imformat: %d", fmt);
|
||||||
// now check all names
|
// now check all names
|
||||||
#define FMTSZ (3)
|
#define FMTSZ (3)
|
||||||
image_format formats[FMTSZ] = {FORMAT_FITS, FORMAT_TIFF, FORMAT_RAW};
|
image_format formats[FMTSZ] = {FORMAT_FITS, FORMAT_TIFF, FORMAT_RAW};
|
||||||
@ -278,6 +277,7 @@ int writefits(imstorage *img){
|
|||||||
char buf[80];
|
char buf[80];
|
||||||
fitsfile *fp;
|
fitsfile *fp;
|
||||||
char *filename = make_filename(img, SUFFIX_FITS);
|
char *filename = make_filename(img, SUFFIX_FITS);
|
||||||
|
if(!filename) return 1;
|
||||||
TRYFITS(fits_create_file, &fp, filename);
|
TRYFITS(fits_create_file, &fp, filename);
|
||||||
TRYFITS(fits_create_img, fp, USHORT_IMG, 2, naxes);
|
TRYFITS(fits_create_img, fp, USHORT_IMG, 2, naxes);
|
||||||
// FILE / Input file original name
|
// FILE / Input file original name
|
||||||
@ -405,9 +405,9 @@ int save_histo(FILE *f, imstorage *img){
|
|||||||
printf("low 2%% (%zd pixels) = %d, median (%zd pixels) = %d, up 2%% (%zd pixels) = %d\n",
|
printf("low 2%% (%zd pixels) = %d, median (%zd pixels) = %d, up 2%% (%zd pixels) = %d\n",
|
||||||
low2, lval, med, mval, up2, tval);
|
low2, lval, med, mval, up2, tval);
|
||||||
double mul = 1., mulmax = 255. / tval;
|
double mul = 1., mulmax = 255. / tval;
|
||||||
if(tval <= 252){ // no overexposed pixels
|
if(tval <= 240){ // no overexposed pixels
|
||||||
if(lval < 32){ // narrow histogram with overexposed black level
|
if(lval < 32){ // narrow histogram with overexposed black level
|
||||||
mul = 252. / tval;
|
mul = 240. / tval;
|
||||||
}else mul = 32. / lval;
|
}else mul = 32. / lval;
|
||||||
}else{
|
}else{
|
||||||
if(mval > 134){
|
if(mval > 134){
|
||||||
@ -418,7 +418,7 @@ int save_histo(FILE *f, imstorage *img){
|
|||||||
if(mul > mulmax) mul = mulmax;
|
if(mul > mulmax) mul = mulmax;
|
||||||
double E = img->exptime * mul;
|
double E = img->exptime * mul;
|
||||||
if(E < 5e-5) E = 5e-5; // too short exposition
|
if(E < 5e-5) E = 5e-5; // too short exposition
|
||||||
else if(E > 120.) E = 120.; // no need to do expositions larger than 2 minutes
|
else if(E > 300.) E = 300.; // no need to do expositions larger than 5 minutes
|
||||||
green("Recommended exposition time: %g seconds\n", E);
|
green("Recommended exposition time: %g seconds\n", E);
|
||||||
exp_calculated = E;
|
exp_calculated = E;
|
||||||
return 0;
|
return 0;
|
||||||
@ -477,12 +477,13 @@ int store_image(imstorage *img){
|
|||||||
if(img->imformat & FORMAT_TIFF){ // save tiff file
|
if(img->imformat & FORMAT_TIFF){ // save tiff file
|
||||||
if(writetiff(img)) status |= 1;
|
if(writetiff(img)) status |= 1;
|
||||||
}
|
}
|
||||||
if(img->imformat & FORMAT_RAW){
|
if(img->imformat & FORMAT_RAW){ // save RAW dump & truncated histogram
|
||||||
if(writedump(img)) status |= 2;
|
if(writedump(img)) status |= 2;
|
||||||
}
|
}
|
||||||
if(img->imformat & FORMAT_FITS){ // not supported yet
|
if(img->imformat & FORMAT_FITS){ // save FITS
|
||||||
if(writefits(img)) status |= 4;
|
if(writefits(img)) status |= 4;
|
||||||
}
|
}
|
||||||
|
if(write_debayer(img, glob_min)) status |= 8; // and save colour image
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -72,6 +72,13 @@ typedef struct{
|
|||||||
|
|
||||||
extern double exp_calculated;
|
extern double exp_calculated;
|
||||||
|
|
||||||
|
// image type suffixes
|
||||||
|
#define SUFFIX_FITS "fits.gz"
|
||||||
|
#define SUFFIX_RAW "bin"
|
||||||
|
#define SUFFIX_TIFF "tiff"
|
||||||
|
#define SUFFIX_JPEG "jpg"
|
||||||
|
|
||||||
|
char *make_filename(imstorage *img, const char *suff);
|
||||||
imstorage *chk_storeimg(char *filename, char* store, char *format);
|
imstorage *chk_storeimg(char *filename, char* store, char *format);
|
||||||
int store_image(imstorage *filename);
|
int store_image(imstorage *filename);
|
||||||
void print_stat(imstorage *img);
|
void print_stat(imstorage *img);
|
||||||
|
|||||||
1
main.c
1
main.c
@ -80,6 +80,7 @@ int main(int argc, char **argv){
|
|||||||
#endif // !CLIENT
|
#endif // !CLIENT
|
||||||
#ifndef DAEMON
|
#ifndef DAEMON
|
||||||
img = chk_storeimg(G->outpfname, G->imstoretype, G->imformat);
|
img = chk_storeimg(G->outpfname, G->imstoretype, G->imformat);
|
||||||
|
if(!img) return 1;
|
||||||
#else
|
#else
|
||||||
img = MALLOC(imstorage, 1); // just allocate empty: all we need in daemon is exposition & binning
|
img = MALLOC(imstorage, 1); // just allocate empty: all we need in daemon is exposition & binning
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -333,7 +333,7 @@ size_t read_tty(uint8_t *buff, size_t length){
|
|||||||
int retval;
|
int retval;
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
FD_SET(comfd, &rfds);
|
FD_SET(comfd, &rfds);
|
||||||
tv.tv_sec = 0; tv.tv_usec = 500000; // wait for 500ms max
|
tv.tv_sec = 0; tv.tv_usec = 500000; // wait for 500ms
|
||||||
retval = select(comfd + 1, &rfds, NULL, NULL, &tv);
|
retval = select(comfd + 1, &rfds, NULL, NULL, &tv);
|
||||||
if (!retval) return 0;
|
if (!retval) return 0;
|
||||||
if(FD_ISSET(comfd, &rfds)){
|
if(FD_ISSET(comfd, &rfds)){
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user