Now RGB based instead of HSV based, this also includes a new RGBA compositing function which cleans up the code responsible false color significantly. Color palettes have also been moved into 1 file instead of 2tags/v1.8.0
@@ -1,4 +1,4 @@ | |||||
CC = gcc | |||||
CC = clang | |||||
BIN = /usr/bin | BIN = /usr/bin | ||||
INCLUDES = -I. | INCLUDES = -I. | ||||
CFLAGS = -O3 -Wall $(INCLUDES) | CFLAGS = -O3 -Wall $(INCLUDES) | ||||
@@ -7,7 +7,7 @@ OBJS = main.o image.o dsp.o filter.o reg.o fcolor.o | |||||
aptdec: $(OBJS) | aptdec: $(OBJS) | ||||
$(CC) -o $@ $(OBJS) -lm -lsndfile -lpng | $(CC) -o $@ $(OBJS) -lm -lsndfile -lpng | ||||
main.o: main.c temppalette.h gvipalette.h offsets.h messages.h | |||||
main.o: main.c colorpalette.h offsets.h messages.h | |||||
dsp.o: dsp.c filtercoeff.h filter.h | dsp.o: dsp.c filtercoeff.h filter.h | ||||
filter.o: filter.c filter.h | filter.o: filter.c filter.h | ||||
image.o: image.c satcal.h offsets.h messages.h | image.o: image.c satcal.h offsets.h messages.h | ||||
@@ -54,7 +54,7 @@ To uninstall | |||||
-i [r|a|b|c|t|l] | -i [r|a|b|c|t|l] | ||||
Output image type | Output image type | ||||
Raw (r), Channel A (a), Channel B (b), False Color (c), Temperature (t), Layered (l) | Raw (r), Channel A (a), Channel B (b), False Color (c), Temperature (t), Layered (l) | ||||
Default: ab | |||||
Default: "ab" | |||||
-d <dir> | -d <dir> | ||||
Images destination directory (optional). | Images destination directory (optional). | ||||
@@ -62,17 +62,17 @@ Default: Current directory | |||||
-s [15|16|17|18|19] | -s [15|16|17|18|19] | ||||
Satellite number | Satellite number | ||||
For temperature and false color generation | |||||
Default: 19 | |||||
For temperature calibration | |||||
Default: "19" | |||||
-e [c|t] | -e [c|t] | ||||
Enhancements | Enhancements | ||||
Contrast (c) or Crop Telemetry (t) | Contrast (c) or Crop Telemetry (t) | ||||
Defaults: ct | |||||
Defaults: "ct" | |||||
-c <file> | -c <file> | ||||
Use configuration file for false color generation. | Use configuration file for false color generation. | ||||
Default: Internal parameters | |||||
Default: Internal defaults | |||||
``` | ``` | ||||
## Output | ## Output | ||||
@@ -1,3 +1,34 @@ | |||||
unsigned char GviPalette[256*3] = { | |||||
"\230t\17\233x\22\236{\27\241\200\33\244\203\37\247\210#\252\214'\255\220" | |||||
",\260\2240\264\2305\267\2358\272\240=\274\245A\300\251E\303\255I\306\262" | |||||
"M\311\266Q\314\272V\317\276Z\322\302^\325\306b\330\312g\334\317k\337\323" | |||||
"o\342\330s\344\333w\350\337{\352\344\200\356\350\203\361\354\207\364\360" | |||||
"\213\367\364\220\372\370\224\376\376\230\376\375\230\376\372\227\376\366" | |||||
"\224\376\362\222\376\357\220\376\352\216\376\347\213\376\343\211\376\340" | |||||
"\207\376\334\205\376\330\202\376\325\200\376\321\177\376\315|\376\312z\376" | |||||
"\306y\376\302v\376\277t\376\273q\376\267o\376\263m\376\260k\376\254h\376" | |||||
"\250f\376\245d\376\241b\376\235_\376\232^\376\226[\376\223Y\376\217W\376" | |||||
"\213U\376\207R\376\203Q\376\200N\376}L\376zJ\376vG\376rE\376nB\376k@\376" | |||||
"g>\376d<\376`:\376\\7\376X6\376T3\376Q0\376M/\376J-\376F*\376C(\376>%\376" | |||||
";$\3767!\3763\37\3760\35\376,\32\376(\31\376$\26\376!\24\376\35\22\376\32" | |||||
"\20\376\26\15\376\22\13\376\16\11\376\12\6\376\7\4\376\0\0\373\2\0\366\3" | |||||
"\0\362\5\0\355\7\0\350\11\0\343\13\0\336\15\0\332\17\0\325\21\0\320\22\0" | |||||
"\313\24\0\307\26\0\303\27\0\275\32\0\270\33\0\264\35\0\257\37\0\253!\0\246" | |||||
"#\0\241%\0\234&\0\227)\0\223+\0\216,\0\212.\0\2050\0\2002\0}4\0w6\0s7\0n" | |||||
"9\0i;\0e>\0`?\0[A\0VC\0QE\0MG\0HH\0CK\0?M\0:N\0""5P\0""0R\0,S\0'V\0\"X\0" | |||||
"\36Z\0\31\\\0\23^\0\17_\0\12a\0\3b\0\6e\2\12i\5\17n\11\23r\14\30v\17\34{" | |||||
"\23\40\200\26$\203\31)\207\35.\215\40""1\221$6\225':\232*?\236.C\2431G\250" | |||||
"4K\2548O\260;U\265>Y\272A\\\276Eb\303Ie\307Lj\313On\320Ss\324Vw\331Y{\336" | |||||
"]\200\342`\203\347d\207\353g\213\357j\217\364n\223\371q\230\376t\222\375" | |||||
"{\207\374\205}\373\216r\371\230g\371\241\\\370\254Q\367\265F\365\300;\364" | |||||
"\3110\363\323%\362\334\32\361\347\17\357\361\3\356\371\4\353\370\3\347\365" | |||||
"\4\342\361\4\335\357\4\331\354\4\323\351\3\317\346\3\313\343\4\306\340\3" | |||||
"\301\335\3\275\332\3\270\327\3\263\324\2\257\322\3\252\316\3\245\314\3\241" | |||||
"\311\2\234\306\2\230\303\2\223\300\3\216\275\3\211\273\2\205\267\2\200\265" | |||||
"\2|\262\2w\257\2s\254\2n\251\2j\246\2e\243\2`\240\2[\235\2W\232\1S\230\2" | |||||
"M\225\1I\221\2E\217\1@\214\1;\211\1""7\206\1""1\203\1-\200\0(~\1${\0\37y" | |||||
"\0\33u\0\25r\0\21p\0\14l\0\7j\0\3" | |||||
}; | |||||
unsigned char TempPalette[256*3] = { | unsigned char TempPalette[256*3] = { | ||||
"\376\376\376\376\376\376\375\375\376\374\375\376\374\375\375\374\373\375" | "\376\376\376\376\376\376\375\375\376\374\375\376\374\375\375\374\373\375" | ||||
"\373\373\375\372\373\375\372\373\374\372\372\374\371\372\374\371\371\375" | "\373\373\375\372\373\375\372\373\374\372\372\374\371\372\374\371\371\375" | ||||
@@ -38,5 +69,5 @@ unsigned char TempPalette[256*3] = { | |||||
"\370J\352\370I\360\370G\367\371F\370\362E\371\354C\370\345A\371\336@\371" | "\370J\352\370I\360\370G\367\371F\370\362E\371\354C\370\345A\371\336@\371" | ||||
"\326?\372\316=\372\307;\372\277:\372\2679\373\2577\373\2475\373\2373\373" | "\326?\372\316=\372\307;\372\277:\372\2679\373\2577\373\2475\373\2373\373" | ||||
"\2261\373\2161\373\206.\373}-\374u,\375k*\374b(\375Y'\375O%\375E#\375;\"" | "\2261\373\2161\373\206.\373}-\374u,\375k*\374b(\375Y'\375O%\375E#\375;\"" | ||||
"\3762\40\376(\37\376\35\35", | |||||
}; | |||||
"\3762\40\376(\37\376\35" | |||||
}; |
@@ -1,9 +1,10 @@ | |||||
30.0 | |||||
90.0 | |||||
100.0 | |||||
230 0.2 0.3 | |||||
230 0.0 1.0 | |||||
200.0 0.7 0.6 | |||||
240.0 0.6 0.4 | |||||
60.0 0.6 0.2 | |||||
100.0 0.1 0.5 | |||||
28 44 95 | |||||
23 78 37 | |||||
240 250 255 | |||||
50 | |||||
0.5 | |||||
24 | |||||
34 | |||||
14 | |||||
141 | |||||
114 |
@@ -3,133 +3,89 @@ | |||||
#include "offsets.h" | #include "offsets.h" | ||||
typedef struct { | typedef struct { | ||||
float h, s, v; | |||||
} hsvpix_t; | |||||
static void HSVtoRGB(float *r, float *g, float *b, hsvpix_t pix) { | |||||
int i; | |||||
double f, p, q, t, h; | |||||
if (pix.s == 0) { | |||||
// achromatic (grey) | |||||
*r = *g = *b = pix.v; | |||||
return; | |||||
} | |||||
h = pix.h / 60; // sector 0 to 5 | |||||
i = floor(h); | |||||
f = h - i; // factorial part of h | |||||
p = pix.v * (1 - pix.s); | |||||
q = pix.v * (1 - pix.s * f); | |||||
t = pix.v * (1 - pix.s * (1 - f)); | |||||
switch (i) { | |||||
case 0: | |||||
*r = pix.v; | |||||
*g = t; | |||||
*b = p; | |||||
break; | |||||
case 1: | |||||
*r = q; | |||||
*g = pix.v; | |||||
*b = p; | |||||
break; | |||||
case 2: | |||||
*r = p; | |||||
*g = pix.v; | |||||
*b = t; | |||||
break; | |||||
case 3: | |||||
*r = p; | |||||
*g = q; | |||||
*b = pix.v; | |||||
break; | |||||
case 4: | |||||
*r = t; | |||||
*g = p; | |||||
*b = pix.v; | |||||
break; | |||||
default: // case 5: | |||||
*r = pix.v; | |||||
*g = p; | |||||
*b = q; | |||||
break; | |||||
} | |||||
} | |||||
float r, g, b, a; | |||||
} rgba; | |||||
static struct { | static struct { | ||||
float Seathreshold; | |||||
float Landthreshold; | |||||
float Threshold; | |||||
hsvpix_t CloudTop; | |||||
hsvpix_t CloudBot; | |||||
hsvpix_t SeaTop; | |||||
hsvpix_t SeaBot; | |||||
hsvpix_t GroundTop; | |||||
hsvpix_t GroundBot; | |||||
rgba Sea; | |||||
rgba Land; | |||||
rgba Cloud; | |||||
int Seaintensity; | |||||
float Seaoffset; | |||||
int Landthreshold; | |||||
int Landintensity; | |||||
int Landoffset; | |||||
int Cloudthreshold; | |||||
int Cloudintensity; | |||||
} fcinfo = { | } fcinfo = { | ||||
30.0, 90.0, 155.0, { | |||||
230, 0.2, 0.3}, { | |||||
230, 0.0, 1.0}, { | |||||
200.0, 0.7, 0.6}, { | |||||
240.0, 0.6, 0.4}, { | |||||
60.0, 0.6, 0.2}, { | |||||
100.0, 0.0, 0.5} | |||||
{28, 44, 95, 1}, | |||||
{23, 78, 37, 1}, | |||||
{240, 250, 255, 1}, | |||||
50, | |||||
0.5, | |||||
24, | |||||
34, | |||||
14, | |||||
141, | |||||
114 | |||||
}; | }; | ||||
void readfconf(char *file) { | |||||
// Read the config file | |||||
void readfcconf(char *file) { | |||||
FILE *fin; | FILE *fin; | ||||
fin = fopen(file, "r"); | fin = fopen(file, "r"); | ||||
if (fin == NULL) | if (fin == NULL) | ||||
return; | return; | ||||
fscanf(fin, "%g\n", &fcinfo.Seathreshold); | |||||
fscanf(fin, "%g\n", &fcinfo.Landthreshold); | |||||
fscanf(fin, "%g\n", &fcinfo.Threshold); | |||||
fscanf(fin, "%g %g %g\n", &fcinfo.CloudTop.h, &fcinfo.CloudTop.s, &fcinfo.CloudTop.v); | |||||
fscanf(fin, "%g %g %g\n", &fcinfo.CloudBot.h, &fcinfo.CloudBot.s, &fcinfo.CloudBot.v); | |||||
fscanf(fin, "%g %g %g\n", &fcinfo.SeaTop.h, &fcinfo.SeaTop.s, &fcinfo.SeaTop.v); | |||||
fscanf(fin, "%g %g %g\n", &fcinfo.SeaBot.h, &fcinfo.SeaBot.s, &fcinfo.SeaBot.v); | |||||
fscanf(fin, "%g %g %g\n", &fcinfo.GroundTop.h, &fcinfo.GroundTop.s, &fcinfo.GroundTop.v); | |||||
fscanf(fin, "%g %g %g\n", &fcinfo.GroundBot.h, &fcinfo.GroundBot.s, &fcinfo.GroundBot.v); | |||||
fscanf(fin, "%g %g %g\n", &fcinfo.Sea.r, &fcinfo.Sea.g, &fcinfo.Sea.b); | |||||
fscanf(fin, "%g %g %g\n", &fcinfo.Land.r, &fcinfo.Land.g, &fcinfo.Land.b); | |||||
fscanf(fin, "%g %g %g\n", &fcinfo.Cloud.r, &fcinfo.Cloud.g, &fcinfo.Cloud.b); | |||||
fscanf(fin, "%d\n", &fcinfo.Seaintensity); | |||||
fscanf(fin, "%g\n", &fcinfo.Seaoffset); | |||||
fscanf(fin, "%d\n", &fcinfo.Landthreshold); | |||||
fscanf(fin, "%d\n", &fcinfo.Landintensity); | |||||
fscanf(fin, "%d\n", &fcinfo.Landoffset); | |||||
fscanf(fin, "%d\n", &fcinfo.Cloudthreshold); | |||||
fscanf(fin, "%d", &fcinfo.Cloudintensity); | |||||
fclose(fin); | fclose(fin); | ||||
}; | }; | ||||
void falsecolor(double v, double t, float *r, float *g, float *b) { | |||||
hsvpix_t top, bot, c; | |||||
double scv, sct; | |||||
if (t > fcinfo.Threshold) { | |||||
if (v < fcinfo.Seathreshold) { | |||||
// Sea | |||||
top = fcinfo.SeaTop, bot = fcinfo.SeaBot; | |||||
scv = v / fcinfo.Seathreshold; | |||||
sct = (256.0 - t) / (256.0 - fcinfo.Threshold); | |||||
} else { | |||||
// Ground | |||||
top = fcinfo.GroundTop, bot = fcinfo.GroundBot; | |||||
scv = (v - fcinfo.Seathreshold) / (fcinfo.Landthreshold - fcinfo.Seathreshold); | |||||
sct = (256.0 - t) / (256.0 - fcinfo.Threshold); | |||||
} | |||||
} else { | |||||
// Clouds | |||||
top = fcinfo.CloudTop, bot = fcinfo.CloudBot; | |||||
scv = v / 256.0; | |||||
sct = (256.0 - t) / 256.0; | |||||
} | |||||
// RGBA Composite | |||||
rgba composite(rgba top, rgba bottom){ | |||||
rgba composite; | |||||
composite.r = MCOMPOSITE(top.r, top.a, bottom.r, bottom.a); | |||||
composite.g = MCOMPOSITE(top.g, top.a, bottom.g, bottom.a); | |||||
composite.b = MCOMPOSITE(top.b, top.a, bottom.b, bottom.a); | |||||
composite.a = bottom.a == 1 || top.a == 1 ? 1 : (top.a+bottom.a)/2; | |||||
return composite; | |||||
} | |||||
c.s = top.s + sct * (bot.s - top.s); | |||||
c.v = top.v + scv * (bot.v - top.v); | |||||
c.h = top.h + scv * sct * (bot.h - top.h); | |||||
void falsecolor(float vis, float temp, float *r, float *g, float *b){ | |||||
rgba buffer; | |||||
fcinfo.Land.a = 0; fcinfo.Sea.a = 0; | |||||
HSVtoRGB(r, g, b, c); | |||||
}; | |||||
// Calculate intensity of sea and land | |||||
fcinfo.Sea.a = CLIP(vis, 0, 20)/fcinfo.Seaintensity + fcinfo.Seaoffset; | |||||
if(vis > fcinfo.Landthreshold) fcinfo.Land.a = CLIP(vis-fcinfo.Landoffset, 0, fcinfo.Landintensity)/fcinfo.Landintensity; | |||||
// Composite land on top of sea | |||||
buffer = composite(fcinfo.Land, fcinfo.Sea); | |||||
buffer.a = 1; | |||||
// Composite clouds on top | |||||
fcinfo.Cloud.a = CLIP(temp-fcinfo.Cloudthreshold, 0, fcinfo.Cloudintensity)/fcinfo.Cloudintensity; | |||||
buffer = composite(fcinfo.Cloud, buffer); | |||||
*r = buffer.r; | |||||
*g = buffer.g; | |||||
*b = buffer.b; | |||||
} | |||||
// GVI (global vegetation index) false color | |||||
void Ngvi(float **prow, int nrow) { | void Ngvi(float **prow, int nrow) { | ||||
printf("GVI... "); | |||||
printf("Computing GVI false color\n"); | |||||
fflush(stdout); | fflush(stdout); | ||||
for (int n = 0; n < nrow; n++) { | for (int n = 0; n < nrow; n++) { | ||||
@@ -148,6 +104,4 @@ void Ngvi(float **prow, int nrow) { | |||||
pixelv[i + CHB_OFFSET] = pv; | pixelv[i + CHB_OFFSET] = pv; | ||||
} | } | ||||
} | } | ||||
printf("Done\n"); | |||||
}; | |||||
}; |
@@ -1,31 +0,0 @@ | |||||
unsigned char GviPalette[256*3] = { | |||||
"\230t\17\233x\22\236{\27\241\200\33\244\203\37\247\210#\252\214'\255\220" | |||||
",\260\2240\264\2305\267\2358\272\240=\274\245A\300\251E\303\255I\306\262" | |||||
"M\311\266Q\314\272V\317\276Z\322\302^\325\306b\330\312g\334\317k\337\323" | |||||
"o\342\330s\344\333w\350\337{\352\344\200\356\350\203\361\354\207\364\360" | |||||
"\213\367\364\220\372\370\224\376\376\230\376\375\230\376\372\227\376\366" | |||||
"\224\376\362\222\376\357\220\376\352\216\376\347\213\376\343\211\376\340" | |||||
"\207\376\334\205\376\330\202\376\325\200\376\321\177\376\315|\376\312z\376" | |||||
"\306y\376\302v\376\277t\376\273q\376\267o\376\263m\376\260k\376\254h\376" | |||||
"\250f\376\245d\376\241b\376\235_\376\232^\376\226[\376\223Y\376\217W\376" | |||||
"\213U\376\207R\376\203Q\376\200N\376}L\376zJ\376vG\376rE\376nB\376k@\376" | |||||
"g>\376d<\376`:\376\\7\376X6\376T3\376Q0\376M/\376J-\376F*\376C(\376>%\376" | |||||
";$\3767!\3763\37\3760\35\376,\32\376(\31\376$\26\376!\24\376\35\22\376\32" | |||||
"\20\376\26\15\376\22\13\376\16\11\376\12\6\376\7\4\376\0\0\373\2\0\366\3" | |||||
"\0\362\5\0\355\7\0\350\11\0\343\13\0\336\15\0\332\17\0\325\21\0\320\22\0" | |||||
"\313\24\0\307\26\0\303\27\0\275\32\0\270\33\0\264\35\0\257\37\0\253!\0\246" | |||||
"#\0\241%\0\234&\0\227)\0\223+\0\216,\0\212.\0\2050\0\2002\0}4\0w6\0s7\0n" | |||||
"9\0i;\0e>\0`?\0[A\0VC\0QE\0MG\0HH\0CK\0?M\0:N\0""5P\0""0R\0,S\0'V\0\"X\0" | |||||
"\36Z\0\31\\\0\23^\0\17_\0\12a\0\3b\0\6e\2\12i\5\17n\11\23r\14\30v\17\34{" | |||||
"\23\40\200\26$\203\31)\207\35.\215\40""1\221$6\225':\232*?\236.C\2431G\250" | |||||
"4K\2548O\260;U\265>Y\272A\\\276Eb\303Ie\307Lj\313On\320Ss\324Vw\331Y{\336" | |||||
"]\200\342`\203\347d\207\353g\213\357j\217\364n\223\371q\230\376t\222\375" | |||||
"{\207\374\205}\373\216r\371\230g\371\241\\\370\254Q\367\265F\365\300;\364" | |||||
"\3110\363\323%\362\334\32\361\347\17\357\361\3\356\371\4\353\370\3\347\365" | |||||
"\4\342\361\4\335\357\4\331\354\4\323\351\3\317\346\3\313\343\4\306\340\3" | |||||
"\301\335\3\275\332\3\270\327\3\263\324\2\257\322\3\252\316\3\245\314\3\241" | |||||
"\311\2\234\306\2\230\303\2\223\300\3\216\275\3\211\273\2\205\267\2\200\265" | |||||
"\2|\262\2w\257\2s\254\2n\251\2j\246\2e\243\2`\240\2[\235\2W\232\1S\230\2" | |||||
"M\225\1I\221\2E\217\1@\214\1;\211\1""7\206\1""1\203\1-\200\0(~\1${\0\37y" | |||||
"\0\33u\0\25r\0\21p\0\14l\0\7j\0\3g" | |||||
}; |
@@ -27,14 +27,15 @@ | |||||
#include <libgen.h> | #include <libgen.h> | ||||
#include <math.h> | |||||
#include <sndfile.h> | #include <sndfile.h> | ||||
#include <png.h> | #include <png.h> | ||||
#include "messages.h" | #include "messages.h" | ||||
#include "offsets.h" | #include "offsets.h" | ||||
#include "temppalette.h" | |||||
#include "gvipalette.h" | |||||
#include "colorpalette.h" | |||||
extern int getpixelrow(float *pixelv); | extern int getpixelrow(float *pixelv); | ||||
extern int init_dsp(double F);; | extern int init_dsp(double F);; | ||||
@@ -74,7 +75,7 @@ static int initsnd(char *filename) { | |||||
// Get a sample from the wave file | // Get a sample from the wave file | ||||
int getsample(float *sample, int nb) { | int getsample(float *sample, int nb) { | ||||
return(sf_read_float(inwav, sample, nb)); | |||||
return sf_read_float(inwav, sample, nb); | |||||
} | } | ||||
static png_text text_ptr[] = { | static png_text text_ptr[] = { | ||||
@@ -95,7 +96,7 @@ static int ImageOut(char *filename, char *chid, float **prow, int nrow, int widt | |||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | ||||
if (!png_ptr) { | if (!png_ptr) { | ||||
fprintf(stderr, ERR_PNG_WRITE); | fprintf(stderr, ERR_PNG_WRITE); | ||||
return(1); | |||||
return(0); | |||||
} | } | ||||
// Metadata | // Metadata | ||||
@@ -103,7 +104,7 @@ static int ImageOut(char *filename, char *chid, float **prow, int nrow, int widt | |||||
if (!info_ptr) { | if (!info_ptr) { | ||||
png_destroy_write_struct(&png_ptr, (png_infopp) NULL); | png_destroy_write_struct(&png_ptr, (png_infopp) NULL); | ||||
fprintf(stderr, ERR_PNG_INFO); | fprintf(stderr, ERR_PNG_INFO); | ||||
return(1); | |||||
return(0); | |||||
} | } | ||||
if(palette == NULL) { | if(palette == NULL) { | ||||
@@ -156,9 +157,9 @@ static int ImageOut(char *filename, char *chid, float **prow, int nrow, int widt | |||||
} | } | ||||
if(layered){ | if(layered){ | ||||
// Layered image, basically overlay highlights in channel B over channel A | |||||
float cloud = CLIP(pixelv[i+CHB_OFFSET]-141, 0, 255)/114*255; | |||||
pixel[i] = CLIP(pixelv[i+CHA_OFFSET] + cloud, 0, 255); | |||||
// Layered image, overlay highlights in channel B over channel A | |||||
float cloud = CLIP(pixelv[i+CHB_OFFSET]-141, 0, 255)/114; | |||||
pixel[i] = MCOMPOSITE(255, cloud, pixelv[i+CHA_OFFSET], 1); | |||||
}else{ | }else{ | ||||
pixel[i] = pixelv[i + offset + f]; | pixel[i] = pixelv[i + offset + f]; | ||||
} | } | ||||
@@ -170,7 +171,7 @@ static int ImageOut(char *filename, char *chid, float **prow, int nrow, int widt | |||||
fclose(pngfile); | fclose(pngfile); | ||||
printf("\nDone\n"); | printf("\nDone\n"); | ||||
png_destroy_write_struct(&png_ptr, &info_ptr); | png_destroy_write_struct(&png_ptr, &info_ptr); | ||||
return(0); | |||||
return(1); | |||||
} | } | ||||
static int ImageRGBOut(char *filename, float **prow, int nrow) { | static int ImageRGBOut(char *filename, float **prow, int nrow) { | ||||
@@ -178,7 +179,7 @@ static int ImageRGBOut(char *filename, float **prow, int nrow) { | |||||
png_infop info_ptr; | png_infop info_ptr; | ||||
png_structp png_ptr; | png_structp png_ptr; | ||||
extern void falsecolor(double v, double t, float *r, float *g, float *b); | |||||
extern void falsecolor(float vis, float temp, float *r, float *g, float *b); | |||||
// Initalise the PNG writer | // Initalise the PNG writer | ||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | ||||
@@ -204,7 +205,7 @@ static int ImageRGBOut(char *filename, float **prow, int nrow) { | |||||
text_ptr[1].text_length = strlen(text_ptr[1].text); | text_ptr[1].text_length = strlen(text_ptr[1].text); | ||||
png_set_text(png_ptr, info_ptr, text_ptr, 3); | png_set_text(png_ptr, info_ptr, text_ptr, 3); | ||||
printf("Computing false color & writing: %s... ", filename); | |||||
printf("Computing false color & writing: %s", filename); | |||||
fflush(stdout); | fflush(stdout); | ||||
pngfile = fopen(filename, "wb"); | pngfile = fopen(filename, "wb"); | ||||
if (pngfile == NULL) { | if (pngfile == NULL) { | ||||
@@ -221,23 +222,20 @@ static int ImageRGBOut(char *filename, float **prow, int nrow) { | |||||
pixelc = prow[n]; | pixelc = prow[n]; | ||||
for (int i = 0; i < CH_WIDTH - 1; i++) { | for (int i = 0; i < CH_WIDTH - 1; i++) { | ||||
float v, t; | |||||
float r, g, b; | |||||
v = pixelc[i+CHA_OFFSET]; | |||||
t = pixelc[i+CHB_OFFSET]; | |||||
float r = 0, g = 0, b = 0; | |||||
falsecolor(v, t, &r, &g, &b); | |||||
// False color computation | |||||
falsecolor(pixelc[i+CHA_OFFSET], pixelc[i+CHB_OFFSET], &r, &g, &b); | |||||
pix[i].red = 255.0 * r; | |||||
pix[i].green = 255.0 * g; | |||||
pix[i].blue = 255.0 * b; | |||||
pix[i].red = r; | |||||
pix[i].green = g; | |||||
pix[i].blue = b; | |||||
} | } | ||||
png_write_row(png_ptr, (png_bytep) pix); | png_write_row(png_ptr, (png_bytep) pix); | ||||
} | } | ||||
png_write_end(png_ptr, info_ptr); | png_write_end(png_ptr, info_ptr); | ||||
fclose(pngfile); | fclose(pngfile); | ||||
printf("Done\n"); | |||||
printf("\nDone\n"); | |||||
png_destroy_write_struct(&png_ptr, &info_ptr); | png_destroy_write_struct(&png_ptr, &info_ptr); | ||||
return(0); | return(0); | ||||
} | } | ||||
@@ -281,7 +279,7 @@ static void Distrib(char *filename, float **prow, int nrow) { | |||||
extern int calibrate(float **prow, int nrow, int offset, int contrastBoost); | extern int calibrate(float **prow, int nrow, int offset, int contrastBoost); | ||||
extern void Temperature(float **prow, int nrow, int ch, int offset); | extern void Temperature(float **prow, int nrow, int ch, int offset); | ||||
extern int Ngvi(float **prow, int nrow); | extern int Ngvi(float **prow, int nrow); | ||||
extern void readfconf(char *file); | |||||
extern void readfcconf(char *file); | |||||
extern int optind; | extern int optind; | ||||
extern char *optarg; | extern char *optarg; | ||||
@@ -343,7 +341,7 @@ int main(int argc, char **argv) { | |||||
break; | break; | ||||
// False color config file | // False color config file | ||||
case 'c': | case 'c': | ||||
readfconf(optarg); | |||||
readfcconf(optarg); | |||||
break; | break; | ||||
// Output image type | // Output image type | ||||
case 'i': | case 'i': | ||||
@@ -366,7 +364,6 @@ int main(int argc, char **argv) { | |||||
usage(); | usage(); | ||||
} | } | ||||
} | } | ||||
if(optind == argc){ | if(optind == argc){ | ||||
printf("No audio files provided.\n"); | printf("No audio files provided.\n"); | ||||
usage(); | usage(); | ||||
@@ -419,7 +416,7 @@ int main(int argc, char **argv) { | |||||
sf_close(inwav); | sf_close(inwav); | ||||
// Layered images require contrast enhancements | // Layered images require contrast enhancements | ||||
int contrastBoost = CONTAINS(enchancements, 'c') || CONTAINS(imgopt, 'l'); | |||||
int contrastBoost = CONTAINS(enchancements, 'c') || CONTAINS(imgopt, 'l') || CONTAINS(imgopt, 'c'); | |||||
chA = calibrate(prow, nrow, CHA_OFFSET, 0); | chA = calibrate(prow, nrow, CHA_OFFSET, 0); | ||||
chB = calibrate(prow, nrow, CHB_OFFSET, 0); | chB = calibrate(prow, nrow, CHB_OFFSET, 0); | ||||
@@ -433,8 +430,8 @@ int main(int argc, char **argv) { | |||||
ImageOut(pngfilename, "Temperature", prow, nrow, CH_WIDTH, CHB_OFFSET, (png_color*)TempPalette, 0, 0); | ImageOut(pngfilename, "Temperature", prow, nrow, CH_WIDTH, CHB_OFFSET, (png_color*)TempPalette, 0, 0); | ||||
} | } | ||||
// We have to run the contrast enhance here because the temperature function requires real data | |||||
// Yes, this is bodgy, yes I should replace this with something more elegant | |||||
// We have to run the contrast enhance here because the temperature calibration requires real data | |||||
// Yes, this requires running a large chunk of code again, but this will be addressed in the future | |||||
chA = calibrate(prow, nrow, CHA_OFFSET, contrastBoost); | chA = calibrate(prow, nrow, CHA_OFFSET, contrastBoost); | ||||
chB = calibrate(prow, nrow, CHB_OFFSET, contrastBoost); | chB = calibrate(prow, nrow, CHB_OFFSET, contrastBoost); | ||||
@@ -480,10 +477,10 @@ int main(int argc, char **argv) { | |||||
// False color image | // False color image | ||||
if(CONTAINS(imgopt, 'c')){ | if(CONTAINS(imgopt, 'c')){ | ||||
if (chA == 2 && chB == 4) { // Normal false color | |||||
if (chA == 2 && chB >= 4) { // Normal false color | |||||
sprintf(pngfilename, "%s/%s-c.png", pngdirname, name); | sprintf(pngfilename, "%s/%s-c.png", pngdirname, name); | ||||
ImageRGBOut(pngfilename, prow, nrow); | ImageRGBOut(pngfilename, prow, nrow); | ||||
} else if (chA == 1 && chB == 2) { // GVI false color | |||||
} else if (chA == 1 && chB == 2) { // GVI (global vegetation index) false color | |||||
Ngvi(prow, nrow); | Ngvi(prow, nrow); | ||||
sprintf(pngfilename, "%s/%s-c.png", pngdirname, name); | sprintf(pngfilename, "%s/%s-c.png", pngdirname, name); | ||||
ImageOut(pngfilename, "GVI False Color", prow, nrow, CH_WIDTH, CHB_OFFSET, (png_color*)GviPalette, 0, 0); | ImageOut(pngfilename, "GVI False Color", prow, nrow, CH_WIDTH, CHB_OFFSET, (png_color*)GviPalette, 0, 0); | ||||
@@ -9,4 +9,5 @@ | |||||
#define TOTAL_TELE (SYNC_WIDTH+SPC_WIDTH+TELE_WIDTH+SYNC_WIDTH+SPC_WIDTH+TELE_WIDTH) | #define TOTAL_TELE (SYNC_WIDTH+SPC_WIDTH+TELE_WIDTH+SYNC_WIDTH+SPC_WIDTH+TELE_WIDTH) | ||||
#define CLIP(val, bottom, top) (val > top ? top : (val > bottom ? val : bottom)) | #define CLIP(val, bottom, top) (val > top ? top : (val > bottom ? val : bottom)) | ||||
#define CONTAINS(str, char) (strchr(str, (int) char) != NULL) | |||||
#define CONTAINS(str, char) (strchr(str, (int) char) != NULL) | |||||
#define MCOMPOSITE(m1, a1, m2, a2) (m1*a1 + m2*a2*(1-a1)) |