diff --git a/grc/satnogs_noaa_apt_sink.xml b/grc/satnogs_noaa_apt_sink.xml
index bd2f87f..63cff9a 100644
--- a/grc/satnogs_noaa_apt_sink.xml
+++ b/grc/satnogs_noaa_apt_sink.xml
@@ -4,7 +4,7 @@
satnogs_noaa_apt_sink
[satnogs]
import satnogs
- satnogs.noaa_apt_sink($*filename_png, $width, $height, $split, $sync)
+ satnogs.noaa_apt_sink($*filename_png, $width, $height, $split, $sync, $flip)
Output PNG Filename
filename_png
@@ -53,6 +53,21 @@
True
+
+ Flip Image
+ flip
+ False
+ bool
+ part
+
+
+
in
float
diff --git a/include/satnogs/noaa_apt_sink.h b/include/satnogs/noaa_apt_sink.h
index cfa6e84..5cabfe5 100644
--- a/include/satnogs/noaa_apt_sink.h
+++ b/include/satnogs/noaa_apt_sink.h
@@ -703,12 +703,15 @@ namespace gr
* choose between deriving a single PNG file for each
* width x length pixels or two PNG files corresponding to
* each one of the two different spectrum images contained
- * in a NOAA APT transmission. Further, this block performs
- * normalization on the input float values based on the max
- * and min values observed in the stream. Adding to that,
- * the user has the option to synchronize to the first of the
+ * in a NOAA APT transmission. The notation 'left' and 'right'
+ * is with respect to the original image sent by the satellite.
+ * Further, this block performs normalization on the input
+ * float values based on the max and min values observed in the stream.
+ * Adding to that, the user has the option to synchronize to the first of the
* two training sequences used by the NOAA APT protocol so that
- * the two images are displayed one next to the other.
+ * the two images are displayed one next to the other. The user
+ * can also select to rotate the image 180 degrees in case the captured one
+ * is upside down.
*
*
* @param filename_png the base filename of the output PNG file(s)
@@ -718,11 +721,12 @@ namespace gr
* in a NOAA APT transmission
* @param sync user option for synchronizing to the first of the
* two training sequences
+ * @param flip user option to rotate the image(s) 180 degrees
*
*/
static sptr
make (const char *filename_png, size_t width,
- size_t height, bool split, bool sync);
+ size_t height, bool split, bool sync, bool flip);
};
} // namespace satnogs
diff --git a/lib/noaa_apt_sink_impl.cc b/lib/noaa_apt_sink_impl.cc
index 80bf302..88c8be5 100644
--- a/lib/noaa_apt_sink_impl.cc
+++ b/lib/noaa_apt_sink_impl.cc
@@ -691,10 +691,10 @@ namespace gr
noaa_apt_sink::sptr
noaa_apt_sink::make (const char *filename_png,
- size_t width, size_t height, bool split, bool sync)
+ size_t width, size_t height, bool split, bool sync, bool flip)
{
return gnuradio::get_initial_sptr (
- new noaa_apt_sink_impl (filename_png, width, height, split, sync));
+ new noaa_apt_sink_impl (filename_png, width, height, split, sync, flip));
}
/*
@@ -703,7 +703,8 @@ namespace gr
noaa_apt_sink_impl::noaa_apt_sink_impl (const char *filename_png,
size_t width, size_t height,
bool split,
- bool sync) :
+ bool sync,
+ bool flip) :
gr::sync_block ("noaa_apt_sink",
gr::io_signature::make (1, 1, sizeof(float)),
gr::io_signature::make (0, 0, 0)),
@@ -723,13 +724,21 @@ namespace gr
d_synchronize_opt(sync),
d_row_counter(0),
d_num_images(0),
- d_current_buffered_samples(0)
+ d_current_buffered_samples(0),
+ d_flip(flip)
{
set_history(d_history_length);
d_color_type = PNG_COLOR_TYPE_GRAY;
d_bit_depth = 8;
d_row_buffer = (uint8_t*)malloc(d_width*sizeof(uint8_t));
+ if(d_split){
+ d_png_fn.push_back(std::string(""));
+ d_png_fn.push_back(std::string(""));
+ }
+ else{
+ d_png_fn.push_back(std::string(""));
+ }
init_png();
}
@@ -737,7 +746,7 @@ namespace gr
noaa_apt_sink_impl::init_png(){
if (d_split) {
d_images_per_frame = 2;
- d_png_fn = (FILE**) malloc (2 * sizeof(FILE*));
+ d_png_fd = (FILE**) malloc (2 * sizeof(FILE*));
d_png_ptr = (png_structp*) malloc (2 * sizeof(png_structp));
d_info_ptr = (png_infop*) malloc (2 * sizeof(png_infop));
std::string fn (d_filename_png);
@@ -766,14 +775,16 @@ namespace gr
std::to_string (d_num_images).append ("_right"));
}
}
- d_png_fn[0] = fopen (fn_left.c_str (), "wb");
- d_png_fn[1] = fopen (fn_right.c_str (), "wb");
+ d_png_fn[0] = fn_left;
+ d_png_fn[1] = fn_right;
+ d_png_fd[0] = fopen (fn_right.c_str (), "wb");
+ d_png_fd[1] = fopen (fn_left.c_str (), "wb");
for (size_t i = 0; i < d_images_per_frame; i++) {
d_png_ptr[i] = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL,
NULL,
NULL);
d_info_ptr[i] = png_create_info_struct (d_png_ptr[i]);
- png_init_io (d_png_ptr[i], d_png_fn[i]);
+ png_init_io (d_png_ptr[i], d_png_fd[i]);
png_set_IHDR (d_png_ptr[i], d_info_ptr[i], d_width / 2, d_height,
d_bit_depth, d_color_type,
PNG_INTERLACE_NONE,
@@ -785,11 +796,12 @@ namespace gr
}
else {
d_images_per_frame = 1;
- d_png_fn = (FILE**) malloc (sizeof(FILE*));
+ d_png_fd = (FILE**) malloc (sizeof(FILE*));
d_png_ptr = (png_structp*) malloc (sizeof(png_structp));
d_info_ptr = (png_infop*) malloc (sizeof(png_infop));
if (d_num_images == 0) {
- d_png_fn[0] = fopen (d_filename_png, "wb");
+ d_png_fd[0] = fopen (d_filename_png, "wb");
+ d_png_fn[0] = std::string(d_filename_png);
}
else {
std::string fn (d_filename_png);
@@ -799,14 +811,15 @@ namespace gr
else {
fn.insert (found, std::to_string (d_num_images));
}
- d_png_fn[0] = fopen (fn.c_str (), "wb");
+ d_png_fd[0] = fopen (fn.c_str (), "wb");
+ d_png_fn[0] = fn;
}
d_png_ptr[0] = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL,
NULL,
NULL);
d_info_ptr[0] = png_create_info_struct (d_png_ptr[0]);
- png_init_io (d_png_ptr[0], d_png_fn[0]);
+ png_init_io (d_png_ptr[0], d_png_fd[0]);
png_set_IHDR (d_png_ptr[0], d_info_ptr[0], d_width, d_height,
d_bit_depth, d_color_type,
PNG_INTERLACE_NONE,
@@ -819,12 +832,14 @@ namespace gr
void
noaa_apt_sink_impl::write_png_row (){
if (d_row_counter == d_height) {
- d_row_counter =0;
- d_num_images++;
for (size_t i = 0; i < d_images_per_frame; i++) {
png_write_end (d_png_ptr[i], NULL);
- fclose (d_png_fn[i]);
+ fclose (d_png_fd[i]);
}
+ if(d_flip)
+ flip_image();
+ d_row_counter =0;
+ d_num_images++;
init_png();
}
if (d_split) {
@@ -837,7 +852,6 @@ namespace gr
}
d_row_counter++;
}
-
noaa_apt_sink_impl::~noaa_apt_sink_impl ()
{
if(d_current_buffered_samples < d_width){
@@ -851,12 +865,80 @@ namespace gr
write_png_row();
}
}
+
for (size_t i = 0; i < d_images_per_frame; i++) {
png_write_end (d_png_ptr[i], NULL);
- fclose (d_png_fn[i]);
+ fclose (d_png_fd[i]);
}
-
+ if(d_flip)
+ flip_image();
}
+
+ void
+ noaa_apt_sink_impl::flip_image ()
+ {
+ int height;
+ png_byte color_type;
+ png_byte bit_depth;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ int number_of_passes;
+ png_bytep* row_pointers;
+ size_t width;
+ //init_png();
+ if (d_split)
+ width = d_width / 2;
+ else
+ width = d_width;
+ for (size_t i = 0; i < d_images_per_frame; i++) {
+ char header[8]; // 8 is the maximum size that can be checked
+ d_png_fd[i] = fopen (d_png_fn[i].c_str (), "rb");
+ fread (header, 1, 8, d_png_fd[i]);
+
+ /* initialize stuff */
+ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL,
+ NULL);
+
+ info_ptr = png_create_info_struct (png_ptr);
+
+ png_init_io (png_ptr, d_png_fd[i]);
+ png_set_sig_bytes (png_ptr, 8);
+ png_read_info (png_ptr, info_ptr);
+
+ png_read_update_info (png_ptr, info_ptr);
+
+ row_pointers = (png_bytep*) malloc (sizeof(png_bytep) * d_height);
+ for (size_t y = 0; y < d_height; y++)
+ row_pointers[y] = (png_byte*) malloc (
+ png_get_rowbytes (png_ptr, info_ptr));
+
+ png_read_image (png_ptr, row_pointers);
+
+ fclose (d_png_fd[i]);
+ d_png_fd[i] = fopen (d_png_fn[i].c_str (), "wb");
+ d_png_ptr[i] = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL,
+ NULL,
+ NULL);
+ d_info_ptr[i] = png_create_info_struct (d_png_ptr[i]);
+ png_init_io (d_png_ptr[i], d_png_fd[i]);
+ png_set_IHDR (d_png_ptr[i], d_info_ptr[i], width, d_height, d_bit_depth,
+ d_color_type,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE,
+ PNG_FILTER_TYPE_BASE);
+
+ png_write_info (d_png_ptr[i], d_info_ptr[i]);
+ for (int j = d_height - 1; j >= 0; j--) {
+ uint8_t *istart = row_pointers[j];
+ uint8_t *iend = istart + width;
+ std::reverse (row_pointers[j], iend);
+ png_write_row (d_png_ptr[i], row_pointers[j]);
+ }
+ png_write_end (d_png_ptr[i], NULL);
+ fclose (d_png_fd[i]);
+ }
+ }
+
int
noaa_apt_sink_impl::work (int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/lib/noaa_apt_sink_impl.h b/lib/noaa_apt_sink_impl.h
index 326b23a..2385d87 100644
--- a/lib/noaa_apt_sink_impl.h
+++ b/lib/noaa_apt_sink_impl.h
@@ -709,20 +709,25 @@ namespace gr
uint8_t* d_row_buffer;
png_byte d_color_type;
png_byte d_bit_depth;
- FILE** d_png_fn;
+ FILE** d_png_fd;
size_t d_images_per_frame;
size_t d_row_counter;
size_t d_num_images;
size_t d_current_buffered_samples;
+ std::vector d_png_fn;
+ bool d_flip;
+
public:
noaa_apt_sink_impl (const char *filename_png,
- size_t width, size_t height, bool split, bool sync);
+ size_t width, size_t height, bool split, bool sync, bool flip);
~noaa_apt_sink_impl ();
void
write_png_row ();
void
init_png ();
+ void
+ flip_image();
// Where all the action really happens
int