diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | README | 40 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | src/Fl_Search_Chooser.H | 4 | ||||
-rw-r--r-- | src/Fl_Value_Dial.H | 8 | ||||
-rw-r--r-- | src/Fl_Value_Dial.cxx | 4 | ||||
-rw-r--r-- | src/GipfelWidget.H | 15 | ||||
-rw-r--r-- | src/GipfelWidget.cxx | 75 | ||||
-rw-r--r-- | src/Hill.H | 2 | ||||
-rw-r--r-- | src/Hill.cxx | 2 | ||||
-rw-r--r-- | src/JPEGOutputImage.H | 55 | ||||
-rw-r--r-- | src/JPEGOutputImage.cxx | 121 | ||||
-rw-r--r-- | src/Makefile.am | 12 | ||||
-rw-r--r-- | src/OutputImage.H | 53 | ||||
-rw-r--r-- | src/OutputImage.cxx | 92 | ||||
-rw-r--r-- | src/Panorama.H | 4 | ||||
-rw-r--r-- | src/Panorama.cxx | 24 | ||||
-rw-r--r-- | src/PreviewOutputImage.H | 52 | ||||
-rw-r--r-- | src/PreviewOutputImage.cxx | 91 | ||||
-rw-r--r-- | src/Projection.H | 7 | ||||
-rw-r--r-- | src/Projection.cxx | 3 | ||||
-rw-r--r-- | src/ProjectionSphaeric.H | 5 | ||||
-rw-r--r-- | src/ProjectionSphaeric.cxx | 22 | ||||
-rw-r--r-- | src/ProjectionTangential.H | 5 | ||||
-rw-r--r-- | src/ProjectionTangential.cxx | 11 | ||||
-rw-r--r-- | src/Stitch.H | 51 | ||||
-rw-r--r-- | src/Stitch.cxx | 151 | ||||
-rw-r--r-- | src/TIFFOutputImage.H | 49 | ||||
-rw-r--r-- | src/TIFFOutputImage.cxx | 110 | ||||
-rw-r--r-- | src/choose_hill.H | 6 | ||||
-rw-r--r-- | src/gipfel.cxx | 99 |
31 files changed, 1109 insertions, 73 deletions
@@ -1,6 +1,9 @@ gipfel ChangeLog ================= +gipfel-0.1.3 + - Add stitching mode (gipfel -s). See README for details. + gipfel-0.1.2 - Fix bugs for "Normal Projection" and "Panoramic Projection" mode. Panorama mode now works with the great view from Mount Everest by @@ -18,9 +18,11 @@ picture manually. Requirements ============ -- gipfel works on UNIX-like system (e.g. Linux, *BSD and probably others). -- You need fltk-1.1.x from www.fltk.org. -- You need the ccmath library (http://freshmeat.net/projects/ccmath/). +- fltk-1.1.x (http://www.fltk.org) +- libtiff (http://www.remotesensing.org/libtiff/) +- libjpeg (http://www.ijg.org/) +- ccmath library (http://freshmeat.net/projects/ccmath/) +- gipfel works on UNIX-like system (e.g. Linux, *BSD and probably others) Installation @@ -133,6 +135,37 @@ the Option->Show Hidden menu entry. Hidden objects and hidden GPS way points are displayed in blue. +Stitching +========= + +If you have multiple images from the same viewpoint referenced with gipfel +you can stitch them together to form a panorama image. +For stitching the input images must all have been correctly referenced +with gipfel and saved (see "Loading and Saving Images"). +You can then call gipfel -s <img1> <img2> ... +to see the result in a window. Alternatively you can call +gipfel -s -j <outimg> <img1> <img2> ... +to save the result as a JPEG image to <outimg> or +gipfel -s -t <outdir> <img1> <img2> ... +to save the result as multiple TIFF images to <outdir>. +Use the multiple TIFF option for blending the result with enblend +(http://enblend.sourceforge.net/). +The width and height of the result images can be adjusted with the +-w and -h options. + +The nice thing about stitching is that gipfel uses the same code that +it already had for positioning mountains on the pictures. +gipfel simply scans all directions needed for the panorama and determines +where these directions would end up on the various pictures. It can then +record the corresponding color values from the input images. + +In contrast to other stitching programs, the input images don't need to +overlap. + +If you want to open a stitched image in gipfel to locate the mountains +on it, don't forget to choose Panoramic Projection! + + Troubleshooting =============== @@ -180,4 +213,3 @@ results of gipfel. Johannes Hofmann (Johannes.Hofmann@gmx.de) -Nov 14, 2005 diff --git a/configure.ac b/configure.ac index 6d4f557..1b5d0ac 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -AC_INIT(gipfel, 0.1.2, Johannes.Hofmann@gmx.de) +AC_INIT(gipfel, 0.1.3, Johannes.Hofmann@gmx.de) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([src/Panorama.H]) AC_CONFIG_HEADER(config.h) @@ -52,5 +52,9 @@ LIBS="`$FLTKCONFIG --use-images --ldflags` $LIBS" AC_CHECK_HEADERS([ccmath.h], [], [echo "Error: ccmath.h not found."; exit 1;]) AC_CHECK_LIB([ccm], [open], [], [echo "Error: ccmath.so not found."; exit 1;]) +# Check for libtiff +AC_CHECK_HEADERS([tiffio.h], [], [echo "Error: tiffio.h not found."; exit 1;]) +AC_CHECK_LIB([tiff], [TIFFOpen], [], [echo "Error: libtiff.so not found."; exit 1;]) + AC_CONFIG_FILES([Makefile src/Makefile]) AC_OUTPUT diff --git a/src/Fl_Search_Chooser.H b/src/Fl_Search_Chooser.H index 6bb71fe..c87f0de 100644 --- a/src/Fl_Search_Chooser.H +++ b/src/Fl_Search_Chooser.H @@ -1,6 +1,4 @@ // -// "$Id: Fl_Value_Dial.H,v 1.2 2005/05/18 11:34:30 hofmann Exp $" -// // Value dial header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2004 by Bill Spitzak and others. @@ -20,8 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA. // -// Please report all bugs and problems to "fltk-bugs@fltk.org". -// #ifndef FL_SEARCH_CHOOSER_H #define FL_SEARCH_CHOOSER_H diff --git a/src/Fl_Value_Dial.H b/src/Fl_Value_Dial.H index 7d41aa5..f9ac18c 100644 --- a/src/Fl_Value_Dial.H +++ b/src/Fl_Value_Dial.H @@ -1,6 +1,4 @@ // -// "$Id: Fl_Value_Dial.H,v 1.2 2005/05/18 11:34:30 hofmann Exp $" -// // Value dial header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2004 by Bill Spitzak and others. @@ -20,8 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA. // -// Please report all bugs and problems to "fltk-bugs@fltk.org". -// #ifndef Fl_Value_Dial_H #define Fl_Value_Dial_H @@ -45,7 +41,3 @@ class Fl_Value_Dial : public Fl_Dial { }; #endif - -// -// End of "$Id: Fl_Value_Dial.H,v 1.2 2005/05/18 11:34:30 hofmann Exp $". -// diff --git a/src/Fl_Value_Dial.cxx b/src/Fl_Value_Dial.cxx index 6e5c35c..c837930 100644 --- a/src/Fl_Value_Dial.cxx +++ b/src/Fl_Value_Dial.cxx @@ -1,6 +1,4 @@ // -// "$Id: Fl_Value_Dial.cxx,v 1.2 2005/05/18 11:34:30 hofmann Exp $" -// // Value dial widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2004 by Bill Spitzak and others. @@ -20,8 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA. // -// Please report all bugs and problems to "fltk-bugs@fltk.org". -// #include <FL/Fl.H> #include <FL/fl_draw.H> diff --git a/src/GipfelWidget.H b/src/GipfelWidget.H index 1aebbea..7bcd3c0 100644 --- a/src/GipfelWidget.H +++ b/src/GipfelWidget.H @@ -1,7 +1,5 @@ // -// "$Id: GipfelWidget.H,v 1.22 2005/06/22 19:47:19 hofmann Exp $" -// -// Copyright 2005 by Johannes Hofmann +// Copyright 2006 by Johannes Hofmann // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -49,6 +47,12 @@ class GipfelWidget : public Fl_Widget { int get_rel_track_width(Hill *m); + static int get_pixel_nearest(Fl_Image *img, double x, double y, + char *r, char *g, char *b); + + static int get_pixel(Fl_Image *img, int x, int y, + char *r, char *g, char *b); + public: GipfelWidget(int X,int Y,int W, int H); @@ -57,6 +61,8 @@ class GipfelWidget : public Fl_Widget { int load_image(char *file); int save_image(char *file); + + const char * get_image_filename(); int load_data(const char *file); @@ -118,6 +124,9 @@ class GipfelWidget : public Fl_Widget { int update(); + int get_pixel(double a_view, double a_nick, + char *r, char *g, char *b); + void draw(); }; #endif diff --git a/src/GipfelWidget.cxx b/src/GipfelWidget.cxx index 0c4ef08..c4fe032 100644 --- a/src/GipfelWidget.cxx +++ b/src/GipfelWidget.cxx @@ -147,6 +147,11 @@ GipfelWidget::load_image(char *file) { return 0; } +const char * +GipfelWidget::get_image_filename() { + return img_file; +} + int GipfelWidget::save_image(char *file) { char * args[32]; @@ -714,6 +719,7 @@ GipfelWidget::set_track_width(double w) { redraw(); } + int GipfelWidget::handle(int event) { int mark_x, mark_y; @@ -743,3 +749,72 @@ GipfelWidget::handle(int event) { } return 0; } + +int +GipfelWidget::get_pixel(double a_view, double a_nick, + char *r, char *g, char *b) { + double px, py; + + + if (img == NULL) { + return 1; + } + + if (pan->get_coordinates(a_view, a_nick, &px, &py) != 0) { + return 1; + } + + return get_pixel_nearest(img, px + ((double) img->w()) / 2.0, + py + ((double) img->h()) / 2.0, r, g, b); +} + +int +GipfelWidget::get_pixel_nearest(Fl_Image *img, double x, double y, + char *r, char *g, char *b) { + if (isnan(x) || isnan(y)) { + return 1; + } else { + return get_pixel(img, (int) rint(x), (int) rint(y), r, g, b); + } +} + + +int +GipfelWidget::get_pixel(Fl_Image *img, int x, int y, + char *r, char *g, char *b) { + if ( img->d() == 0 ) { + return 1; + } + + if (x < 0 || x >=img->w() || y < 0 || y >= img->h()) { + return 1; + } + long index = (y * img->w() * img->d()) + (x * img->d()); // X/Y -> buf index + switch ( img->count() ) { + case 1: { // bitmap + const char *buf = img->data()[0]; + switch ( img->d() ) { + case 1: { // 8bit + *r = *g = *b = *(buf+index); + break; + } + case 3: // 24bit + *r = *(buf+index+0); + *g = *(buf+index+1); + *b = *(buf+index+2); + break; + default: // ?? + printf("Not supported: chans=%d\n", img->d()); + return 1; + } + break; + } + default: // ?? pixmap, bit vals + printf("Not supported: count=%d\n", img->count()); + return 1; + } + + return 0; + +} + @@ -1,6 +1,4 @@ // -// "$Id: Hill.H,v 1.16 2005/06/22 20:40:35 hofmann Exp $" -// // Copyright 2005 by Johannes Hofmann // // This library is free software; you can redistribute it and/or diff --git a/src/Hill.cxx b/src/Hill.cxx index 626e470..67e1d8e 100644 --- a/src/Hill.cxx +++ b/src/Hill.cxx @@ -58,7 +58,7 @@ Hill::Hill(const Hill& h) { } Hill::Hill(int x_tmp, int y_tmp) { - name = ""; + name = NULL; phi = 0.0; lam = 0.0; height = 0.0; diff --git a/src/JPEGOutputImage.H b/src/JPEGOutputImage.H new file mode 100644 index 0000000..50570e5 --- /dev/null +++ b/src/JPEGOutputImage.H @@ -0,0 +1,55 @@ +// +// Copyright 2006 by Johannes Hofmann +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +#ifndef JPEGOUTPUTIMAGE_H +#define JPEGOUTPUTIMAGE_H + +#include <stdio.h> +extern "C" { +#include <jpeglib.h> +#undef HAVE_STDLIB_H +} + +#include "OutputImage.H" + +class JPEGOutputImage : OutputImage { + private: + unsigned char *row; + char *file; + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + FILE *fp; + int quality; + + public: + JPEGOutputImage(const char *file, int quality = 90); + + ~JPEGOutputImage(); + + protected: + int init_internal(int w, int h); + + int set_pixel_internal(int x, char r, char g, char b); + + int next_line_internal(); + + int done_internal(); +}; + +#endif diff --git a/src/JPEGOutputImage.cxx b/src/JPEGOutputImage.cxx new file mode 100644 index 0000000..3f7fd11 --- /dev/null +++ b/src/JPEGOutputImage.cxx @@ -0,0 +1,121 @@ +// +// Copyright 2006 by Johannes Hofmann +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +extern "C" { +#include <jpeglib.h> +} + +#include "JPEGOutputImage.H" + +JPEGOutputImage::JPEGOutputImage(const char *f, int q) { + file = strdup(f); + fp = NULL; + row = NULL; + quality = q; +} + +JPEGOutputImage::~JPEGOutputImage() { + if (row) { + free(row); + } + if (file) { + free(file); + } +} + +int +JPEGOutputImage::init_internal(int w1, int h1) { + if (row) { + free(row); + row = NULL; + } + + row = (unsigned char*) malloc(sizeof(char) * 3 * W); + if (!row) { + perror("malloc"); + return 1; + } + memset(row, 0, sizeof(char) * 3 * W); + + if (fp) { + fclose(fp); + } + + if ((fp = fopen(file, "wb")) == NULL) { + fprintf(stderr, "can't open %s\n", file); + return 1; + } + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + jpeg_stdio_dest(&cinfo, fp); + cinfo.image_width = W; + cinfo.image_height = H; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; + + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, quality, TRUE); + + jpeg_start_compress(&cinfo, TRUE); + +} + +int +JPEGOutputImage::set_pixel_internal(int x, char r, char g, char b) { + row[x*3+0] = r; + row[x*3+1] = g; + row[x*3+2] = b; + + return 0; +} + +int +JPEGOutputImage::next_line_internal() { + JSAMPROW row_pointer[1]; + + row_pointer[0] = row; + jpeg_write_scanlines(&cinfo, row_pointer, 1); + memset(row, 0, sizeof(char) * 3 * W); + return 0; +} + +int +JPEGOutputImage::done_internal() { + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + if (fp) { + fclose(fp); + fp = NULL; + } + if (row) { + free(row); + } + + if (fp) { + fclose(fp); + fp = NULL; + } + return 0; +} + diff --git a/src/Makefile.am b/src/Makefile.am index e9e32f7..5577090 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,7 +11,12 @@ gipfel_SOURCES = \ Hill.cxx \ Fl_Value_Dial.cxx \ Fl_Search_Chooser.cxx \ - choose_hill.cxx + choose_hill.cxx \ + Stitch.cxx \ + OutputImage.cxx \ + JPEGOutputImage.cxx \ + TIFFOutputImage.cxx \ + PreviewOutputImage.cxx noinst_HEADERS = \ GipfelWidget.H \ @@ -24,4 +29,9 @@ noinst_HEADERS = \ Fl_Value_Dial.H \ Fl_Search_Chooser.H \ choose_hill.H \ + Stitch.H \ + OutputImage.H \ + JPEGOutputImage.H \ + TIFFOutputImage.H \ + PreviewOutputImage.H \ util.h diff --git a/src/OutputImage.H b/src/OutputImage.H new file mode 100644 index 0000000..8792eb6 --- /dev/null +++ b/src/OutputImage.H @@ -0,0 +1,53 @@ +// +// Copyright 2006 by Johannes Hofmann +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +#ifndef OUTPUTIMAGE_H +#define OUTPUTIMAGE_H + + +class OutputImage { + private: + int initialized; + + public: + OutputImage(); + + ~OutputImage(); + + virtual int init(int w1, int h1); + + int set_pixel(int x, char r, char g, char b); + + int next_line(); + + int done(); + + protected: + int W, H, line; + + virtual int init_internal(int w1, int h1); + + virtual int set_pixel_internal(int x, char r, char g, char b); + + virtual int next_line_internal(); + + virtual int done_internal(); +}; + +#endif diff --git a/src/OutputImage.cxx b/src/OutputImage.cxx new file mode 100644 index 0000000..f2e7296 --- /dev/null +++ b/src/OutputImage.cxx @@ -0,0 +1,92 @@ +// +// Copyright 2006 by Johannes Hofmann +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +#include <stdlib.h> +#include <stdio.h> + +#include "OutputImage.H" + +OutputImage::OutputImage() { + W = 0; + H = 0; + initialized = 0; +} + +OutputImage::~OutputImage() { +} + +int +OutputImage::init(int w1, int h1) { + W = w1; + H = h1; + line = 0; + initialized = 1; + + return init_internal(w1, h1); +} + + +int +OutputImage::init_internal(int w1, int h1) { + return 0; +} + +int +OutputImage::set_pixel(int x, char r, char g, char b) { + if (!initialized || x < 0 || x >= W) { + return 1; + } else { + return set_pixel_internal(x, r, g, b); + } +} + +int +OutputImage::set_pixel_internal(int x, char r, char g, char b) { + return 0; +} + +int +OutputImage::next_line() { + if (!initialized || line++ >= H) { + return 1; + } else { + return next_line_internal(); + } +} + +int +OutputImage::next_line_internal() { + return 0; +} + +int +OutputImage::done() { + if (!initialized) { + return 1; + } else { + next_line(); + return done_internal(); + } +} + +int +OutputImage::done_internal() { + return 0; +} + diff --git a/src/Panorama.H b/src/Panorama.H index 32cefa6..a538809 100644 --- a/src/Panorama.H +++ b/src/Panorama.H @@ -1,6 +1,4 @@ // -// "$Id: Panorama.H,v 1.20 2005/06/22 19:47:20 hofmann Exp $" -// // Copyright 2005 by Johannes Hofmann // // This library is free software; you can redistribute it and/or @@ -144,5 +142,7 @@ class Panorama { Projection::Projection_t get_projection(); void set_projection(Projection::Projection_t p); + + int get_coordinates(double a_view, double a_nick, double *x, double *y); }; #endif diff --git a/src/Panorama.cxx b/src/Panorama.cxx index c8cb1dc..73bc003 100644 --- a/src/Panorama.cxx +++ b/src/Panorama.cxx @@ -508,8 +508,11 @@ Panorama::update_coordinates() { for (int i=0; i<visible_mountains->get_num(); i++) { m = visible_mountains->get(i); + double tmp_x, tmp_y; - proj->set_coordinates(m, &parms); + proj->get_coordinates(m->a_view, m->a_nick, &parms, &tmp_x, &tmp_y); + m->x = (int) rint(tmp_x); + m->y = (int) rint(tmp_y); } } @@ -586,3 +589,22 @@ Panorama::get_real_distance(Hill *m) { return c; } +int +Panorama::get_coordinates(double a_view, double a_nick, double *x, double *y) { + a_view = a_view - parms.a_center; + + if (a_view > pi_d) { + a_view -= 2.0*pi_d; + } else if (a_view < -pi_d) { + a_view += 2.0*pi_d; + } + + if (a_view > view_angle || a_view < - view_angle) { + return 1; + } + + proj->get_coordinates(a_view, a_nick, &parms, x, y); + + return 0; +} + diff --git a/src/PreviewOutputImage.H b/src/PreviewOutputImage.H new file mode 100644 index 0000000..7095999 --- /dev/null +++ b/src/PreviewOutputImage.H @@ -0,0 +1,52 @@ +// +// Copyright 2006 by Johannes Hofmann +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +#ifndef PREVIEWOUTPUTIMAGE_H +#define PREVIEWOUTPUTIMAGE_H + +#include <stdio.h> + +#include <FL/Fl_Widget.H> +#include <FL/Fl_Image.H> + +#include "OutputImage.H" + +class PreviewOutputImage : OutputImage , public Fl_Widget { + private: + uchar *data; + int d; + + public: + PreviewOutputImage(int X, int Y, int W, int H); + + ~PreviewOutputImage(); + + void draw(); + + protected: + int init_internal(int w, int h); + + int set_pixel_internal(int x, char r, char g, char b); + + int next_line_internal(); + + int done_internal(); +}; + +#endif diff --git a/src/PreviewOutputImage.cxx b/src/PreviewOutputImage.cxx new file mode 100644 index 0000000..078ba26 --- /dev/null +++ b/src/PreviewOutputImage.cxx @@ -0,0 +1,91 @@ +// +// DataImage routines. +// +// Copyright 2006 by Johannes Hofmann +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <Fl/Fl.H> +#include <Fl/fl_draw.h> + +#include "PreviewOutputImage.H" + +PreviewOutputImage::PreviewOutputImage(int X, int Y, int W, int H): Fl_Widget(X, Y, W, H) { + d = 3; + data = NULL; +} + +PreviewOutputImage::~PreviewOutputImage() { + if (data) { + free(data); + } +} + +int +PreviewOutputImage::init_internal(int w, int h) { + data = (uchar*) malloc(w * h * d); + memset(data, 0, w * h * d); + size(w, h); + return 0; +} + + + +int +PreviewOutputImage::set_pixel_internal(int x, char r, char g, char b) { + if (!data) { + return 1; + } + + long index = (line * w() * d + (x * d)); + *(data+index+0) = r; + *(data+index+1) = g; + *(data+index+2) = b; + + return 0; +} + +int +PreviewOutputImage::next_line_internal() { + if (line % 10 == 0) { + redraw(); + Fl::check(); + } + return 0; +} + +int +PreviewOutputImage::done_internal() { + return 0; +} + +void +PreviewOutputImage::draw() { + if (!data) { + return; + } + fl_push_clip(x(), y(), w(), h()); + + fl_draw_image(data, x(), y(), w(), h(), d); + + fl_pop_clip(); +} + diff --git a/src/Projection.H b/src/Projection.H index b81e531..0a6ec81 100644 --- a/src/Projection.H +++ b/src/Projection.H @@ -1,7 +1,5 @@ // -// "$Id: Panorama.H,v 1.20 2005/06/22 19:47:20 hofmann Exp $" -// -// Copyright 2005 by Johannes Hofmann +// Copyright 2006 by Johannes Hofmann // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -37,7 +35,8 @@ class Projection { Projection(); - virtual void set_coordinates(Hill *m, const ViewParams *parms); + virtual void get_coordinates(double a_view, double a_nick, + const ViewParams *parms, double *x, double *y); virtual int comp_params(const Hill *m1, const Hill *m2, ViewParams *parms); }; diff --git a/src/Projection.cxx b/src/Projection.cxx index 57a210a..1f224e8 100644 --- a/src/Projection.cxx +++ b/src/Projection.cxx @@ -31,7 +31,8 @@ Projection::Projection() { }; void -Projection::set_coordinates(Hill *m, const ViewParams *parms) { +Projection::get_coordinates(double a_view, double a_nick, + const ViewParams *parms, double *x, double *y) { fprintf(stderr, "Error: Projection::set_coordinates()\n"); } diff --git a/src/ProjectionSphaeric.H b/src/ProjectionSphaeric.H index fcaffa8..06396f1 100644 --- a/src/ProjectionSphaeric.H +++ b/src/ProjectionSphaeric.H @@ -30,11 +30,10 @@ class ProjectionSphaeric : public Projection { double comp_dir_view(const Hill *m1, const Hill *m2, double d_m1_2, double d_m2_2, double scale, double sign3); double comp_nick_view(const Hill *m1, const Hill *m2, double d_m1_2, double scale, double dir_view, double sign1); double comp_tilt_view(const Hill *m, double scale, double dir_view, double nick_view); - void set_coordinates(const Hill *m, const ViewParams *parms, - double *x, double *y); public: - void set_coordinates(Hill *m, const ViewParams *parms); + void get_coordinates(double a_view, double a_nick, const ViewParams *parms, + double *x, double *y); int comp_params(const Hill *m1, const Hill *m2, ViewParams *parms); }; diff --git a/src/ProjectionSphaeric.cxx b/src/ProjectionSphaeric.cxx index 74c9de6..e69882b 100644 --- a/src/ProjectionSphaeric.cxx +++ b/src/ProjectionSphaeric.cxx @@ -66,9 +66,9 @@ ProjectionSphaeric::comp_params(const Hill *m1, const Hill *m2, ViewParams *parm isnan(tmp.a_nick) || isnan(tmp.a_tilt)) { ; } else { - set_coordinates(m1, &tmp, &tmp_x, &tmp_y); + get_coordinates(m1->a_view, m1->a_nick, &tmp, &tmp_x, &tmp_y); val = sqrt(pow(tmp_x - m1->x, 2.0) + pow(tmp_y - m1->y, 2.0)); - set_coordinates(m2, &tmp, &tmp_x, &tmp_y); + get_coordinates(m2->a_view, m2->a_nick, &tmp, &tmp_x, &tmp_y); val += sqrt(pow(tmp_x - m2->x, 2.0) + pow(tmp_y - m2->y, 2.0)); if (val < best_val) { @@ -88,22 +88,12 @@ ProjectionSphaeric::comp_params(const Hill *m1, const Hill *m2, ViewParams *parm } void -ProjectionSphaeric::set_coordinates(Hill *m, const ViewParams *parms) { +ProjectionSphaeric::get_coordinates(double a_view, double a_nick, + const ViewParams *parms, double *x, double *y) { double x_tmp, y_tmp; - set_coordinates(m, parms, &x_tmp, &y_tmp); - - m->x = (int) rint(x_tmp); - m->y = (int) rint(y_tmp); -} - -void -ProjectionSphaeric::set_coordinates(const Hill *m, const ViewParams *parms, - double *x, double *y) { - double x_tmp, y_tmp; - - x_tmp = m->a_view * parms->scale; - y_tmp = - (m->a_nick - parms->a_nick) * parms->scale; + x_tmp = a_view * parms->scale; + y_tmp = - (a_nick - parms->a_nick) * parms->scale; // rotate by a_tilt; *x = x_tmp * cos(parms->a_tilt) - y_tmp * sin(parms->a_tilt); diff --git a/src/ProjectionTangential.H b/src/ProjectionTangential.H index 8e7673e..e74511f 100644 --- a/src/ProjectionTangential.H +++ b/src/ProjectionTangential.H @@ -1,6 +1,4 @@ // -// "$Id: Panorama.H,v 1.20 2005/06/22 19:47:20 hofmann Exp $" -// // Copyright 2005 by Johannes Hofmann // // This library is free software; you can redistribute it and/or @@ -36,7 +34,8 @@ class ProjectionTangential : public Projection { int optimize(const Hill *m1, const Hill *m2, ViewParams *parms); public: - void set_coordinates(Hill *m, const ViewParams *parms); + void get_coordinates(double a_view, double a_nick, const ViewParams *parms, + double *x, double *y); int comp_params(const Hill *m1, const Hill *m2, ViewParams *parms); }; diff --git a/src/ProjectionTangential.cxx b/src/ProjectionTangential.cxx index 032005d..416d27d 100644 --- a/src/ProjectionTangential.cxx +++ b/src/ProjectionTangential.cxx @@ -160,15 +160,16 @@ ProjectionTangential::optimize(const Hill *m1, const Hill *m2, ViewParams *parms } void -ProjectionTangential::set_coordinates(Hill *m, const ViewParams *parms) { +ProjectionTangential::get_coordinates(double a_view, double a_nick, + const ViewParams *parms, double *x, double *y) { double x_tmp, y_tmp; - x_tmp = tan(m->a_view) * parms->scale; - y_tmp = - (tan(m->a_nick - parms->a_nick) * parms->scale); + x_tmp = tan(a_view) * parms->scale; + y_tmp = - (tan(a_nick - parms->a_nick) * parms->scale); // rotate by a_tilt; - m->x = (int) rint(x_tmp * cos(parms->a_tilt) - y_tmp * sin(parms->a_tilt)); - m->y = (int) rint(x_tmp * sin(parms->a_tilt) + y_tmp * cos(parms->a_tilt)); + *x = x_tmp * cos(parms->a_tilt) - y_tmp * sin(parms->a_tilt); + *y = x_tmp * sin(parms->a_tilt) + y_tmp * cos(parms->a_tilt); } double diff --git a/src/Stitch.H b/src/Stitch.H new file mode 100644 index 0000000..0bb6d48 --- /dev/null +++ b/src/Stitch.H @@ -0,0 +1,51 @@ +// +// Copyright 2005 by Johannes Hofmann +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +#ifndef STITCH_H +#define STITCH_H + +#include "GipfelWidget.H" +#include "OutputImage.H" + +#define MAX_PICS 256 + + +class Stitch { + private: + GipfelWidget *gipf[MAX_PICS]; + OutputImage *single_images[MAX_PICS]; + OutputImage *merged_image; + + + public: + Stitch(); + + ~Stitch(); + + int load_image(char *file); + + OutputImage * set_output(OutputImage *img); + + OutputImage * set_output(const char *file, OutputImage *img); + + int resample(int w, int h, + double view_start, double view_end); +}; + +#endif diff --git a/src/Stitch.cxx b/src/Stitch.cxx new file mode 100644 index 0000000..1fe3d88 --- /dev/null +++ b/src/Stitch.cxx @@ -0,0 +1,151 @@ +// +// Stitch routines. +// +// Copyright 2006 by Johannes Hofmann +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> + +#include <Fl/Fl.H> + +#include "OutputImage.H" +#include "Stitch.H" + +static double pi_d = asin(1.0) * 2.0; + +Stitch::Stitch() { + for (int i=0; i<MAX_PICS; i++) { + gipf[i] = NULL; + single_images[i] = NULL; + } + merged_image = NULL; +} + +Stitch::~Stitch() { + for (int i=0; i<MAX_PICS; i++) { + if (gipf[i]) { + delete(gipf[i]); + } else { + break; + } + } +} + + +int +Stitch::load_image(char *file) { + for (int i=0; i<MAX_PICS; i++) { + if (gipf[i] == NULL) { + gipf[i] = new GipfelWidget(0, 0, 800, 600); + if (gipf[i]->load_image(file) != 0) { + delete gipf[i]; + gipf[i] = NULL; + } + break; + } + } + + +} + +OutputImage* +Stitch::set_output(OutputImage *img) { + OutputImage *ret = merged_image; + merged_image = img; + return ret; +} + +OutputImage* +Stitch::set_output(const char *file, OutputImage *img) { + OutputImage *ret = NULL; + + for (int i=0; i<MAX_PICS; i++) { + if (gipf[i] != NULL) { + const char *img_file = gipf[i]->get_image_filename(); + if (img_file && strcmp(file, img_file) == 0) { + ret = single_images[i]; + single_images[i] = img; + break; + } + } + } + + return ret; +} + +int +Stitch::resample(int w, int h, + double view_start, double view_end) { + double step_view = (view_end - view_start) / w; + char r, g, b; + int y_off = h / 2; + int merged_pixel_set; + double radius = (double) w / (view_end -view_start); + + if (merged_image) { + merged_image->init(w, h); + } + for (int i=0; i<MAX_PICS; i++) { + if (single_images[i]) { + single_images[i]->init(w, h); + } + } + + for (int y=0; y<h; y++) { + double a_nick = atan((double)(y_off - y)/radius); + + for (int x=0; x<w; x++) { + double a_view; + a_view = view_start + x * step_view; + merged_pixel_set = 0; + for (int i=0; i<MAX_PICS; i++) { + if (gipf[i] == NULL) { + break; + } else if (gipf[i]->get_pixel(a_view, a_nick, &r, &g, &b)==0) { + if (single_images[i]) { + single_images[i]->set_pixel(x, r, g, b); + } + if (!merged_pixel_set && merged_image) { + merged_image->set_pixel(x, r, g, b); + merged_pixel_set++; + } + } + } + } + if (merged_image) { + merged_image->next_line(); + } + for (int i=0; i<MAX_PICS; i++) { + if (single_images[i]) { + single_images[i]->next_line(); + } + } + } + + if (merged_image) { + merged_image->done(); + } + for (int i=0; i<MAX_PICS; i++) { + if (single_images[i]) { + single_images[i]->done(); + } + } +} diff --git a/src/TIFFOutputImage.H b/src/TIFFOutputImage.H new file mode 100644 index 0000000..3a14279 --- /dev/null +++ b/src/TIFFOutputImage.H @@ -0,0 +1,49 @@ +// +// Copyright 2006 by Johannes Hofmann +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +#ifndef TIFFOUTPUTIMAGE_H +#define TIFFOUTPUTIMAGE_H + +#include <stdio.h> +#include <tiffio.h> + +#include "OutputImage.H" + +class TIFFOutputImage : OutputImage { + private: + unsigned char *row; + char *file; + TIFF *tiff; + + public: + TIFFOutputImage(const char *file); + + ~TIFFOutputImage(); + + protected: + int init_internal(int w, int h); + + int set_pixel_internal(int x, char r, char g, char b); + + int next_line_internal(); + + int done_internal(); +}; + +#endif diff --git a/src/TIFFOutputImage.cxx b/src/TIFFOutputImage.cxx new file mode 100644 index 0000000..b8433ca --- /dev/null +++ b/src/TIFFOutputImage.cxx @@ -0,0 +1,110 @@ +// +// Copyright 2006 by Johannes Hofmann +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "TIFFOutputImage.H" + +TIFFOutputImage::TIFFOutputImage(const char *f) { + file = strdup(f); + tiff = NULL; + row = NULL; +} + +TIFFOutputImage::~TIFFOutputImage() { + if (row) { + free(row); + } + if (file) { + free(file); + } +} + +int +TIFFOutputImage::init_internal(int w1, int h1) { + if (row) { + free(row); + row = NULL; + } + + row = (unsigned char*) malloc(sizeof(char) * 4 * w1); + if (!row) { + perror("malloc"); + return 1; + } + memset(row, 0, sizeof(char) * 4 * w1); + + if (tiff) { + TIFFClose(tiff); + } + + if((tiff = TIFFOpen(file, "w")) == NULL){ + fprintf(stderr, "can't open %s\n", file); + return 1; + } + + TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, w1); + TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, h1); + TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); + TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, 1); + TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4); + + return 0; +} + +int +TIFFOutputImage::set_pixel_internal(int x, char r, char g, char b) { + row[x*4+0] = r; + row[x*4+1] = g; + row[x*4+2] = b; + row[x*4+3] = 255; + + return 0; +} + +int +TIFFOutputImage::next_line_internal() { + int ret; + + TIFFWriteEncodedStrip(tiff, line -1 , row, W * 4); + + memset(row, 0, sizeof(char) * 4 * W); + return 0; +} + +int +TIFFOutputImage::done_internal() { + if (tiff) { + TIFFClose(tiff); + tiff = NULL; + } + + if (row) { + free(row); + row = NULL; + } + + return 0; +} + diff --git a/src/choose_hill.H b/src/choose_hill.H index 1387868..e424d70 100644 --- a/src/choose_hill.H +++ b/src/choose_hill.H @@ -1,8 +1,4 @@ // -// "$Id: Fl_Value_Dial.H,v 1.2 2005/05/18 11:34:30 hofmann Exp $" -// -// Value dial header file for the Fast Light Tool Kit (FLTK). -// // Copyright 1998-2004 by Bill Spitzak and others. // // This library is free software; you can redistribute it and/or @@ -20,8 +16,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA. // -// Please report all bugs and problems to "fltk-bugs@fltk.org". -// #ifndef CHOOSE_HILL_H #define CHOOSE_HILL_H diff --git a/src/gipfel.cxx b/src/gipfel.cxx index 4a284aa..9755f2e 100644 --- a/src/gipfel.cxx +++ b/src/gipfel.cxx @@ -41,6 +41,10 @@ #include "Fl_Value_Dial.H" #include "Fl_Search_Chooser.H" #include "GipfelWidget.H" +#include "JPEGOutputImage.H" +#include "TIFFOutputImage.H" +#include "PreviewOutputImage.H" +#include "Stitch.H" #include "choose_hill.H" #include "../config.h" @@ -60,6 +64,12 @@ Fl_Value_Input *i_view_lat, *i_view_long, *i_view_height; Fl_Box *b_viewpoint; Fl_Menu_Bar *mb; +#define STITCH_PREVIEW 1 +#define STITCH_JPEG 2 +#define STITCH_TIFF 4 +static int stitch(int stitch_w, int stitch_h, int type, const char *path, + int argc, char **argv); + void set_values() { s_center->value(gipf->get_center_angle()); s_nick->value(gipf->get_nick_angle()); @@ -201,12 +211,17 @@ void fill_menubar(Fl_Menu_Bar* mb) { void usage() { fprintf(stderr, - "usage: gipfel [-v <viewpoint>] [-d <datafile>] [<image>]\n" + "usage: gipfel [-v <viewpoint>] [-d <datafile>]\n" + " [-s] [-j <outfile>] [-t <outdir] [-w <width>] [-h <height>]\n" + " [<image(s)>]\n" " -v <viewpoint> Set point from which the picture was taken.\n" " This must be a string that unambiguously \n" " matches the name of an entry in the data file.\n" " -d <datafile> Use <datafile> for GPS data.\n" - " <image> JPEG file to use.\n"); + " -s Stitch mode.\n" + " -j <outfile> JPEG output file for Stitch mode.\n" + " -t <outdir> Output directory for TIFF images in Stitch mode.\n" + " <image(s)> JPEG file(s) to use.\n"); } Fl_Window * @@ -319,14 +334,17 @@ int main(int argc, char** argv) { char c, *sep, *tmp, **my_argv; char *view_point = NULL; int err, bflag = 0, dflag = 0, my_argc; + int stitch_flag = 0, stitch_w = 2000, stitch_h = 500; + int jpeg_flag = 0, tiff_flag = 0; + char *outpath; Fl_Window *control_win, *view_win; Fl_Scroll *scroll; err = 0; - while ((c = getopt(argc, argv, "d:v:")) != EOF) { + while ((c = getopt(argc, argv, "?d:v:sw:h:j:t:")) != EOF) { switch (c) { - case 'h': + case '?': usage(); exit(0); break; @@ -336,6 +354,23 @@ int main(int argc, char** argv) { case 'v': view_point = optarg; break; + case 's': + stitch_flag++; + break; + case 'j': + jpeg_flag++; + outpath = optarg; + break; + case 't': + tiff_flag++; + outpath = optarg; + break; + case 'w': + stitch_w = atoi(optarg); + break; + case 'h': + stitch_h = atoi(optarg); + break; default: err++; } @@ -354,6 +389,17 @@ int main(int argc, char** argv) { exit(1); } + if (stitch_flag) { + int type = STITCH_PREVIEW; + if (jpeg_flag) { + type = STITCH_JPEG; + } else if (tiff_flag) { + type = STITCH_TIFF; + } + stitch(stitch_w, stitch_h, type, outpath, my_argc, my_argv); + exit(0); + } + Fl::get_system_colors(); if (getenv("FLTK_SCHEME")) { Fl::scheme(NULL); @@ -398,3 +444,48 @@ int main(int argc, char** argv) { return Fl::run(); } + +static int stitch(int stitch_w, int stitch_h, int type, const char *path, int argc, char **argv) { + Fl_Window *win; + Fl_Scroll *scroll; + Stitch *st = new Stitch(); + + for (int i=0; i<argc; i++) { + st->load_image(argv[i]); + } + + if (type == STITCH_JPEG) { + + st->set_output((OutputImage*) new JPEGOutputImage(path, 90)); + st->resample(stitch_w, stitch_h, 0.0, 7.0); + + } else if (type == STITCH_TIFF) { + + for (int i=0; i<argc; i++) { + char buf[1024]; + char *dot; + + snprintf(buf, sizeof(buf), "%s/%s", path, argv[i]); + dot = strrchr(buf, '.'); + *dot = '\0'; + strncat(buf, ".tiff", sizeof(buf)); + + st->set_output(argv[i], (OutputImage*) new TIFFOutputImage(buf)); + } + + st->resample(stitch_w, stitch_h, 0.0, 7.0); + + } else { + win = new Fl_Window(0,0, stitch_w, stitch_h); + scroll = new Fl_Scroll(0, 0, win->w(), win->h()); + PreviewOutputImage *img = new PreviewOutputImage(0, 0, stitch_w, stitch_h); + win->resizable(scroll); + win->show(0, argv); + st->set_output((OutputImage*) img); + st->resample(stitch_w, stitch_h, 0.0, 7.0); + img->redraw(); + Fl::run(); + } + + return 0; +} |