From bb2401356a766a1bedd63bac24cf062725d0c030 Mon Sep 17 00:00:00 2001 From: George Vardakis Date: Mon, 10 Apr 2017 18:03:00 +0300 Subject: [PATCH] Add option for rotating image --- grc/satnogs_noaa_apt_sink.xml | 17 ++++- include/satnogs/noaa_apt_sink.h | 16 +++-- lib/noaa_apt_sink_impl.cc | 118 +++++++++++++++++++++++++++----- lib/noaa_apt_sink_impl.h | 9 ++- 4 files changed, 133 insertions(+), 27 deletions(-) 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