diff --git a/Makefile b/Makefile
index c6df7be..2ea66df 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CC = gcc
+CC = clang
BIN = /usr/bin
INCLUDES = -I.
CFLAGS = -O3 -Wall $(INCLUDES)
@@ -7,7 +7,7 @@ OBJS = main.o image.o dsp.o filter.o reg.o fcolor.o
aptdec: $(OBJS)
$(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
filter.o: filter.c filter.h
image.o: image.c satcal.h offsets.h messages.h
diff --git a/README.md b/README.md
index ed449e5..203a29c 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@ To uninstall
-i [r|a|b|c|t|l]
Output image type
Raw (r), Channel A (a), Channel B (b), False Color (c), Temperature (t), Layered (l)
-Default: ab
+Default: "ab"
-d
Images destination directory (optional).
@@ -62,17 +62,17 @@ Default: Current directory
-s [15|16|17|18|19]
Satellite number
-For temperature and false color generation
-Default: 19
+For temperature calibration
+Default: "19"
-e [c|t]
Enhancements
Contrast (c) or Crop Telemetry (t)
-Defaults: ct
+Defaults: "ct"
-c
Use configuration file for false color generation.
-Default: Internal parameters
+Default: Internal defaults
```
## Output
diff --git a/temppalette.h b/colorpalette.h
similarity index 57%
rename from temppalette.h
rename to colorpalette.h
index 6e6d716..de3d95d 100644
--- a/temppalette.h
+++ b/colorpalette.h
@@ -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] = {
"\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"
@@ -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"
"\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;\""
- "\3762\40\376(\37\376\35\35",
-};
+ "\3762\40\376(\37\376\35"
+};
\ No newline at end of file
diff --git a/falsecolor.conf b/falsecolor.conf
index cb3c03c..fff1193 100644
--- a/falsecolor.conf
+++ b/falsecolor.conf
@@ -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
\ No newline at end of file
diff --git a/fcolor.c b/fcolor.c
index e3608c8..a3a98e1 100644
--- a/fcolor.c
+++ b/fcolor.c
@@ -3,133 +3,89 @@
#include "offsets.h"
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 {
- 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 = {
- 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;
fin = fopen(file, "r");
if (fin == NULL)
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);
};
-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) {
- printf("GVI... ");
+ printf("Computing GVI false color\n");
fflush(stdout);
for (int n = 0; n < nrow; n++) {
@@ -148,6 +104,4 @@ void Ngvi(float **prow, int nrow) {
pixelv[i + CHB_OFFSET] = pv;
}
}
- printf("Done\n");
-};
-
+};
\ No newline at end of file
diff --git a/gvipalette.h b/gvipalette.h
deleted file mode 100644
index a9ab41f..0000000
--- a/gvipalette.h
+++ /dev/null
@@ -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"
-};
\ No newline at end of file
diff --git a/main.c b/main.c
index 169c6fe..16138e8 100644
--- a/main.c
+++ b/main.c
@@ -27,14 +27,15 @@
#include
+#include
+
#include
#include
#include "messages.h"
#include "offsets.h"
-#include "temppalette.h"
-#include "gvipalette.h"
+#include "colorpalette.h"
extern int getpixelrow(float *pixelv);
extern int init_dsp(double F);;
@@ -74,7 +75,7 @@ static int initsnd(char *filename) {
// Get a sample from the wave file
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[] = {
@@ -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);
if (!png_ptr) {
fprintf(stderr, ERR_PNG_WRITE);
- return(1);
+ return(0);
}
// Metadata
@@ -103,7 +104,7 @@ static int ImageOut(char *filename, char *chid, float **prow, int nrow, int widt
if (!info_ptr) {
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
fprintf(stderr, ERR_PNG_INFO);
- return(1);
+ return(0);
}
if(palette == NULL) {
@@ -156,9 +157,9 @@ static int ImageOut(char *filename, char *chid, float **prow, int nrow, int widt
}
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{
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);
printf("\nDone\n");
png_destroy_write_struct(&png_ptr, &info_ptr);
- return(0);
+ return(1);
}
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_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
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);
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);
pngfile = fopen(filename, "wb");
if (pngfile == NULL) {
@@ -221,23 +222,20 @@ static int ImageRGBOut(char *filename, float **prow, int nrow) {
pixelc = prow[n];
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_end(png_ptr, info_ptr);
fclose(pngfile);
- printf("Done\n");
+ printf("\nDone\n");
png_destroy_write_struct(&png_ptr, &info_ptr);
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 void Temperature(float **prow, int nrow, int ch, int offset);
extern int Ngvi(float **prow, int nrow);
-extern void readfconf(char *file);
+extern void readfcconf(char *file);
extern int optind;
extern char *optarg;
@@ -343,7 +341,7 @@ int main(int argc, char **argv) {
break;
// False color config file
case 'c':
- readfconf(optarg);
+ readfcconf(optarg);
break;
// Output image type
case 'i':
@@ -366,7 +364,6 @@ int main(int argc, char **argv) {
usage();
}
}
-
if(optind == argc){
printf("No audio files provided.\n");
usage();
@@ -419,7 +416,7 @@ int main(int argc, char **argv) {
sf_close(inwav);
// 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);
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);
}
- // 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);
chB = calibrate(prow, nrow, CHB_OFFSET, contrastBoost);
@@ -480,10 +477,10 @@ int main(int argc, char **argv) {
// False color image
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);
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);
sprintf(pngfilename, "%s/%s-c.png", pngdirname, name);
ImageOut(pngfilename, "GVI False Color", prow, nrow, CH_WIDTH, CHB_OFFSET, (png_color*)GviPalette, 0, 0);
diff --git a/offsets.h b/offsets.h
index d8980bb..453e4fc 100644
--- a/offsets.h
+++ b/offsets.h
@@ -9,4 +9,5 @@
#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 CONTAINS(str, char) (strchr(str, (int) char) != NULL)
\ No newline at end of file
+#define CONTAINS(str, char) (strchr(str, (int) char) != NULL)
+#define MCOMPOSITE(m1, a1, m2, a2) (m1*a1 + m2*a2*(1-a1))
\ No newline at end of file