gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master 64f8db5 080/125: ConvertType working except fo


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 64f8db5 080/125: ConvertType working except for text inputs and outputs
Date: Sun, 23 Apr 2017 22:36:42 -0400 (EDT)

branch: master
commit 64f8db5b8fa4796d5b7023aafc905f9b6fb57f8d
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    ConvertType working except for text inputs and outputs
    
    ConvertType has been mostly re-written to effectively use `gal_data_t' and
    all its added features in this branch. The only major visible changes
    are:
    
     - The log `--log' option is removed (since it was the same as the common
       option `--log' option). In practice, people can use the Arithmetic to
       get the log of the image and then convert that. It would be interesting
       to implement it, but for now, I don't have much time.
    
     - Until now, the 8-bit images were inverted by default and this behavior
       was disabled with the `--noinvert' option. Having a `no...' option is
       very confusing both for the users and the developers. So it was changed
       to `--invert' and by default, there is no inversion.
    
    Besides these, I also noticed that in some of the arithetic functions in
    particular, we were mistakenly setting the output pointer based on the
    input `void *' pointer, not based on the pointer to the proper type. This
    caused problems because arithmetic on `void *' is like arithmetic on `char'
    (1, not 8). So after an investigation, several such cases were corrected.
    
    For all the tests written so far, ConvertType works nicely, we just need to
    write library functions to read and write from text files to make the final
    two tests pass.
---
 bin/convertt/args.h           |  395 +++++----------
 bin/convertt/astconvertt.conf |   10 +-
 bin/convertt/convertt.c       |  430 ++++++++---------
 bin/convertt/eps.c            |  244 +++++-----
 bin/convertt/eps.h            |    2 +-
 bin/convertt/jpeg.c           |   97 ++--
 bin/convertt/jpeg.h           |    6 +-
 bin/convertt/main.c           |    6 +-
 bin/convertt/main.h           |  123 ++---
 bin/convertt/ui.c             | 1074 ++++++++++++++++++++++-------------------
 bin/convertt/ui.h             |    9 +-
 doc/gnuastro.texi             |   45 +-
 lib/arithmetic.c              |   48 +-
 lib/data.c                    |   30 ++
 lib/fits.c                    |    9 +-
 lib/gnuastro/data.h           |    3 +
 tests/convertt/blankch.sh     |    2 +-
 tests/convertt/fitstojpeg.sh  |    2 +-
 tests/convertt/fitstopdf.sh   |    2 +-
 tmpfs-config-make             |    6 +-
 20 files changed, 1231 insertions(+), 1312 deletions(-)

diff --git a/bin/convertt/args.h b/bin/convertt/args.h
index 71b0e4e..42a80ad 100644
--- a/bin/convertt/args.h
+++ b/bin/convertt/args.h
@@ -5,7 +5,7 @@ ConvertType is part of GNU Astronomy Utilities (Gnuastro) 
package.
 Original author:
      Mohammad Akhlaghi <address@hidden>
 Contributing author(s):
-Copyright (C) 2015, Free Software Foundation, Inc.
+Copyright (C) 2016, Free Software Foundation, Inc.
 
 Gnuastro is free software: you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
@@ -23,209 +23,183 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #ifndef ARGS_H
 #define ARGS_H
 
-#include <commonargs.h>
-#include <fixedstringmacros.h>
 
-#include "ui.h"
 
 
-/* Definition parameters for the argp: */
-const char *argp_program_version=SPACK_STRING"\n"GAL_STRINGS_COPYRIGHT
-  "\n\nWritten by Mohammad Akhlaghi";
-const char *argp_program_bug_address=PACKAGE_BUGREPORT;
-static char args_doc[] = "InputFile1 [InputFile2] ... [InputFile4]";
 
-
-
-
-
-const char doc[] =
-  /* Before the list of options: */
-  GAL_STRINGS_TOP_HELP_INFO
-  SPACK_NAME" will convert any of the known input formats to any other "
-  "of the known formats. The output file will have the same number of "
-  "pixels.\n"
-  GAL_STRINGS_MORE_HELP_INFO
-  /* After the list of options: */
-  "\v"
-  PACKAGE_NAME" home page: "PACKAGE_URL;
-
-
-
-
-
-/* Free letters for options:
-
-   d e f g j k p r s t v y z
-   A B E F G I J M O Q R T U W X Y Z
-
-   Free numbers: 503
-*/
-static struct argp_option options[] =
+/* Array of acceptable options. */
+struct argp_option program_options[] =
   {
-    {
-      0, 0, 0, 0,
-      "Operating modes:",
-      -1
-    },
-
-
-
-
-
-    {
-      0, 0, 0, 0,
-      "Input:",
-      1
-    },
-    {
-      "hdu2",
-      500,
-      "STR",
-      0,
-      "HDU of second input FITS image.",
-      1
-    },
-    {
-      "hdu3",
-      501,
-      "STR",
-      0,
-      "HDU of third input FITS image.",
-      1
-    },
-    {
-      "hdu4",
-      502,
-      "STR",
-      0,
-      "HDU of fourth input FITS image.",
-      1
-    },
-
-
-
-
-    {
-      0, 0, 0, 0,
-      "Output:",
-      2
-    },
+    /* Output */
     {
       "quality",
-      'u',
+      ARGS_OPTION_KEY_QUALITY,
       "INT",
       0,
       "Quality of output JPEG image (1 to 100).",
-      2
+      GAL_OPTIONS_GROUP_OUTPUT,
+      &p->quality,
+      GAL_DATA_TYPE_UCHAR,
+      GAL_OPTIONS_RANGE_GT_0,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
     },
     {
       "widthincm",
-      'w',
+      ARGS_OPTION_KEY_WIDTHINCM,
       "FLT",
       0,
       "Width in units of centimeters.",
-      2
+      GAL_OPTIONS_GROUP_OUTPUT,
+      &p->widthincm,
+      GAL_DATA_TYPE_FLOAT,
+      GAL_OPTIONS_RANGE_GT_0,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
     },
     {
       "borderwidth",
-      'b',
-      "FLT",
+      ARGS_OPTION_KEY_BORDERWIDTH,
+      "INT",
       0,
-      "Border width (EPS, PDF) in units of 1/72 inch.",
-      2
+      "EPS/PDF border width in units of 1/72 inch.",
+      GAL_OPTIONS_GROUP_OUTPUT,
+      &p->borderwidth,
+      GAL_DATA_TYPE_UINT,
+      GAL_OPTIONS_RANGE_GE_0,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
     },
     {
       "hex",
-      'x',
+      ARGS_OPTION_KEY_HEX,
       0,
       0,
       "Hexadecimal encoding in EPS. Default: ASCII85.",
-      2
+      GAL_OPTIONS_GROUP_OUTPUT,
+      &p->hex,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
     },
 
 
 
 
+
     {
       0, 0, 0, 0,
       "Flux:",
-      3
+      ARGS_GROUP_FLUX
     },
     {
       "fluxlow",
-      'L',
+      ARGS_OPTION_KEY_FLUXLOW,
       "FLT",
       0,
       "Lower flux truncation value.",
-      3
+      ARGS_GROUP_FLUX,
+      &p->fluxlowstr,
+      GAL_DATA_TYPE_STRING,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
     },
     {
       "fluxhigh",
-      'H',
+      ARGS_OPTION_KEY_FLUXHIGH,
       "FLT",
       0,
       "Higher flux truncation value.",
-      3
+      ARGS_GROUP_FLUX,
+      &p->fluxhighstr,
+      GAL_DATA_TYPE_STRING,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
     },
     {
       "maxbyte",
-      'm',
+      ARGS_OPTION_KEY_MAXBYTE,
       "INT",
       0,
       "Maximum byte value for all color channels.",
-      3
+      ARGS_GROUP_FLUX,
+      &p->maxbyte,
+      GAL_DATA_TYPE_UCHAR,
+      GAL_OPTIONS_RANGE_GE_0,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
     },
     {
       "flminbyte",
-      'i',
+      ARGS_OPTION_KEY_FLMINBYTE,
       0,
       0,
       "Set value of fluxlow as the minimum byte value.",
-      3
+      ARGS_GROUP_FLUX,
+      &p->flminbyte,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
     },
     {
       "fhmaxbyte",
-      'a',
+      ARGS_OPTION_KEY_FHMAXBYTE,
       0,
       0,
       "Set value of fluxhigh as the maximum byte value.",
-      3
+      ARGS_GROUP_FLUX,
+      &p->fhmaxbyte,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
     },
     {
       "change",
-      'c',
+      ARGS_OPTION_KEY_CHANGE,
       "STR",
       0,
       "Change pixel values `from_1:to_1,from_2:to_2`.",
-      3
+      ARGS_GROUP_FLUX,
+      &p->changestr,
+      GAL_DATA_TYPE_STRING,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
     },
     {
       "changeaftertrunc",
-      'C',
+      ARGS_OPTION_KEY_CHANGEAFTERTRUNC,
       0,
       0,
       "First truncate then change pixel values.",
-      3
+      ARGS_GROUP_FLUX,
+      &p->changeaftertrunc,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
     },
     {
-      "log",
-      'l',
+      "invert",
+      ARGS_OPTION_KEY_INVERT,
       0,
       0,
-      "Save flux in log scale.",
-      3
-    },
-    {
-      "noinvert",
-      'n',
-      0,
-      0,
-      "Don't invert the image.",
-      3
+      "Invert the values in JPEG and EPS/PDF.",
+      ARGS_GROUP_FLUX,
+      &p->invert,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
     },
 
 
+
     {0}
   };
 
@@ -233,172 +207,21 @@ static struct argp_option options[] =
 
 
 
+/* Define the child argp structure. */
+struct argp
+gal_options_common_child = {gal_commonopts_options,
+                            gal_options_common_argp_parse,
+                            NULL, NULL, NULL, NULL, NULL};
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/* Parse a single option: */
-static error_t
-parse_opt(int key, char *arg, struct argp_state *state)
+/* Use the child argp structure in list of children (only one for now). */
+struct argp_child
+children[]=
 {
-  int tmp;
-
-  /* Save the arguments structure: */
-  struct converttparams *p = state->input;
-
-  /* Set the pointer to the common parameters for all programs
-     here: */
-  state->child_inputs[0]=&p->cp;
-
-  /* In case the user incorrectly uses the equal sign (for example
-     with a short format or with space in the long format, then `arg`
-     start with (if the short version was called) or be (if the long
-     version was called with a space) the equal sign. So, here we
-     check if the first character of arg is the equal sign, then the
-     user is warned and the program is stopped: */
-  if(arg && arg[0]=='=')
-    argp_error(state, "incorrect use of the equal sign (`=`). For short "
-               "options, `=` should not be used and for long options, "
-               "there should be no space between the option, equal sign "
-               "and value");
-
-  switch(key)
-    {
-
-    /* Input:  */
-    case 500:
-      gal_checkset_allocate_copy_set(arg, &p->up.hdu2, &p->up.hdu2set);
-      break;
-    case 501:
-      gal_checkset_allocate_copy_set(arg, &p->up.hdu3, &p->up.hdu3set);
-      break;
-    case 502:
-      gal_checkset_allocate_copy_set(arg, &p->up.hdu4, &p->up.hdu4set);
-      break;
-
-
-    /* Output: */
-    case 'w':
-      gal_checkset_float_l_0(arg, &p->widthincm, "widthincm", key, p->cp.spack,
-                             NULL, 0);
-      p->up.widthincmset=1;
-      break;
-    case 'b':
-      gal_checkset_int_el_zero(arg, &p->borderwidth, "borderwidth", key,
-                               p->cp.spack, NULL, 0);
-      p->up.borderwidthset=1;
-      break;
-    case 'u':
-      gal_checkset_int_smaller_equal_to(arg, &p->quality, "quality", key,
-                                        p->cp.spack, NULL, 0, 100);
-      if(p->quality<0)
-        error(EXIT_FAILURE, 0, "the quality option should be positive");
-      p->up.qualityset=1;
-      break;
-    case 'x':
-      p->hex=1;
-      break;
-
-
-
-    /* Flux: */
-    case 'L':
-      gal_checkset_any_double(arg, &p->fluxlow, "fluxlow", key, p->cp.spack, 
NULL, 0);
-      p->up.fluxlowset=1;
-      break;
-    case 'H':
-      gal_checkset_any_double(arg, &p->fluxhigh, "fluxhigh", key, p->cp.spack, 
NULL, 0);
-      p->up.fluxhighset=1;
-      break;
-    case 'm':
-      gal_checkset_int_smaller_equal_to(arg, &tmp, "maxbyte", key,
-                                        p->cp.spack, NULL, 0, UINT8_MAX);
-      if(tmp<0) error(EXIT_FAILURE, 0, "--maxbyte (-m) should be positive");
-      p->maxbyte=tmp;
-      p->up.maxbyteset=1;
-      break;
-    case 'i':
-      p->flminbyte=1;
-      break;
-    case 'a':
-      p->fhmaxbyte=1;
-      break;
-    case 'c':
-      p->change=makechangestruct(arg);
-      break;
-    case 'C':
-      p->changeaftertrunc=1;
-      break;
-    case 'l':
-      p->log=1;
-      break;
-    case 'n':
-      p->invert=0;
-      break;
-
-
-    /* Read the non-option arguments: */
-    case ARGP_KEY_ARG:
-      gal_linkedlist_add_to_stll(&p->inputnames, arg);
-      ++p->numinputs;
-      break;
-
-
-
-
-
-
-    /* The command line options and arguments are finished. */
-    case ARGP_KEY_END:
-      if(p->cp.setdirconf==0 && p->cp.setusrconf==0
-         && p->cp.printparams==0)
-        {
-          if(state->arg_num==0)
-            argp_error(state, "no argument given");
-          if(p->inputnames==NULL)
-            argp_error(state, "no input files provided");
-        }
-      break;
-
-
-
-
-
-
-    default:
-      return ARGP_ERR_UNKNOWN;
-    }
-  return 0;
-}
-
-
-
-
-
-/* Specify the children parsers: */
-struct argp_child children[]=
-  {
-    {&commonargp, 0, NULL, 0},
-    {0, 0, 0, 0}
-  };
-
-
-
-
-
-/* Basic structure defining the whole argument reading process. */
-static struct argp thisargp = {options, parse_opt, args_doc,
-                               doc, children, NULL, NULL};
+  {&gal_options_common_child, 0, NULL, 0},
+  {0, 0, 0, 0}
+};
 
+/* Set all the necessary argp parameters. */
+struct argp
+thisargp = {program_options, parse_opt, args_doc, doc, children, NULL, NULL};
 #endif
diff --git a/bin/convertt/astconvertt.conf b/bin/convertt/astconvertt.conf
index 3d88b26..f0072bb 100644
--- a/bin/convertt/astconvertt.conf
+++ b/bin/convertt/astconvertt.conf
@@ -19,9 +19,6 @@
 
 # Input:
  hdu                  0
- hdu2                 0
- hdu3                 0
- hdu4                 0
 
 # Output:
  quality              100
@@ -30,6 +27,7 @@
  output               jpg
 
 # Flux:
- fluxlow              0.0
- fluxhigh             0.0
- maxbyte              255
+ invert               0
+
+# Common options
+ minmapsize           1000000000
\ No newline at end of file
diff --git a/bin/convertt/convertt.c b/bin/convertt/convertt.c
index 850bfc7..0952254 100644
--- a/bin/convertt/convertt.c
+++ b/bin/convertt/convertt.c
@@ -31,7 +31,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <gnuastro/fits.h>
 #include <gnuastro/txtarray.h>
-#include <gnuastro/statistics.h>
+#include <gnuastro/arithmetic.h>
 
 #include <timing.h>
 
@@ -41,129 +41,109 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include "eps.h"
 
 
+
+
+
+
+
+
+
+
 /**************************************************************/
 /**************      Modifying pixel values     ***************/
 /**************************************************************/
-void
-changevalue(struct converttparams *p)
+static void
+convertt_change(struct converttparams *p)
 {
-  struct change *tmp, *ttmp;
-  size_t numchange=0, i, j, size;
-  double *from, *to, **ch=p->ch, *d, *df, f, t;
+  gal_data_t *channel, *cond;
+  struct change *change, *tmp;
+  unsigned char flags = ( GAL_ARITHMETIC_NUMOK
+                          | GAL_ARITHMETIC_FREE
+                          | GAL_ARITHMETIC_INPLACE );
 
   /* In case there is no value to convert. */
   if(p->change==NULL) return;
 
-  /* Count the number of conversions, allocate the arrays for them
-     and put the conversion values in it. */
-  for(tmp=p->change;tmp!=NULL;tmp=tmp->next) ++numchange;
-  errno=0;
-  to=malloc(numchange*sizeof *to);
-  from=malloc(numchange*sizeof *from);
-  if(to==NULL || from==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for `to` or `from` in convert",
-          numchange*sizeof *from);
-  i=1;
-  tmp=p->change;
-  while(tmp!=NULL)
-    {
-      to[numchange-i]=tmp->to;
-      from[numchange-i]=tmp->from;
-      ttmp=tmp->next;
-      free(tmp);
-      tmp=ttmp;
-      ++i;
-    }
-
-  /* Convert the pixel values in the given order: */
-  size=p->s0[0]*p->s1[0];
-  for(i=0;i<p->numch;++i)
-    {
-      if(p->isblank[i]) continue;
-      for(j=0;j<numchange;++j)
-        {
-          f=from[j]; t=to[j];
-          df=(d=ch[i])+size;
-          do *d = (*d==f) ? t : *d; while(++d<df);
-        }
-    }
+  /* Do the conversion on all channels for each change. */
+  for(change=p->change; change!=NULL; change=change->next)
+    for(channel=p->chll; channel!=NULL; channel=channel->next)
+      {
+        /* Make a condition array: all pixels with a value equal to
+           `change->from' will be set as 1 in this array. */
+        cond=gal_arithmetic(GAL_ARITHMETIC_OP_EQ, GAL_ARITHMETIC_NUMOK,
+                            channel, change->from);
+
+        /* Now, use the condition array to set the proper values. */
+        channel=gal_arithmetic(GAL_ARITHMETIC_OP_WHERE, flags, channel,
+                               cond, change->to);
+
+        /* Clean up, since we set the free flag, all extra arrays have been
+           freed.*/
+        gal_data_free(cond);
+        gal_data_free(change->from);
+      }
 
-  free(to);
-  free(from);
+  /* Free the channels linked list. */
+  change=p->change;
+  while(change!=NULL) { tmp=change->next; free(change); change=tmp; }
 }
 
 
 
 
-
-void
-truncateflux(struct converttparams *p)
+static void
+convertt_trunc_function(int operator, gal_data_t *data, gal_data_t *value)
 {
-  size_t i, size;
-  double *d, *df, **ch=p->ch;
-  double fluxlow=p->fluxlow, fluxhigh=p->fluxhigh;
+  gal_data_t *cond, *out;
 
-  /* If the flux truncation values are equal, there is no truncation.*/
-  if(fluxlow==fluxhigh) return;
 
-  size=p->s0[0]*p->s1[0];
-  for(i=0;i<p->numch;++i)
-    {
-      if(p->isblank[i]) continue;
-      df=(d=ch[i])+size;
-      do
-        {
-          if(*d<fluxlow) *d=fluxlow;
-          if(*d>fluxhigh) *d=fluxhigh;
-        }
-      while(++d<df);
-    }
-}
+  /* Note that we need the fluxlow and fluxhigh values later. */
+  unsigned char flags = ( GAL_ARITHMETIC_NUMOK | GAL_ARITHMETIC_INPLACE );
 
 
+  /* Make a condition array: all pixels with a value equal to
+     `change->from' will be set as 1 in this array. */
+  cond=gal_arithmetic(operator, GAL_ARITHMETIC_NUMOK, data, value);
 
 
+  /* Now, use the condition array to set the proper values. */
+  out=gal_arithmetic(GAL_ARITHMETIC_OP_WHERE, flags, data, cond, value);
 
-/* Change the array to the logarithm of the array.
 
-   Note that the logarithm of a zero or negative value is not
-   defined. We assume here that the full range of flux is desired. So
-   if the minimum value in the array is zero or negative, all the
-   elements of the array are added to a constant such that the minimum
-   value is only slightly larger than zero. The "slight"ness is
-   defined in terms of the distance between the minimum and maximum
-   for each color channel.*/
-void
-takelog(struct converttparams *p)
-{
-  size_t i, size;
-  double **ch=p->ch;
-  double min, max, toadd, *d, *df;
-
-  size=p->s0[0]*p->s1[0];
-  for(i=0;i<p->numch;++i)
-    {
-      gal_statistics_d_min_max(ch[i], size, &min, &max);
-      if(p->isblank[i]) continue;
-      if(min<=0.0f)
-        {
-          toadd=-1.0*min+(max-min)/10000.0f;
-          df=(d=ch[i])+size;
-          do *d+=toadd; while(++d<df);
-        }
-      df=(d=ch[i])+size;
-      do *d=log10(*d); while(++d<df);
-    }
-}
+  /* A small sanity check. The process must be in-place so the original
+     data structure must not have changed. */
+  if(out!=data)
+    error(EXIT_FAILURE, 0, "a bug! please contact us at %s to solve the "
+          "problem. The `out' and `data' pointers in "
+          "`convertt_trunc_function' are not equal", PACKAGE_BUGREPORT);
 
 
+  /* Clean up. */
+  gal_data_free(cond);
+}
 
 
 
 
 
+static void
+convertt_truncate(struct converttparams *p)
+{
+  gal_data_t *channel;
 
+  /* Return if no truncation is desired. */
+  if(p->fluxhigh==NULL && p->fluxlow==NULL)
+    return;
 
+  /* Do the truncation for each channel. */
+  for(channel=p->chll; channel!=NULL; channel=channel->next)
+    {
+      if(p->fluxlow)
+        convertt_trunc_function(GAL_ARITHMETIC_OP_LT, channel, p->fluxlow);
+      if(p->fluxhigh)
+        convertt_trunc_function(GAL_ARITHMETIC_OP_GT, channel, p->fluxhigh);
+    }
+}
 
 
 
@@ -175,64 +155,39 @@ takelog(struct converttparams *p)
 
 
 
-/**************************************************************/
-/**************       Save text and FITS        ***************/
-/**************************************************************/
-void
-savetxt(struct converttparams *p)
-{
-  char comments[10000];
-  int iprec[]={0, 8}, fprec[]={6, 8};
-  int int_cols[]={-1}, accu_cols[]={-1};
-  int ispace[]={1, 10, 15}, fspace[]={1, 15, 15};
 
 
-  /* Find the input file name and  */
-  sprintf(comments, "# Pixel values of %s (%zu x %zu pixels).\n"
-          "# Created on %s# %s", p->names[0], p->s0[0], p->s1[0],
-          ctime(&p->rawtime), SPACK_STRING);
 
-  if(p->bitpixs[0]==BYTE_IMG || p->bitpixs[0]==SHORT_IMG
-     || p->bitpixs[0]==LONG_IMG || p->bitpixs[0]==LONGLONG_IMG )
-    gal_txtarray_array_to_txt(p->ch[0], p->s0[0], p->s1[0], comments, int_cols,
-                              accu_cols, ispace, iprec, 'f', p->cp.output);
-  else
-    gal_txtarray_array_to_txt(p->ch[0], p->s0[0], p->s1[0], comments, int_cols,
-                              accu_cols, fspace, fprec, 'g', p->cp.output);
 
-}
 
 
 
 
 
+/**************************************************************/
+/**************       Save text and FITS        ***************/
+/**************************************************************/
 void
-savefits(struct converttparams *p)
+save_with_gnuastro_lib(struct converttparams *p)
 {
-  void *array;
-  size_t i, size;
-  char hdu[1000];
-
-  size=p->s0[0]*p->s1[0];
-  for(i=0;i<p->numch;++i)
-    {
-      /* Make sure array is in the correct format. */
-      if(p->bitpixs[i]!=DOUBLE_IMG)
-        gal_fits_change_type(p->ch[i], DOUBLE_IMG, size, p->numnul[i],
-                                  &array, p->bitpixs[i]);
-      else
-        array=p->ch[i];
+  gal_data_t *channel;
 
-      /* Write array to a FITS file.*/
-      sprintf(hdu, "Channel%zu", i+1);
-      gal_fits_array_to_file(p->cp.output, hdu, p->bitpixs[i], array,
-                             p->s0[i], p->s1[i], 0, NULL, NULL,
-                             SPACK_STRING);
-
-      /* If array was allocated separately, free it. */
-      if(p->bitpixs[i]!=DOUBLE_IMG)
-        free(array);
-    }
+  for(channel=p->chll; channel!=NULL; channel=channel->next)
+    switch(p->outformat)
+      {
+      case OUT_FORMAT_FITS:
+        gal_fits_write_img(channel, p->cp.output, NULL, PROGRAM_STRING);
+        break;
+
+      case OUT_FORMAT_TXT:
+        printf("\n... in save_with_gnuastro_lib ...\n");
+        exit(1);
+        break;
+
+      default:
+        error(EXIT_FAILURE, 0, "a bug! output format code `%d' not "
+              "recognized in `save_with_gnuastro_lib'", p->outformat);
+      }
 }
 
 
@@ -258,97 +213,122 @@ savefits(struct converttparams *p)
 /**************       convert to 8 bit          ***************/
 /**************************************************************/
 void
-doubleto8bit(struct converttparams *p)
+convertt_scale_to_uchar(struct converttparams *p)
 {
-  size_t i, size, numch=p->numch;
-  uint8_t *u, *fu, **ech=p->ech, maxbyte=p->maxbyte;
-  double *d, m, tmin, tmax, min=FLT_MAX, max=-FLT_MAX;
+  size_t size=p->chll->size;
+  unsigned char *u, *fu, maxbyte=p->maxbyte;
+  gal_data_t *channel, *prev, *copied, *mind, *maxd;
+  float *f, *ff, m, tmin, tmax, min=FLT_MAX, max=-FLT_MAX;
 
-  /* Allocate space for all the channels. */
-  size=p->s0[0]*p->s1[0];
-  for(i=0;i<numch;++i)
-    {
-      errno=0;
-      ech[i]=malloc(size*sizeof *ech[i]);
-      if(ech[i]==NULL)
-        error(EXIT_FAILURE, errno, "%zu bytes for ech[%zu]",
-              size*sizeof *ech[i], i);
-    }
 
-  /* Find the minimum and maximum of all the color channels. */
-  for(i=0;i<numch;++i)
+  /* Convert everything to single precision floating point type and find
+     the minimum and maximum values of all the channels in the process. */
+  prev=NULL;
+  for(channel=p->chll; channel!=NULL; channel=channel->next)
     {
-      gal_statistics_d_min_max(p->ch[i], size, &tmin, &tmax);
-      if(i)
+      /* Only for channels that weren't originally blank. */
+      if(channel->status==0)
         {
+          /* If the type isn't float, then convert it to float. */
+          if(channel->type!=GAL_DATA_TYPE_FLOAT)
+            {
+              /* Change the type to float. */
+              copied=gal_data_copy_to_new_type(channel, GAL_DATA_TYPE_FLOAT);
+
+              /* Correct the pointers. */
+              copied->next=channel->next;
+              if(prev) prev->next=copied; else p->chll=copied;
+
+              /* Clean the old data structure and put in the new one */
+              gal_data_free(channel);
+              channel=copied;
+            }
+
+          /* Calculate the minimum and maximum. */
+          mind = gal_arithmetic(GAL_ARITHMETIC_OP_MINVAL, 0, channel);
+          maxd = gal_arithmetic(GAL_ARITHMETIC_OP_MAXVAL, 0, channel);
+          tmin = *((float *)(mind->array));
+          tmax = *((float *)(maxd->array));
+          gal_data_free(mind);
+          gal_data_free(maxd);
+
+          /* See the over-all minimum and maximum values. */
           if(tmin<min) min=tmin;
           if(tmax>max) max=tmax;
-          continue;
         }
-      min=tmin;
-      max=tmax;
-    }
 
-  /* Change the minimum and maximum if desired, Note that this
-     is only non-redundant when fluxhigh and fluxlow are more
-     or less than the maximum and minimum values in the
-     image.*/
-  if(p->fluxlow!=p->fluxhigh)
-    {
-      if(p->flminbyte) min=p->fluxlow;
-      if(p->fhmaxbyte) max=p->fluxhigh;
+      /* Set the prev pointer. */
+      prev=channel;
     }
-  m=(double)maxbyte/(max-min);
 
-  /* Write the values in the array: */
-  for(i=0;i<numch;++i)
+
+  /* Change the minimum and maximum if desired, Note that this is only
+     non-redundant when fluxhigh and fluxlow are more or less than the
+     maximum and minimum values in the image.*/
+  if(p->fluxlow || p->fluxhigh)
     {
-      if(p->isblank[i])
+      if(p->flminbyte)
         {
-          if(numch==3)          /* RGB  */
-            {fu=(u=ech[i])+size; do *u=0; while(++u<fu);}
-          else if(numch==4)     /* CMYK */
-            {fu=(u=ech[i])+size; do *u=UINT8_MAX; while(++u<fu);}
-          else error(EXIT_FAILURE, 0, "a bug! The number of channels in "
-                     "doubleto8bit is not 3 or 4 when there is a blank "
-                     "channel, this should not happen. Please contact us "
-                     "So we can fix it");
+          /* Convert the fluxlow value to float and put it in min. */
+          copied=gal_data_copy_to_new_type(p->fluxlow, GAL_DATA_TYPE_FLOAT);
+          min = *((float *)(copied->array));
+          gal_data_free(copied);
         }
-      else
+      if(p->fhmaxbyte)
         {
-          d=p->ch[i];
-          fu=(u=ech[i])+size;
+          /* Convert the fluxhigh value to float and put it in min. */
+          copied=gal_data_copy_to_new_type(p->fluxhigh, GAL_DATA_TYPE_FLOAT);
+          max = *((float *)(copied->array));
+          gal_data_free(copied);
+        }
+    }
+  m=(float)maxbyte/(max-min);
+
+
+
+  /* Convert all the non-blank channels to unsigned char. */
+  prev=NULL;
+  for(channel=p->chll; channel!=NULL; channel=channel->next)
+    {
+      if(channel->status==0)
+        {
+          /* Convert the values into a range between `0' and `maxbyte'. */
+          ff=(f=channel->array)+size;
           if(p->invert)
             {
               do
-                {
-                  *u = isnan(*d) ? maxbyte : maxbyte-(*d-min)*m;
-                  ++d;
-                }
-              while(++u<fu);
+                *f = isnan(*f) ? maxbyte : maxbyte-(*f-min)*m;
+              while(++f<ff);
             }
           else
             {
               do
-                {
-                  *u = isnan(*d) ? 0 : (*d-min)*m;
-                  ++d;
-                }
-              while(++u<fu);
+                *f = isnan(*f) ? 0 : (*f-min)*m;
+              while(++f<ff);
             }
+
+          /* Change the type to unsigned char. */
+          copied=gal_data_copy_to_new_type(channel, GAL_DATA_TYPE_UCHAR);
+
+          /* Correct the pointers. */
+          copied->next=channel->next;
+          if(prev) prev->next=copied; else p->chll=copied;
+
+          /* Clean the old data structure and put in the new one */
+          gal_data_free(channel);
+          channel=copied;
+        }
+      else
+        {
+          /* In CMYK, a blank channel should have a maximum value. */
+          if(p->numch==4)
+            {fu=(u=channel->array)+size; do *u=UINT8_MAX; while(++u<fu);}
         }
+
+      /* Set the prev pointer. */
+      prev=channel;
+
     }
-  /* Check all channels (practical for a small input file).
-  {
-    size_t j;
-    for(j=0;j<size;++j)
-      {
-        for(i=0;i<numch;++i)
-          printf("%d:", (int)p->ech[i][j]);
-        printf("\b.\n");
-      }
-  }
-  */
 }
 
 
@@ -375,36 +355,32 @@ doubleto8bit(struct converttparams *p)
 void
 convertt(struct converttparams *p)
 {
-  size_t i;
-
   /* Make any of the desired changes to the data. */
   if(p->changeaftertrunc)
     {
-      truncateflux(p);
-      changevalue(p);
+      convertt_truncate(p);
+      convertt_change(p);
     }
   else
     {
-      changevalue(p);
-      truncateflux(p);
+      convertt_change(p);
+      convertt_truncate(p);
     }
-  if(p->log) takelog(p);
 
 
 
   /* Save the outputs: */
-  switch(p->outputtype)
+  switch(p->outformat)
     {
-    case TXTFORMAT:
-      savetxt(p);
+    case OUT_FORMAT_TXT:
+    case OUT_FORMAT_FITS:
+      save_with_gnuastro_lib(p);
       break;
-    case FITSFORMAT:
-      savefits(p);
-      break;
-    case JPEGFORMAT:
-      doubleto8bit(p);
+
+    case OUT_FORMAT_JPEG:
 #ifdef HAVE_LIBJPEG
-      savejpeg(p);
+      convertt_scale_to_uchar(p);
+      jpeg_write(p);
 #else
       error(EXIT_FAILURE, 0, "you have asked for a JPEG output, however, "
             "when %s was configured libjpeg was not available. To write "
@@ -413,18 +389,16 @@ convertt(struct converttparams *p)
             PACKAGE_STRING);
 #endif
       break;
-    case EPSFORMAT: case PDFFORMAT:
-      doubleto8bit(p);
-      saveepsorpdf(p);
+
+    case OUT_FORMAT_EPS:
+    case OUT_FORMAT_PDF:
+      convertt_scale_to_uchar(p);
+      eps_write_eps_or_pdf(p);
       break;
+
     default:
       error(EXIT_FAILURE, 0, "a bug! The internal type of the output is "
             "not recognized. Please contact us so we can find the problem "
             "and fix it");
     }
-
-  /* Free the ech arrays. Note that if they have not been
-     allocated, they are NULL and free won't complain. */
-  for(i=0;i<p->numch;++i)
-    free(p->ech[i]);
 }
diff --git a/bin/convertt/eps.c b/bin/convertt/eps.c
index 336ab9e..3eebfcf 100644
--- a/bin/convertt/eps.c
+++ b/bin/convertt/eps.c
@@ -122,18 +122,31 @@ nameispdfsuffix(char *name)
 /*************************************************************
  **************       Write an EPS image        **************
  *************************************************************/
-int
-onlytwovalues(struct converttparams *p)
+static int
+eps_is_binary(struct converttparams *p)
 {
-  uint8_t *i, *fi;
+  gal_data_t *channel;
+  unsigned char *i, *fi;
 
-  fi=(i=p->ech[0])+p->s0[0]*p->s1[0];
-  do
-    if(*i!=UINT8_MAX && *i!=0) break;
-  while(++i<fi);
+  /* Go through all the channels. */
+  for(channel=p->chll; channel!=NULL; channel=channel->next)
+    {
+      /* Go through all the values and see they are 0 and break out of the
+         loop as soon as you get to a pixel that is not 0 or `maxbyte'. */
+      fi = (i=p->chll->array) + p->chll->size;
+      do
+        if(*i!=p->maxbyte && *i!=0) break;
+      while(++i<fi);
+
+      /* If we didn't get to the end of the channel, then we have a
+         non-binary image. */
+      if(i!=fi)
+        return 0;
+    }
 
-  if(i==fi) return 1;
-  else      return 0;
+  /* If we get to this point, then all the channels were binary, so return
+     success. */
+  return 1;
 }
 
 
@@ -144,13 +157,13 @@ onlytwovalues(struct converttparams *p)
    test in debugging problems with blackandwhite. To test it use a
    very small valued input to make the outputs reasonable. For example
    I am now testing it with an input text array of 12 elements (while
-   calling the --noinvert option):
+   calling the --invert option):
 
    1 0 1 0 0 0
    0 0 0 1 0 1
 */
 void
-showbits(uint8_t x)
+eps_show_bits(uint8_t x)
 {
   int i;
 
@@ -164,49 +177,57 @@ showbits(uint8_t x)
 
 
 
-/* Convert p->ech[0] into a 0 and 1 bit stream since it only has two
-   values. NOTE: each row has to have an integer number of bytes. */
+/* Convert the channels into into a 0 and 1 bit stream. This function is
+   only called when the image is binary (has only two values). NOTE: each
+   row has to have an integer number of bytes, so when the number of pixels
+   in a row is not a multiple of 8, we'll add one. */
 size_t
-blackandwhite(struct converttparams *p)
+eps_convert_to_bitstream(struct converttparams *p)
 {
-  size_t i, j, k;
-  uint8_t *bits, byte, curbit, *ech=p->ech[0];
-  size_t s0=p->s0[0], s1=p->s1[0], bytesinrow, bytesinimg;
-
-  /* Find the size values: */
-  if(p->s1[0]%8) bytesinrow = s1/8 + 1;
-  else           bytesinrow = s1/8;
-  bytesinimg=bytesinrow*s0;
-
-  /* Allocate the array. */
-  errno=0;
-  bits=calloc(bytesinimg, sizeof *bits);
-  if(bits==NULL)
-    error(EXIT_FAILURE, errno, "allocating %zu bytes in blackandwhite",
-          bytesinimg);
-
-  for(i=0;i<s0;++i)
+  gal_data_t *channel;
+  size_t i, j, k, bytesinrow, bytesinimg;
+  unsigned char *bits, byte, curbit, *in;
+  size_t s0=p->chll->dsize[0], s1=p->chll->dsize[1];
+
+  /* Find the size values and allocate the array. */
+  if( s1 % 8 ) bytesinrow = s1/8 + 1;
+  else         bytesinrow = s1/8;
+  bytesinimg = bytesinrow*s0;
+
+  /* Go over all the channels. */
+  for(channel=p->chll; channel!=NULL; channel=channel->next)
     {
-      for(j=0;j<bytesinrow;++j)
-        {                  /* i*s0+j is the byte, not bit position. */
-          byte=0;          /* Set the 8 bits to zero.               */
-          curbit=0x80;     /* Current bit position, starting at:    */
-          for(k=0;k<8;++k)
-            {
-              if( j*8+k < s1 )
+      /* Allocate the array. */
+      bits=gal_data_malloc_array(GAL_DATA_TYPE_UCHAR, bytesinimg);
+
+      /* Put the values in. */
+      in=channel->array;
+      for(i=0;i<s0;++i)
+        {
+          for(j=0;j<bytesinrow;++j)
+            {                  /* i*s0+j is the byte, not bit position. */
+              byte=0;          /* Set the 8 bits to zero.               */
+              curbit=0x80;     /* Current bit position, starting at:    */
+              for(k=0;k<8;++k)
                 {
-                  if(ech[i*s1+j*8+k])
-                    byte |= curbit;
-                  curbit >>= 1;
+                  if( j*8+k < s1 )
+                    {
+                      if(in[i*s1+j*8+k])
+                        byte |= curbit;
+                      curbit >>= 1;
+                    }
+                  else break;
                 }
-              else break;
+              /*eps_show_bits(byte);*/
+              bits[i*bytesinrow+j]=byte;
             }
-          /*showbits(byte);*/
-          bits[i*bytesinrow+j]=byte;
         }
+      free(channel->array);
+      channel->array=bits;
+      channel->type=GAL_DATA_TYPE_BIT;
     }
-  free(p->ech[0]);
-  p->ech[0]=bits;
+
+  /* Return the total number of bytes in the image. */
   return bytesinimg;
 }
 
@@ -215,23 +236,24 @@ blackandwhite(struct converttparams *p)
 
 
 void
-channelsinhex(struct converttparams *p, FILE *fp, size_t size)
+eps_write_hex(struct converttparams *p, FILE *fp, size_t size)
 {
-  uint8_t *ech;
-  size_t i, j, numelem=35;
+  unsigned char *in;
+  gal_data_t *channel;
+  size_t i, elem_for_newline=35;
 
-  for(i=0;i<p->numch;++i)
+  for(channel=p->chll; channel!=NULL; channel=channel->next)
     {
-      if(p->isblank[i])
+      if(channel->status)       /* A blank channel has status==1. */
         fprintf(fp, "{<00>} %% Channel %zu is blank\n", i);
       else
         {
-          ech=p->ech[i];
+          in=channel->array;
           fprintf(fp, "{<");
-          for(j=0;j<size;++j)
+          for(i=0;i<size;++i)
             {
-              fprintf(fp, "%02X", ech[j]);
-              if(j%numelem==0) fprintf(fp, "\n");
+              fprintf(fp, "%02X", in[i]);
+              if(i%elem_for_newline==0) fprintf(fp, "\n");
             }
           fprintf(fp, ">}\n");
         }
@@ -243,32 +265,33 @@ channelsinhex(struct converttparams *p, FILE *fp, size_t 
size)
 
 
 void
-channelsinascii85(struct converttparams *p, FILE *fp, size_t size)
+eps_write_ascii85(struct converttparams *p, FILE *fp, size_t size)
 {
-  uint8_t *ech;
+  unsigned char *in;
+  gal_data_t *channel;
   uint32_t anint, base;
-  size_t i, j, k, numelem=15;   /* 15*5=75 */
+  size_t i, j, elem_for_newline=15;   /* 15*5=75 */
 
-  for(i=0;i<p->numch;++i)
+  for(channel=p->chll; channel!=NULL; channel=channel->next)
     {
-      if(p->isblank[i])
+      if(channel->status)
         fprintf(fp, "{<00>} %% Channel %zu is blank\n", i);
       else
         {
-          ech=p->ech[i];
+          in=channel->array;
           fprintf(fp, "{<~");
-          for(j=0;j<size;j+=4)
+          for(i=0;i<size;i+=4)
             {
               /* This is the last four bytes */
-              if(size-j<4)
+              if(size-i<4)
                 {
-                  anint=ech[j]*256*256*256;
-                  if(size-j>1)  anint+=ech[j+1]*256*256;
-                  if(size-j==3) anint+=ech[j+2]*256;
+                  anint=in[i]*256*256*256;
+                  if(size-i>1)  anint+=in[i+1]*256*256;
+                  if(size-i==3) anint+=in[i+2]*256;
                 }
               else
-                anint=( ech[j]*256*256*256 + ech[j+1]*256*256
-                        + ech[j+2]*256     + ech[j+3] );
+                anint=( in[i]*256*256*256 + in[i+1]*256*256
+                        + in[i+2]*256     + in[i+3]         );
 
               /* If all four bytes are zero, then just print `z'. */
               if(anint==0) fprintf(fp, "z");
@@ -276,12 +299,12 @@ channelsinascii85(struct converttparams *p, FILE *fp, 
size_t size)
                 {
                   /* To check, just change the fprintf below to printf:
                      printf("\n\n");
-                     printf("%u %u %u %u\n", ech[j], ech[j+1],
-                            ech[j+2], ech[j+3]);
+                     printf("%u %u %u %u\n", in[i], in[i+1],
+                            in[i+2], in[i+3]);
                   */
                   base=85*85*85*85;
                   /* Do the ASCII85 encoding: */
-                  for(k=0;k<5;++k)
+                  for(j=0;j<5;++j)
                     {
                       fprintf(fp, "%c", anint/base+33);
                       anint%=base;
@@ -289,7 +312,7 @@ channelsinascii85(struct converttparams *p, FILE *fp, 
size_t size)
                     }
                 }
               /* Go to the next line if on the right place: */
-              if(j%numelem==0) fprintf(fp, "\n");
+              if(i%elem_for_newline==0) fprintf(fp, "\n");
             }
           fprintf(fp, "~>}\n");
         }
@@ -300,40 +323,43 @@ channelsinascii85(struct converttparams *p, FILE *fp, 
size_t size)
 
 
 
-void
-writeepsimage(struct converttparams *p, FILE *fp)
+static void
+eps_write_image(struct converttparams *p, FILE *fp)
 {
   int bpc=8;
-  size_t i, size;
+  size_t i, size, *dsize=p->chll->dsize;
 
   /* Set the number of bits per component. */
-  if( p->numch==1 && onlytwovalues(p) )
+  if( p->numch==1 && eps_is_binary(p) )
     {
       bpc=1;
-      size=blackandwhite(p);
+      size=eps_convert_to_bitstream(p);
     }
-  else size=p->s0[0]*p->s1[0];
+  else size=p->chll->size;
 
-  if(p->numch==1)      fprintf(fp, "/DeviceGray setcolorspace\n");
-  else if(p->numch==3) fprintf(fp, "/DeviceRGB setcolorspace\n");
-  else if(p->numch==4) fprintf(fp, "/DeviceCMYK setcolorspace\n");
-  else
-    error(EXIT_FAILURE, 0, "a bug! In saveepsorpdf the number of channels "
-          "is not 1, 3 or 4. Please contact us so we can find the issue "
-          "and fix it");
+  switch(p->numch)
+    {
+    case 1: fprintf(fp, "/DeviceGray setcolorspace\n"); break;
+    case 3: fprintf(fp, "/DeviceRGB setcolorspace\n");  break;
+    case 4: fprintf(fp, "/DeviceCMYK setcolorspace\n"); break;
+    default:
+      error(EXIT_FAILURE, 0, "a bug! In saveepsorpdf the number of channels "
+            "is not 1, 3 or 4. Please contact us so we can find the issue "
+            "and fix it");
+    }
   fprintf(fp, "<<\n");
   fprintf(fp, "  /ImageType 1\n");
-  fprintf(fp, "  /Width %zu\n", p->s1[0]);
-  fprintf(fp, "  /Height %zu\n", p->s0[0]);
-  fprintf(fp, "  /ImageMatrix [ %zu 0 0 %zu 0 0 ]\n", p->s1[0], p->s0[0]);
+  fprintf(fp, "  /Width %zu\n", dsize[1]);
+  fprintf(fp, "  /Height %zu\n", dsize[0]);
+  fprintf(fp, "  /ImageMatrix [ %zu 0 0 %zu 0 0 ]\n", dsize[1], dsize[0]);
   fprintf(fp, "  /MultipleDataSources true\n");
   fprintf(fp, "  /BitsPerComponent %d\n", bpc);
   fprintf(fp, "  /Decode[");
   for(i=0;i<p->numch;++i) {fprintf(fp, " 0 1");} fprintf(fp, " ]\n");
   fprintf(fp, "  /Interpolate false\n");
   fprintf(fp, "  /DataSource [\n");
-  if(p->hex) channelsinhex(p, fp, size);
-  else channelsinascii85(p, fp, size);
+  if(p->hex) eps_write_hex(p, fp, size);
+  else eps_write_ascii85(p, fp, size);
   fprintf(fp, "  ]\n");
   fprintf(fp, ">>\n");
   fprintf(fp, "image\n\n");
@@ -343,39 +369,36 @@ writeepsimage(struct converttparams *p, FILE *fp)
 
 
 void
-saveepsorpdf(struct converttparams *p)
+eps_write_eps_or_pdf(struct converttparams *p)
 {
   FILE *fp;
   float hbw;
-  size_t winpt, hinpt;
   char command[20000], *epsfilename=NULL;
+  size_t winpt, hinpt, *dsize=p->chll->dsize;
+
+
+  /* Find the bounding box  */
+  winpt=p->widthincm*72.0f/2.54f;
+  hinpt=(float)( dsize[0] * winpt )/(float)(dsize[1]);
+  hbw=(float)p->borderwidth/2.0f;
 
 
   /* EPS filename */
-  if(p->outputtype==EPSFORMAT)
+  if(p->outformat==OUT_FORMAT_EPS)
     {
       epsfilename=p->cp.output;
       gal_checkset_check_remove_file(epsfilename, p->cp.dontdelete);
     }
-  else if (p->outputtype==PDFFORMAT)
+  else if (p->outformat==OUT_FORMAT_PDF)
     {
       gal_checkset_check_remove_file(p->cp.output, p->cp.dontdelete);
-      gal_checkset_automatic_output(p->cp.output, ".ps", 0, p->cp.dontdelete,
-                                    &epsfilename);
+      epsfilename=gal_checkset_automatic_output(&p->cp, p->cp.output, ".ps");
     }
   else
-    error(EXIT_FAILURE, 0, "a bug! In `saveeps`, for outputtype is "
+    error(EXIT_FAILURE, 0, "a bug! In `saveeps`, for outformat is "
           "neither eps or pdf! Please contact us so we fix it");
 
 
-
-  /* Find the bounding box  */
-  winpt=p->widthincm*72.0f/2.54f;
-  hinpt=(float)(p->s0[0]*winpt)/(float)(p->s1[0]);
-  hbw=(float)p->borderwidth/2.0f;
-
-
-
   /* Open the output file and write the top comments. */
   errno=0;
   fp=fopen(epsfilename, "w");
@@ -384,15 +407,14 @@ saveepsorpdf(struct converttparams *p)
   fprintf(fp, "%%!PS-Adobe-3.0 EPSF-3.0\n");
   fprintf(fp, "%%%%BoundingBox: 0 0 %zu %zu\n", winpt+2*p->borderwidth,
           hinpt+2*p->borderwidth);
-  fprintf(fp, "%%%%Creator: %s\n", SPACK_STRING);
+  fprintf(fp, "%%%%Creator: %s\n", PROGRAM_STRING);
   fprintf(fp, "%%%%CreationDate: %s", ctime(&p->rawtime));
   fprintf(fp, "%%%%LanuageLevel: 3\n");
   fprintf(fp, "%%%%EndComments\n\n");
-  if(p->outputtype==EPSFORMAT)
+  if(p->outformat==OUT_FORMAT_EPS)
     fprintf(fp, "gsave\n\n");
 
 
-
   /* Commands to draw the border: */
   if(p->borderwidth)
     {
@@ -413,12 +435,12 @@ saveepsorpdf(struct converttparams *p)
   fprintf(fp, "%% Draw the image:\n");
   fprintf(fp, "%d %d translate\n", p->borderwidth, p->borderwidth);
   fprintf(fp, "%zu %zu scale\n", winpt, hinpt);
-  writeepsimage(p, fp);
+  eps_write_image(p, fp);
 
 
 
   /* Ending of the EPS file: */
-  if(p->outputtype==EPSFORMAT)
+  if(p->outformat==OUT_FORMAT_EPS)
     fprintf(fp, "grestore\n");
   else
     fprintf(fp, "showpage\n");
@@ -427,7 +449,7 @@ saveepsorpdf(struct converttparams *p)
 
 
 
-  if(p->outputtype==PDFFORMAT)
+  if(p->outformat==OUT_FORMAT_PDF)
     {
       sprintf(command, "gs -q -o %s -sDEVICE=pdfwrite -dDEVICEWIDTHPOINTS=%zu"
               " -dDEVICEHEIGHTPOINTS=%zu -dPDFFitPage %s", p->cp.output,
diff --git a/bin/convertt/eps.h b/bin/convertt/eps.h
index 35f62a8..6005f6e 100644
--- a/bin/convertt/eps.h
+++ b/bin/convertt/eps.h
@@ -36,6 +36,6 @@ int
 nameispdfsuffix(char *name);
 
 void
-saveepsorpdf(struct converttparams *p);
+eps_write_eps_or_pdf(struct converttparams *p);
 
 #endif
diff --git a/bin/convertt/jpeg.c b/bin/convertt/jpeg.c
index 0ac474f..ec20d62 100644
--- a/bin/convertt/jpeg.c
+++ b/bin/convertt/jpeg.c
@@ -157,15 +157,15 @@ makejsample(JSAMPLE **a, size_t size)
 
 
 
-double **
+unsigned char **
 readjpg(char *inname, size_t *outs0, size_t *outs1, size_t *numcolors)
 {
-  double **all;
   FILE * infile;
   JSAMPROW jrow;
   JSAMPLE *jsamp;
   int rowstride, c;
   JSAMPARRAY jsarr;
+  unsigned char **all;
   struct my_error_mgr jerr;
   size_t i, j, size, nc, s0, s1;
   struct jpeg_decompress_struct cinfo;
@@ -240,35 +240,38 @@ readjpg(char *inname, size_t *outs0, size_t *outs1, 
size_t *numcolors)
 
 
 
-void
-preparejpeg(struct converttparams *p, char *filename)
+/* Read each color channel of a JPEG image as a separate array and put them
+   in a linked list of data-structures. */
+size_t
+jpeg_read_to_ll(char *filename, gal_data_t **list, size_t minmapsize)
 {
-  double **allcolors;
+  char *name;
+  size_t ndim=2, dsize[2];
+  unsigned char **allcolors;
   size_t i, s0, s1, numcolors;
 
   /* Read the JPEG image into the all array. */
   allcolors=readjpg(filename, &s0, &s1, &numcolors);
 
-  /* Check if the number of colors that will be added with this JPEG
-     image does not exceed 4. */
-  if(p->numch+numcolors>4)
-    error(EXIT_FAILURE, 0, "the number of channels in %s added with the "
-          "previous inputs will exceed 4 (the maximum number of color "
-          "channels). Can't continue", filename);
-
-  /* Add each channel to the final set of channels. */
+  /* Add the arrays to the linked list. */
   for(i=0;i<numcolors;++i)
     {
-      p->s0[p->numch]=s0;
-      p->s1[p->numch]=s1;
-      p->ch[p->numch]=allcolors[i];
-      p->bitpixs[p->numch]=BYTE_IMG;
-      ++p->numch;
+      dsize[0]=s0;
+      dsize[1]=s1;
+      asprintf(&name, "JPEG_CH_%zu", i+1);
+      gal_data_add_to_ll(list, allcolors[i], GAL_DATA_TYPE_UCHAR, ndim,
+                         dsize, NULL, 0, minmapsize, name, NULL, NULL);
+      free(name);
     }
 
-  /* Free the array keeping the pointers to each channel. Note that
-     each channel was allocated separately so we can safely remove it.*/
+  /* Free the array keeping the pointers to each channel. Note that each
+     channel was allocated separately and goes out of this function with
+     the data structure, so we just have to free the outer array that kept
+     all the channels. */
   free(allcolors);
+
+  /* Return the number of color channels. */
+  return numcolors;
 }
 
 
@@ -293,14 +296,14 @@ preparejpeg(struct converttparams *p, char *filename)
 /*************************************************************
  **************       Write a JPEG image        **************
  *************************************************************/
-void
-writejpeg(JSAMPLE *jsr, struct converttparams *p)
+static void
+jpeg_write_array(JSAMPLE *jsr, struct converttparams *p)
 {
   JSAMPROW r[1];
   FILE * outfile;
   int row_stride=0, c;
   struct jpeg_error_mgr jerr;
-  size_t s0=p->s0[0], s1=p->s1[0];
+  size_t *dsize=p->chll->dsize;
   struct jpeg_compress_struct cinfo;
 
   /* Begin the JPEG writing, following libjpeg's example.c  */
@@ -312,22 +315,22 @@ writejpeg(JSAMPLE *jsr, struct converttparams *p)
     error(EXIT_FAILURE, errno, "%s", p->cp.output);
   jpeg_stdio_dest(&cinfo, outfile);
 
-  cinfo.image_width  = s1;
-  cinfo.image_height = s0;
+  cinfo.image_width  = dsize[1];
+  cinfo.image_height = dsize[0];
   switch(p->numch)
     {
     case 1:
-      row_stride=s1;
+      row_stride=dsize[1];
       cinfo.input_components = 1;
       cinfo.in_color_space = JCS_GRAYSCALE;
       break;
     case 3:
-      row_stride=3*s1;
+      row_stride=3*dsize[1];
       cinfo.input_components = 3;
       cinfo.in_color_space = JCS_RGB;
       break;
     case 4:
-      row_stride=4*s1;
+      row_stride=4*dsize[1];
       cinfo.input_components = 4;
       cinfo.in_color_space = JCS_CMYK;
       break;
@@ -340,11 +343,11 @@ writejpeg(JSAMPLE *jsr, struct converttparams *p)
   jpeg_set_defaults(&cinfo);
   jpeg_set_quality(&cinfo, p->quality, TRUE);
   cinfo.density_unit=1;
-  cinfo.Y_density=cinfo.X_density=s1/(p->widthincm/2.54);
+  cinfo.Y_density=cinfo.X_density=dsize[1]/(p->widthincm/2.54);
   jpeg_start_compress(&cinfo, TRUE);
 
   /* cinfo.next_scanline is 'unsigned int' */
-  c=s0-1; /* In FITS the first row is on the bottom!  */
+  c=dsize[0]-1; /* In JPEG the first row is on the bottom!  */
   while (cinfo.next_scanline < cinfo.image_height)
     {
       r[0] = & jsr[c-- * row_stride];
@@ -361,38 +364,46 @@ writejpeg(JSAMPLE *jsr, struct converttparams *p)
 
 
 void
-savejpeg(struct converttparams *p)
+jpeg_write(struct converttparams *p)
 {
   JSAMPLE *jsr;
-  uint8_t **ech=p->ech;
-  size_t pixel, color, size, numch=p->numch;
+  gal_data_t *channel;
+  unsigned char *colors[4];
+  size_t i, pixel, color, numch=p->numch;
+
+  /* A small sanity check */
+  if(p->numch==2 || p->numch>4)
+    error(EXIT_FAILURE, 0, "in jpeg, only 1, 3, and 4 color channels are "
+          "acceptable, ");
 
   /* Make sure the JSAMPLE is 8bits, then allocate the necessary space
      based on the number of channels. */
   if(sizeof *jsr!=1)
     error(EXIT_FAILURE, 0, "JSAMPLE has to be 8bit");
-  size=p->numch*p->s0[0]*p->s1[0];
   errno=0;
-  jsr=malloc(size*sizeof *jsr);
+  jsr=malloc(numch * p->chll->size * sizeof *jsr);
   if(jsr==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for jsr", size*sizeof *jsr);
+    error(EXIT_FAILURE, errno, "%zu bytes for jsr",
+          numch * p->chll->size * sizeof *jsr );
+
+  /* Set the pointers to each color. */
+  i=0;
+  for(channel=p->chll; channel!=NULL; channel=channel->next)
+    colors[i++]=channel->array;
 
   /* Write the different colors into jsr. */
-  size=p->s0[0]*p->s1[0];
-  for(pixel=0;pixel<size;++pixel)
+  for(pixel=0; pixel<p->chll->size; ++pixel)
     for(color=0;color<numch;++color)
       {
-        jsr[pixel*numch+color]=ech[color][pixel];
+        jsr[pixel*numch+color] = colors[color][pixel];
         /*
         printf("color: %zu, pixel: %zu, jsr: %d\n", color, pixel,
                (int)jsr[pixel*numch+color]);
         */
       }
 
-
-  /* Write jsr to a JPEG image. */
-  writejpeg(jsr, p);
-
+  /* Write jsr to a JPEG image and clean up. */
+  jpeg_write_array(jsr, p);
   free(jsr);
 }
 #endif  /* HAVE_LIBJPEG */
diff --git a/bin/convertt/jpeg.h b/bin/convertt/jpeg.h
index 5621a22..cfe7a9f 100644
--- a/bin/convertt/jpeg.h
+++ b/bin/convertt/jpeg.h
@@ -29,10 +29,10 @@ nameisjpeg(char *name);
 int
 nameisjpegsuffix(char *name);
 
-void
-preparejpeg(struct converttparams *p, char *filename);
+size_t
+jpeg_read_to_ll(char *filename, gal_data_t **list, size_t minmapsize);
 
 void
-savejpeg(struct converttparams *p);
+jpeg_write(struct converttparams *p);
 
 #endif
diff --git a/bin/convertt/main.c b/bin/convertt/main.c
index f8f5ae7..73489e1 100644
--- a/bin/convertt/main.c
+++ b/bin/convertt/main.c
@@ -35,19 +35,19 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 int
 main(int argc, char *argv[])
 {
-  struct converttparams p={{0}, {0}, 0};
+  struct converttparams p={{0}, 0};
 
   /* Set the starting time.*/
   time(&p.rawtime);
 
   /* Read the input parameters.*/
-  setparams(argc, argv, &p);
+  ui_read_check_inputs_setup(argc, argv, &p);
 
   /* Run Convert. */
   convertt(&p);
 
   /* Free all non-freed allocations. */
-  freeandreport(&p);
+  ui_free_report(&p);
 
   /* Return successfully.*/
   return EXIT_SUCCESS;
diff --git a/bin/convertt/main.h b/bin/convertt/main.h
index 313e9df..549b37f 100644
--- a/bin/convertt/main.h
+++ b/bin/convertt/main.h
@@ -5,7 +5,7 @@ ConvertType is part of GNU Astronomy Utilities (Gnuastro) 
package.
 Original author:
      Mohammad Akhlaghi <address@hidden>
 Contributing author(s):
-Copyright (C) 2015, Free Software Foundation, Inc.
+Copyright (C) 2016, Free Software Foundation, Inc.
 
 Gnuastro is free software: you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
@@ -23,32 +23,30 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #ifndef MAIN_H
 #define MAIN_H
 
-#include <stdint.h>
+/* Include necessary headers */
+#include <gnuastro/data.h>
 
-#include <commonparams.h>
+#include <options.h>
 
+/* Progarm names.  */
+#define PROGRAM_NAME   "ConvertType"   /* Program full name.       */
+#define PROGRAM_EXEC   "astconvertt"   /* Program executable name. */
+#define PROGRAM_STRING PROGRAM_NAME" (" PACKAGE_NAME ") " PACKAGE_VERSION
 
 
-/* Progarm name macros: */
-#define SPACK           "astconvertt" /* Subpackage executable name. */
-#define SPACK_NAME      "ConvertType" /* Subpackage full name.       */
-#define SPACK_STRING    SPACK_NAME" ("PACKAGE_NAME") "PACKAGE_VERSION
-
-
-
-
-
-#define BLANKCHANNELNAME "blank"
-
-
+/* Constants/macros. */
+#define BLANK_CHANNEL_NAME "blank"
 
+enum output_formats
+{
+  OUT_FORMAT_INVALID,           /* ==0 by C standard */
 
-/* Format codes: */
-#define TXTFORMAT     -1
-#define FITSFORMAT     1
-#define JPEGFORMAT     2
-#define EPSFORMAT      3
-#define PDFFORMAT      4
+  OUT_FORMAT_TXT,
+  OUT_FORMAT_EPS,
+  OUT_FORMAT_PDF,
+  OUT_FORMAT_FITS,
+  OUT_FORMAT_JPEG,
+};
 
 
 
@@ -57,8 +55,8 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 /* This is used in converting certain values in the array. */
 struct change
 {
-  double from;
-  double to;
+  gal_data_t    *from;
+  gal_data_t      *to;
   struct change *next;
 };
 
@@ -66,72 +64,33 @@ struct change
 
 
 
-struct uiparams
-{
-  char         *hdu2;            /* Header for second FITS image.   */
-  char         *hdu3;            /* Header for third FITS image.    */
-  char         *hdu4;            /* Header for fourth FITS image.   */
-
-  int        hdu2set;
-  int        hdu3set;
-  int        hdu4set;
-
-  int     qualityset;
-  int   widthincmset;
-  int borderwidthset;
-
-  int     fluxlowset;
-  int    fluxhighset;
-  int     maxbyteset;
-};
-
-
-
-
-
 struct converttparams
 {
-  /* Before actual program: */
-  struct uiparams         up;  /* User interface parameters.           */
-  struct gal_commonparams cp; /* Common parameters.                    */
-
-  /* Input: */
+  /* From command-line */
+  struct gal_options_common_params cp;    /* Common parameters.        */
   struct gal_linkedlist_stll *inputnames; /* The names of input files. */
-  size_t          numinputs;  /* Number of input files.                */
-  int             inputtype;  /* The type of the input file.           */
-
-  /* Output: */
-  int            outputtype;  /* The type of the output file.          */
-  int               quality;  /* Quality of JPEG image.                */
+  struct gal_linkedlist_stll *hdus;       /* The names of input hdus.  */
+  unsigned char     quality;  /* Quality of JPEG image.                */
   float           widthincm;  /* Width in centimeters.                 */
-  int           borderwidth;  /* Width of border in PostScript points. */
-  int                   hex;  /* Use hexadecimal not ASCII85 encoding. */
-
-  /* Flux: */
-  double            fluxlow;  /* Lower flux truncation value.          */
-  double           fluxhigh;  /* Higher flux truncation value.         */
-  uint8_t           maxbyte;  /* Maximum byte value.                   */
-  int             flminbyte;  /* fluxlow is minimum byte.              */
-  int             fhmaxbyte;  /* fluxhigh is maximum byte.             */
+  unsigned int  borderwidth;  /* Width of border in PostScript points. */
+  unsigned char         hex;  /* Use hexadecimal not ASCII85 encoding. */
+  char          *fluxlowstr;  /* Lower flux truncation value.          */
+  char         *fluxhighstr;  /* Higher flux truncation value.         */
+  unsigned char     maxbyte;  /* Maximum byte value.                   */
+  unsigned char   flminbyte;  /* fluxlow is minimum byte.              */
+  unsigned char   fhmaxbyte;  /* fluxhigh is maximum byte.             */
+  char           *changestr;  /* String of change values.              */
+  unsigned char changeaftertrunc;  /* First convert, then truncate.    */
+  unsigned char      invert;  /* ==1: invert the output image.         */
+
+  /* Internal */
   struct change     *change;  /* The value conversion string.          */
-  int      changeaftertrunc;  /* First convert, then truncate.         */
-  int                   log;  /* ==1: Save input in log scale.         */
-  int                invert;  /* ==1: Invert the image.                */
-
-  /* INTERNAL PARAMETERS: */
+  gal_data_t       *fluxlow;  /* The lower flux truncation.            */
+  gal_data_t      *fluxhigh;  /* The higher flux truncation.           */
   time_t            rawtime;  /* Starting time of the program.         */
-
-  /* Input channels: */
-  char            *names[4];  /* File names in input order.            */
+  int             outformat;  /* The format of the output file.        */
   size_t              numch;  /* Current Channel.                      */
-  int            isblank[4];  /* ==1: this channel is blank or fill.   */
-  int            bitpixs[4];  /* Bitpix values for each channel.       */
-  int             numnul[4];  /* Number of NUL in each channel.        */
-  double             *ch[4];  /* Data for each channel.                */
-  uint8_t           *ech[4];  /* 8-bit color channels.                 */
-  size_t              s0[4];  /* First C axis size for each channel.   */
-  size_t              s1[4];  /* Second C axis size for each channel.  */
+  gal_data_t          *chll;  /* Linked list of color channels.        */
 };
 
-
 #endif
diff --git a/bin/convertt/ui.c b/bin/convertt/ui.c
index 02c53fd..bc85dc7 100644
--- a/bin/convertt/ui.c
+++ b/bin/convertt/ui.c
@@ -5,7 +5,7 @@ ConvertType is part of GNU Astronomy Utilities (Gnuastro) 
package.
 Original author:
      Mohammad Akhlaghi <address@hidden>
 Contributing author(s):
-Copyright (C) 2015, Free Software Foundation, Inc.
+Copyright (C) 2016, Free Software Foundation, Inc.
 
 Gnuastro is free software: you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
@@ -22,249 +22,105 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 **********************************************************************/
 #include <config.h>
 
-#include <math.h>
 #include <argp.h>
 #include <errno.h>
 #include <error.h>
 #include <stdio.h>
-#include <float.h>
-#include <stdlib.h>
+#include <string.h>
 
 #include <gnuastro/fits.h>
-#include <gnuastro/txtarray.h>
-#include <gnuastro/linkedlist.h>
+#include <gnuastro/table.h>
+#include <gnuastro/arithmetic.h>
 
-#include <nproc.h>              /* From Gnulib.                     */
-#include <timing.h>             /* Includes time.h and sys/time.h   */
-#include <configfiles.h>
+#include <timing.h>
+#include <options.h>
+#include <checkset.h>
+#include <fixedstringmacros.h>
 
 #include "main.h"
 
+#include "ui.h"
 #include "eps.h"
-#include "args.h"
 #include "jpeg.h"
-
-
-
-/* Set the file names of the places where the default parameters are
-   put. */
-#define CONFIG_FILE SPACK CONF_POSTFIX
-#define SYSCONFIG_FILE SYSCONFIG_DIR "/" CONFIG_FILE
-#define USERCONFIG_FILEEND USERCONFIG_DIR CONFIG_FILE
-#define CURDIRCONFIG_FILE CURDIRCONFIG_DIR CONFIG_FILE
+#include "authors-cite.h"
 
 
 
 
 
 /**************************************************************/
-/**************       Options and parameters    ***************/
+/*********      Argp necessary global entities     ************/
 /**************************************************************/
-void
-readconfig(char *filename, struct converttparams *p)
-{
-  int tmp;
-  FILE *fp;
-  size_t lineno=0, len=200;
-  char *line, *name, *value;
-  struct uiparams *up=&p->up;
-  struct gal_commonparams *cp=&p->cp;
-  char key='a';        /* Not used, just a place holder. */
-
-  /* When the file doesn't exist or can't be opened, it is ignored. It
-     might be intentional, so there is no error. If a parameter is
-     missing, it will be reported after all defaults are read. */
-  fp=fopen(filename, "r");
-  if (fp==NULL) return;
-
-
-  /* Allocate some space for `line` with `len` elements so it can
-     easily be freed later on. The value of `len` is arbitarary at
-     this point, during the run, getline will change it along with the
-     pointer to line. */
-  errno=0;
-  line=malloc(len*sizeof *line);
-  if(line==NULL)
-    error(EXIT_FAILURE, errno, "ui.c: %zu bytes in readdefaults",
-          len * sizeof *line);
+/* Definition parameters for the Argp: */
+const char *
+argp_program_version = PROGRAM_STRING "\n"
+                       GAL_STRINGS_COPYRIGHT
+                       "\n\nWritten/developed by "PROGRAM_AUTHORS;
 
-  /* Read the tokens in the file:  */
-  while(getline(&line, &len, fp) != -1)
-    {
-      /* Prepare the "name" and "value" strings, also set lineno. */
-      GAL_CONFIGFILES_START_READING_LINE;
+const char *
+argp_program_bug_address = PACKAGE_BUGREPORT;
 
-      /* Inputs: */
-      if(strcmp(name, "hdu")==0)
-        gal_checkset_allocate_copy_set(value, &cp->hdu, &cp->hduset);
-      else if(strcmp(name, "hdu2")==0)
-        gal_checkset_allocate_copy_set(value, &up->hdu2, &up->hdu2set);
-      else if(strcmp(name, "hdu3")==0)
-        gal_checkset_allocate_copy_set(value, &up->hdu3, &up->hdu3set);
-      else if(strcmp(name, "hdu4")==0)
-        gal_checkset_allocate_copy_set(value, &up->hdu4, &up->hdu4set);
+static char
+args_doc[] = "InputFile1 [InputFile2] ... [InputFile4]";
 
+const char
+doc[] = GAL_STRINGS_TOP_HELP_INFO PROGRAM_NAME" will convert any of the "
+  "known input formats to any other of the known formats. The output file "
+  "will have the same number of pixels.\n"
+  GAL_STRINGS_MORE_HELP_INFO
+  /* After the list of options: */
+  "\v"
+  PACKAGE_NAME" home page: "PACKAGE_URL;
 
-      /* Outputs: */
-      else if(strcmp(name, "output")==0)
-        gal_checkset_allocate_copy_set(value, &cp->output, &cp->outputset);
 
-      else if(strcmp(name, "quality")==0)
-        {
-          if(up->qualityset) continue;
-          gal_checkset_int_smaller_equal_to(value, &p->quality, name, key,
-                                            p->cp.spack, filename, lineno,
-                                            100);
-          if(p->quality<0)
-            error(EXIT_FAILURE, 0, "the quality option should be positive");
-          up->qualityset=1;
-        }
-      else if(strcmp(name, "widthincm")==0)
-        {
-          if(up->widthincmset) continue;
-          gal_checkset_float_l_0(value, &p->widthincm, name, key, SPACK,
-                                 filename, lineno);
-          up->widthincmset=1;
-        }
-      else if(strcmp(name, "borderwidth")==0)
-        {
-          if(up->borderwidthset) continue;
-          gal_checkset_int_el_zero(value, &p->borderwidth, name, key, SPACK,
-                                   filename, lineno);
-          up->borderwidthset=1;
-        }
 
 
 
+/* Option groups particular to this program */
+enum program_args_groups
+{
+  ARGS_GROUP_FLUX = GAL_OPTIONS_GROUP_AFTER_COMMON,
+};
 
 
-      /* Flux: */
-      else if(strcmp(name, "fluxlow")==0)
-        {
-          if(up->fluxlowset) continue;
-          gal_checkset_any_double(value, &p->fluxlow, name, key,
-                                  p->cp.spack, filename, lineno);
-          up->fluxlowset=1;
-        }
-      else if(strcmp(name, "fluxhigh")==0)
-        {
-          if(up->fluxhighset) continue;
-          gal_checkset_any_double(value, &p->fluxhigh, name, key,
-                                  p->cp.spack, filename, lineno);
-          up->fluxhighset=1;
-        }
-      else if(strcmp(name, "maxbyte")==0)
-        {
-          if(up->maxbyteset) continue;
-          gal_checkset_int_smaller_equal_to(value, &tmp, "maxbyte", key,
-                                            p->cp.spack, NULL, 0, UINT8_MAX);
-          if(tmp<0)
-            error(EXIT_FAILURE, 0, "--maxbyte (-m) should be positive");
-          p->maxbyte=tmp;
-          p->up.maxbyteset=1;
-        }
 
 
+/* Available letters for short options:
 
-      /* Operating modes: */
-      /* Read options common to all programs */
-      GAL_CONFIGFILES_READ_COMMONOPTIONS_FROM_CONF
+   d e f g j k l n p r s t v y z
+   A B E F G I J M O Q R T U W X Y Z      */
+enum option_keys_enum
+{
+  /* With short-option version. */
+  ARGS_OPTION_KEY_QUALITY             = 'u',
+  ARGS_OPTION_KEY_WIDTHINCM           = 'w',
+  ARGS_OPTION_KEY_BORDERWIDTH         = 'b',
+  ARGS_OPTION_KEY_HEX                 = 'x',
+  ARGS_OPTION_KEY_FLUXLOW             = 'L',
+  ARGS_OPTION_KEY_FLUXHIGH            = 'H',
+  ARGS_OPTION_KEY_HIGH                = 'H',
+  ARGS_OPTION_KEY_MAXBYTE             = 'm',
+  ARGS_OPTION_KEY_FLMINBYTE           = 'a',
+  ARGS_OPTION_KEY_FHMAXBYTE           = 'b',
+  ARGS_OPTION_KEY_CHANGE              = 'c',
+  ARGS_OPTION_KEY_CHANGEAFTERTRUNC    = 'C',
+  ARGS_OPTION_KEY_INVERT            = 'i',
 
+  /* Only with long version (start with a value 1000, the rest will be set
+     automatically). */
+};
 
-      else
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      "`%s` not recognized.\n", name);
-    }
 
-  free(line);
-  fclose(fp);
-}
 
 
 
 
 
-void
-printvalues(FILE *fp, struct converttparams *p)
-{
-  struct uiparams *up=&p->up;
-  struct gal_commonparams *cp=&p->cp;
-
-  /* Print all the options that are set. Separate each group with a
-     commented line explaining the options in that group. */
-  fprintf(fp, "\n# Input image:\n");
-  if(cp->hduset)
-    GAL_CHECKSET_PRINT_STRING_MAYBE_WITH_SPACE("hdu", cp->hdu);
-  if(up->hdu2set)
-    GAL_CHECKSET_PRINT_STRING_MAYBE_WITH_SPACE("hdu2", up->hdu2);
-  if(up->hdu3set)
-    GAL_CHECKSET_PRINT_STRING_MAYBE_WITH_SPACE("hdu3", up->hdu3);
-  if(up->hdu4set)
-    GAL_CHECKSET_PRINT_STRING_MAYBE_WITH_SPACE("hdu4", up->hdu4);
-
-
-  fprintf(fp, "\n# Output parameters:\n");
-  if(cp->outputset)
-    fprintf(fp, CONF_SHOWFMT"%s\n", "output", cp->output);
-  if(up->qualityset)
-    fprintf(fp, CONF_SHOWFMT"%d\n", "quality", p->quality);
-  if(up->widthincmset)
-    fprintf(fp, CONF_SHOWFMT"%.2f\n", "widthincm", p->widthincm);
-  if(up->borderwidthset)
-    fprintf(fp, CONF_SHOWFMT"%d\n", "borderwidth", p->borderwidth);
-
-
-  fprintf(fp, "\n# Output flux display:\n");
-  if(up->fluxlowset)
-    fprintf(fp, CONF_SHOWFMT"%.3f\n", "fluxlow", p->fluxlow);
-  if(up->fluxhighset)
-    fprintf(fp, CONF_SHOWFMT"%.3f\n", "fluxhigh", p->fluxhigh);
-  if(up->maxbyteset)
-    fprintf(fp, CONF_SHOWFMT"%d\n", "maxbyte", (int)(p->maxbyte));
-
-  /* For the operating mode, first put the macro to print the common
-     options, then the (possible options particular to this
-     program). */
-  fprintf(fp, "\n# Operating modes:\n");
-  GAL_CONFIGFILES_PRINT_COMMONOPTIONS;
-}
 
 
 
 
 
-/* Note that numthreads will be used automatically based on the
-   configure time. */
-void
-checkifset(struct converttparams *p)
-{
-  struct uiparams *up=&p->up;
-  struct gal_commonparams *cp=&p->cp;
-
-  int intro=0;
-  if(cp->hduset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("hdu");
-  if(up->hdu2set==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("hdu2");
-  if(up->hdu3set==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("hdu3");
-  if(up->hdu4set==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("hdu4");
-  if(up->qualityset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("quality");
-  if(up->widthincmset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("widthincm");
-  if(up->borderwidthset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("borderwidth");
-  if(up->fluxlowset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("fluxlow");
-  if(up->fluxhighset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("fluxhigh");
-  if(up->maxbyteset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("maxbyte");
-
-  GAL_CONFIGFILES_END_OF_NOTSET_REPORT;
-}
 
 
 
@@ -272,65 +128,97 @@ checkifset(struct converttparams *p)
 
 
 
+/**************************************************************/
+/*********    Initialize & Parse command-line    **************/
+/**************************************************************/
+static void
+ui_initialize_options(struct converttparams *p,
+                      struct argp_option *program_options,
+                      struct argp_option *gal_commonopts_options)
+{
+  size_t i;
+  struct gal_options_common_params *cp=&p->cp;
 
 
+  /* Set the necessary common parameters structure. */
+  cp->poptions           = program_options;
+  cp->program_name       = PROGRAM_NAME;
+  cp->program_exec       = PROGRAM_EXEC;
+  cp->program_bibtex     = PROGRAM_BIBTEX;
+  cp->program_authors    = PROGRAM_AUTHORS;
+  cp->coptions           = gal_commonopts_options;
 
+  /* Program specific non-zero values. */
+  p->maxbyte             = UINT8_MAX;
 
+  /* Edit the common options. */
+  for(i=0; !gal_options_is_last(&cp->coptions[i]); ++i)
+    switch(cp->coptions[i].key)
+      {
+      case GAL_OPTIONS_KEY_HDU:
+        cp->coptions[i].value=&p->hdus;
+        cp->coptions[i].type=GAL_DATA_TYPE_STRLL;
+        cp->coptions[i].doc="FITS input HDU, multiple calls possible.";
+        break;
 
+      case GAL_OPTIONS_KEY_OUTPUT:
+        cp->coptions[i].mandatory=GAL_OPTIONS_MANDATORY;
+        cp->coptions[i].doc="Output filename or suffix.";
+        break;
 
+      case GAL_OPTIONS_KEY_MINMAPSIZE:
+        cp->coptions[i].mandatory=GAL_OPTIONS_MANDATORY;
+        break;
 
+      case GAL_OPTIONS_KEY_SEARCHIN:
+      case GAL_OPTIONS_KEY_IGNORECASE:
+      case GAL_OPTIONS_KEY_TABLEFORMAT:
+        cp->coptions[i].flags=OPTION_HIDDEN;
+        break;
+      }
+}
 
 
 
 
 
-/****************************************************************
- *****************   Read convert values:    ********************
- ****************************************************************/
-struct change *
-makechangestruct(char *arg)
+/* Parse a single option: */
+error_t
+parse_opt(int key, char *arg, struct argp_state *state)
 {
-  char *p=arg;
-  struct change *out=NULL, *c;
-
-  while(*p!='\0')
+  struct converttparams *p = state->input;
+
+  /* Pass `gal_options_common_params' into the child parser.  */
+  state->child_inputs[0] = &p->cp;
+
+  /* In case the user incorrectly uses the equal sign (for example
+     with a short format or with space in the long format, then `arg`
+     start with (if the short version was called) or be (if the long
+     version was called with a space) the equal sign. So, here we
+     check if the first character of arg is the equal sign, then the
+     user is warned and the program is stopped: */
+  if(arg && arg[0]=='=')
+    argp_error(state, "incorrect use of the equal sign (`=`). For short "
+               "options, `=` should not be used and for long options, "
+               "there should be no space between the option, equal sign "
+               "and value");
+
+  /* Set the key to this option. */
+  switch(key)
     {
-      while(*p==' ') {++p; continue;} /* Skip all space characters. */
-      errno=0;
-      c=malloc(sizeof *c);
-      if(c==NULL) error(EXIT_FAILURE, 0, "%zu bytes for struct change",
-                        sizeof *c);
-      c->from=strtod(p, &p);
-      while(*p==' ') {++p; continue;}
-      if(*p==':') ++p;
-      else
-        {
-          fprintf(stderr, PACKAGE": In the conversion option, [from] "
-                  "and [to] values should be separated by a ':'. You "
-                  "have given a '%c': %s\n", *p, arg);
-          exit(EXIT_FAILURE);
-        }
-      c->to=strtod(p, &p);
-      while(*p==' ') {++p; continue;}
-      if(*p==',') p++;
-      else if(*p!='\0')
-        {
-          fprintf(stderr, PACKAGE": In the conversion option, [from] "
-                  "and [to] pairs should be separated by a ','. You have "
-                  "provided a '%c': %s\n", *p, arg);
-          exit(EXIT_FAILURE);
-        }
-      c->next=out;
-      out=c;
+
+    /* Read the non-option tokens (arguments): */
+    case ARGP_KEY_ARG:
+      gal_linkedlist_add_to_stll(&p->inputnames, arg, 0);
+      break;
+
+
+    /* This is an option, set its value. */
+    default:
+      return gal_options_set_from_key(key, arg, p->cp.poptions, &p->cp);
     }
-  /*
-  {
-    struct change *tmp;
-    for(tmp=out;tmp!=NULL;tmp=tmp->next)
-      printf("%f --> %f\n", tmp->from, tmp->to);
-  }
-  */
-  return out;
+
+  return 0;
 }
 
 
@@ -355,177 +243,68 @@ makechangestruct(char *arg)
 /**************************************************************/
 /***************       Sanity Check         *******************/
 /**************************************************************/
-/* We know cp->output is a known suffix, we just don't know if it has
-   a `.` before it or not. If it doesn't one will be added to it an
-   the output name will be set. */
-void
-adddotautomaticoutput(struct converttparams *p)
+/* Read and check ONLY the options. When arguments are involved, do the
+   check in `ui_check_options_and_arguments'. */
+static void
+ui_read_check_only_options(struct converttparams *p)
 {
-  size_t i;
-  struct gal_commonparams *cp=&p->cp;
-  char *tmp, *basename="output.txt";
+  gal_data_t *cond;
 
-  /* Find the first file name in the input(s). */
-  for(i=0;i<p->numinputs;++i)
-    if(strcmp(p->names[i], BLANKCHANNELNAME))
-      {
-        basename=p->names[i];
-        break;
-      }
 
-  /* If the suffix does not start with a `.`, put one there. */
-  if(cp->output[0]!='.')
+  /* Check if quality is smaller and equal to 100 (we already checked if it
+     was greater than zero before. */
+  if(p->quality>100)
+    error(EXIT_FAILURE, 0, "`%u' is larger than 100. The value to the "
+          "`--quality' (`-u') option must be between 1 and 100 (inclusive)",
+          p->quality);
+
+
+  /* Read the truncation values into a data structure and see if flux low
+     is indeed smaller than fluxhigh. */
+  if(p->fluxlowstr)
     {
-      errno=0;
-      tmp=malloc(strlen(cp->output)+10*sizeof *tmp);
-      if(tmp==NULL)
-        error(EXIT_FAILURE, errno, "%zu bytes for suffix name",
-              strlen(cp->output)+10*sizeof *tmp);
-      sprintf(tmp, ".%s", cp->output);
-      free(cp->output);
-      cp->output=tmp;
+      p->fluxlow=gal_data_string_to_number(p->fluxlowstr);
+      if(p->fluxlow==NULL)
+        error(EXIT_FAILURE, 0, "value to the `--fluxlow' (`-L', %s) "
+              "couldn't be read as a number", p->fluxlowstr);
     }
 
-  /* Set the automatic output and make sure we have write access. */
-  gal_checkset_automatic_output(basename, cp->output, cp->removedirinfo,
-                                cp->dontdelete, &cp->output);
-  if( gal_checkset_dir_0_file_1(cp->output, cp->dontdelete)==0 )
-    error(EXIT_FAILURE, 0, "%s is a directory", cp->output);
-}
+  if(p->fluxhighstr)
+    {
+      p->fluxhigh=gal_data_string_to_number(p->fluxhighstr);
+      if(p->fluxhigh==NULL)
+        error(EXIT_FAILURE, 0, "value to the `--fluxhigh' (`-H', %s) "
+              "couldn't be read as a number", p->fluxhighstr);
+    }
 
+  if(p->fluxhighstr && p->fluxlowstr)
+    {
+      cond=gal_arithmetic(GAL_ARITHMETIC_OP_GT, GAL_ARITHMETIC_NUMOK,
+                          p->fluxhigh, p->fluxlow);
 
+      if( *((unsigned char *)cond->array) == 0 )
+        error(EXIT_FAILURE, 0, "The value of `--fluxlow' must be less "
+              "than `--fluxhigh'");
 
+      gal_data_free(cond);
+    }
+}
 
 
-void
-sanitycheck(struct converttparams *p)
-{
-  size_t i, j;
-  struct gal_commonparams *cp=&p->cp;
 
-  /* The flux range: */
-  if(p->fluxlow>p->fluxhigh)
-    error(EXIT_FAILURE, 0, "the value of `--fluxlow` (`-L`, %.3f) is "
-          "larger than `--fluxhigh` (`-H`, %.3f)", p->fluxlow, p->fluxhigh);
 
-  /* Make sure there are 1 (for grayscale), 3 (for RGB) or 4 (for
-     CMYK) color channels. */
-  if(p->numch!=1 && p->numch!=3 && p->numch!=4)
-    error(EXIT_FAILURE, 0, "the number of input color channels has to be "
-          "1 (for non image data, grayscale or only K channel in CMYK), "
-          "3 (for RGB) and 4 (for CMYK). You have given %zu color channels. "
-          "Note that some file formats (for example JPEG) can contain more "
-          "than one color channel", p->numch);
-
-  /* Make sure that there is atleast one input file (not only blank)
-     and set the sizes of the blank channels to the first non-blank
-     value. */
-  for(i=0;i<p->numch;++i)
-    if(p->isblank[i]==0) break;
-  if(i==p->numch)
-    error(EXIT_FAILURE, 0, "all the input(s) are of type blank");
-  for(j=0;j<p->numch;++j)
-    if(p->isblank[j])
-      {
-        p->s0[j]=p->s0[i];
-        p->s1[j]=p->s1[i];
-      }
 
-  /* Check if all the input sources have the same size: */
-  if(p->numch>1)
-    {
-      for(i=1;i<p->numch;++i)
-        if(p->s0[i]!=p->s0[0] || p->s1[i]!=p->s1[0])
-          break;
-      if(i!=p->numch)
-        {
-          for(i=0;i<p->numch;++i)
-            fprintf(stderr, "Channel %zu is %zu x %zu pixels.\n", i,
-                    p->s1[i], p->s0[i]);
-          error(EXIT_FAILURE, 0, "the input color channels have different "
-                "sizes");
-        }
-    }
+static void
+ui_check_options_and_arguments(struct converttparams *p)
+{
+  /* Check if there was any inputs. */
+  if(p->inputnames==NULL)
+    error(EXIT_FAILURE, 0, "no input files given");
 
-  /* Allocate space for the blank channels and set them to zero: */
-  for(i=0;i<p->numch;++i)
-    if(p->isblank[i])
-      {
-        errno=0;
-        p->ch[i]=calloc(p->s0[0]*p->s1[0], sizeof *p->ch[i]);
-        if(p->ch[i]==NULL)
-          error(EXIT_FAILURE, errno, "allocating %zu bytes for the blank "
-                "channel %zu", p->s0[0]*p->s1[0]*sizeof *p->ch[i], i);
-      }
+  /* Reverse the `inputnames' linked list, note that the `hdu' linked list
+     was reversed during option parsing.*/
+  gal_linkedlist_reverse_stll(&p->inputnames);
 
-  /* The output file name. First find the first non-blank file name: */
-  if(cp->outputset)
-    {
-      if(gal_fits_name_is_fits(cp->output))
-        {
-          p->outputtype=FITSFORMAT;
-          if( gal_fits_suffix_is_fits(cp->output) )
-            adddotautomaticoutput(p);
-        }
-      else if(nameisjpeg(cp->output))
-        {
-#ifndef HAVE_LIBJPEG
-          error(EXIT_FAILURE, 0, "you have asked for a JPEG output, "
-                "however, when %s was configured libjpeg was not "
-                "available. To write to JPEG files, libjpeg is required. "
-                "Please install it and configure, make and install %s "
-                "again", PACKAGE_STRING, PACKAGE_STRING);
-#else
-          p->outputtype=JPEGFORMAT;
-          if( nameisjpegsuffix(cp->output) )
-            adddotautomaticoutput(p);
-#endif
-        }
-      else if(nameiseps(cp->output))
-        {
-          p->outputtype=EPSFORMAT;
-          if( nameisepssuffix(cp->output) )
-            adddotautomaticoutput(p);
-        }
-      else if(nameispdf(cp->output))
-        {
-          p->outputtype=PDFFORMAT;
-          if( nameispdfsuffix(cp->output) )
-            adddotautomaticoutput(p);
-        }
-      else
-        {
-          /* If the length of the name is shorter than 4 characters, it is
-             most probably a mis-spelled extension, warn the user. */
-          if(strlen(cp->output)<=5)
-            error(EXIT_FAILURE, 0, "your output file name is "
-                    "`%s`, based on its length, it might be a mis-spelled "
-                    "extension. Your input is converted to a plain text "
-                    "format file with That name",
-                    cp->output);
-
-          p->outputtype=TXTFORMAT;
-
-          /* If output type is not an image, there should only be one color
-             channel: */
-          if(p->numch>1)
-            error(EXIT_FAILURE, 0, "text output (`--output=%s`) can only be "
-                  "completed with one input color channel. You have given "
-                  "%zu. Note that some formats (for example JPEG) can have "
-                  "more than one color channel in each file. You can first "
-                  "convert the file to FITS, then convert the desired "
-                  "channel to text by specifying the HDU",
-                  cp->output, p->numch);
-        }
-    }
-  else
-    error(EXIT_FAILURE, 0, "no output file name or extension is specified, "
-          "Please run "SPACK" again with the `--output' or `-o' option.\n\n"
-          "The value to this option doesn't have to be a file name, you "
-          "can also only give an extension (in which case your input file"
-          "name will be used for the base name of the output. For example "
-          "running `"SPACK" filename.fits -ojpg') will produce the output "
-          "file `filename.jpg')");
 }
 
 
@@ -548,88 +327,170 @@ sanitycheck(struct converttparams *p)
 
 
 /**************************************************************/
-/***************        Preparations        *******************/
+/***************       Preparations         *******************/
 /**************************************************************/
-void
-preparearrays(struct converttparams *p)
+static struct change *
+ui_make_change_struct(char *arg)
 {
-  size_t i;
-  void *array;
-  double *d, *df;
-  struct gal_linkedlist_stll *tmp;
-  char *hdu=NULL, **names=p->names;
+  char *p=arg;
+  gal_data_t *data;
+  size_t len=0, counter=0;
+  struct change *out, *last=NULL, *ch;
+
+  /* First set all the delimiters to `\0' and count the number of
+     characters in the full string. */
+  while(*p!='\0')
+    {
+      if( isspace(*p) || *p==':' || *p==',' ) *p='\0';
+      ++p;
+    }
+  len=p-arg;
+
+  /* Now, go through the string and read everything that remains. */
+  p=arg;
+  while(p<arg+len)
+    {
+      if(*p=='\0')
+        ++p;
+      else
+        {
+          /* Read the number and increment the counter. */
+          ++counter;
+          data=gal_data_string_to_number(p);
+          if(data==NULL)
+            error(EXIT_FAILURE, 0, "`%s' (input number %zu to the "
+                  "`--change' option) couldn't be read as a number", p,
+                  counter);
+
+          /* Go to the end of this number (until you reach a `\0'). */
+          while(*p!='\0') {++p; continue;}
+
+          /* Put the data structure in the correct place. When the counter is
+             an odd number, we have just started a new set of changes.*/
+          if(counter%2)             /* Odd. */
+            {
+              /* Allocate space for the new structure. */
+              errno=0;
+              ch=malloc(sizeof *ch);
+              if(ch==NULL)
+                error(EXIT_FAILURE, errno, "%zu bytes for ch in "
+                      "`ui_make_change_struct'", sizeof *ch);
+
+              /* If the last structure has already been defined (!=NULL)
+                 then we should set its next element to `ch' and change it
+                 to point to `ch'. On the other hand, when this is the
+                 first structure to be created, then `last==NULL', so to
+                 start off the process, we should put `ch' into both the
+                 `out' and `last' lists.. */
+              if(last)
+                {
+                  last->next=ch;
+                  last=ch;
+                }
+              else
+                out=last=ch;
+
+              /* Put `data' in the `from' element, and since this is the
+                 last structure, set its next element to NULL. */
+              last->from=data;
+              last->next=NULL;
+            }
+          else                      /* Even. */
+            last->to=data;
+        }
+    }
+
+  /*
+    {
+    struct change *tmp;
+    for(tmp=out;tmp!=NULL;tmp=tmp->next)
+    printf("%f --> %f\n", tmp->from, tmp->to);
+    }
+  */
+  return out;
+}
+
+
 
-  /* Put the names in the correct order. */
-  i=p->numinputs-1;
-  for(tmp=p->inputnames; tmp!=NULL; tmp=tmp->next)
-    names[i--]=tmp->v;
 
+
+/* Go through the input files and make a linked list of all the channels
+   that exist in them. When this function finishes the list of channels
+   will be filled in the same order as they were read from the inputs. */
+static void
+ui_make_channels_ll(struct converttparams *p)
+{
+  char *hdu;
+  size_t dsize=0;
+  gal_data_t *data;
+  struct gal_linkedlist_stll *name;
+
+  /* Go through the input files and add the channel(s). */
   p->numch=0;
-  for(i=0;i<p->numinputs;++i)
+  for(name=p->inputnames; name!=NULL; name=name->next)
     {
       /* Check if p->numch has not exceeded 4. */
       if(p->numch>=4)
         error(EXIT_FAILURE, 0, "the number of input color channels (not "
-              "files) has exceeded 4! Note that one file can contain more "
-              "than one color channel");
+              "necessarily files) has exceeded 4! Note that one file can "
+              "contain more than one color channel (for example a JPEG "
+              "file in RGB has 3 channels)");
 
       /* Make sure this input file exists (if it isn't blank). */
-      if(strcmp(names[i], "blank")) gal_checkset_check_file(names[i]);
+      if(strcmp(name->v, "blank")) gal_checkset_check_file(name->v);
 
       /* FITS: */
-      if( gal_fits_name_is_fits(names[i]) )
+      if( gal_fits_name_is_fits(name->v) )
         {
-          switch(p->numch) /* Get the HDU value for this channel. */
-            {
-            case 0: hdu=p->cp.hdu; break;   case 1: hdu=p->up.hdu2; break;
-            case 2: hdu=p->up.hdu3; break;  case 3: hdu=p->up.hdu4; break;
-            default: error(EXIT_FAILURE, 0, "a bug! In parsing the input "
-                           "FITS files, it has gone beyond four! Please "
-                           "contact us so we can see what caused this "
-                           "problem and fix it");
-            }
-          p->numnul[p->numch]=
-            gal_fits_hdu_to_array(names[i], hdu, &p->bitpixs[p->numch],
-                                  &array, &p->s0[p->numch],
-                                  &p->s1[p->numch]);
-          gal_fits_change_type(array, p->bitpixs[p->numch],
-                               p->s0[p->numch]*p->s1[p->numch],
-                               p->numnul[p->numch],
-                               (void **)(&p->ch[p->numch]), DOUBLE_IMG);
-          free(array);
+          /* Get the HDU value for this channel. */
+          if(p->hdus)
+            gal_linkedlist_pop_from_stll(&p->hdus, &hdu);
+          else
+            error(EXIT_FAILURE, 0, "not enough HDUs. Every input FITS image "
+                  "needs a HDU, you can use the `--hdu' (`-h') option once "
+                  "for each input FITS image (in the same order)");
+
+          /* Read in the array and its WCS information. */
+          data=gal_fits_read_to_type(name->v, hdu, GAL_DATA_TYPE_DOUBLE,
+                                     p->cp.minmapsize);
+          gal_fits_read_wcs(name->v, hdu, 0, 0, &data->nwcs, &data->wcs);
+          gal_data_add_existing_to_ll(&p->chll, data);
+
+          /* A FITS file only has one channel. */
           ++p->numch;
         }
 
 
 
       /* JPEG: */
-      else if ( nameisjpeg(names[i]) )
+      else if ( nameisjpeg(name->v) )
         {
 #ifndef HAVE_LIBJPEG
           error(EXIT_FAILURE, 0, "you are giving a JPEG input, however, "
                 "when %s was configured libjpeg was not available. To read "
-                "from JPEG files, libjpeg is required. Please install it "
-                "and configure, make and install %s again", PACKAGE_STRING,
-                PACKAGE_STRING);
+                "from (and write to) JPEG files, libjpeg is required. "
+                "Please install it and configure, make and install %s "
+                "again", PACKAGE_STRING, PACKAGE_STRING);
 #else
-          preparejpeg(p, names[i]);
+          p->numch += jpeg_read_to_ll(name->v, &p->chll, p->cp.minmapsize);
 #endif
         }
 
 
 
       /* Blank: */
-      else if(strcmp(names[i], BLANKCHANNELNAME)==0)
+      else if(strcmp(name->v, BLANK_CHANNEL_NAME)==0)
         {
-          p->isblank[p->numch]=1;
-          p->bitpixs[p->numch]=BYTE_IMG;
+          gal_data_add_to_ll(&p->chll, NULL, GAL_DATA_TYPE_INVALID, 0,
+                             &dsize, NULL, 0, p->cp.minmapsize, "blank",
+                             NULL, NULL);
           ++p->numch;
         }
 
 
 
       /* EPS:  */
-      else if ( nameiseps(names[i]) )
+      else if ( nameiseps(name->v) )
         error(EXIT_FAILURE, 0, "EPS files cannot be used as input. Since "
               "EPS files are not raster graphics, they are only used as "
               "output");
@@ -637,7 +498,7 @@ preparearrays(struct converttparams *p)
 
 
       /* PDF:  */
-      else if ( nameispdf(names[i]) )
+      else if ( nameispdf(name->v) )
         error(EXIT_FAILURE, 0, "PDF files cannot be used as input. Since "
               "PDF files are not raster graphics, they are only used as "
               "output");
@@ -646,7 +507,10 @@ preparearrays(struct converttparams *p)
       /* Text: */
       else
         {
-          gal_txtarray_txt_to_array(names[i], &p->ch[p->numch],
+          printf("\n\n... Work on txt inputs ...\n");
+          exit(1);
+          /*
+          gal_txtarray_txt_to_array(name->v, &p->ch[p->numch],
                                     &p->s0[p->numch], &p->s1[p->numch]);
           df = (d=p->ch[p->numch]) + p->s0[p->numch]*p->s1[p->numch];
           do if(isnan(*d++)) break; while(d<df);
@@ -654,17 +518,252 @@ preparearrays(struct converttparams *p)
             gal_checkset_check_remove_file(GAL_TXTARRAY_LOG, 0);
           else
             error(EXIT_FAILURE, 0, "%s contains non-numeric data, see %s",
-                  names[i], GAL_TXTARRAY_LOG);
+                  name->v, GAL_TXTARRAY_LOG);
           p->bitpixs[p->numch]=DOUBLE_IMG;
+          */
           ++p->numch;
         }
     }
+
+
+  /* Reverse the list of channels into the input order. */
+  gal_data_reverse_ll(&p->chll);
 }
 
 
 
 
 
+/* Read the input(s)/channels. */
+static void
+ui_prepare_input_channels(struct converttparams *p)
+{
+  struct wcsprm *wcs=NULL;
+  size_t i, ndim, *dsize=NULL;
+  gal_data_t *tmp, *blank, *prev;
+
+  /* Fill in the channels linked list. */
+  ui_make_channels_ll(p);
+
+
+  /* Make sure there are 1 (for grayscale), 3 (for RGB) or 4 (for CMYK)
+     color channels. */
+  if(p->numch!=1 && p->numch!=3 && p->numch!=4)
+    error(EXIT_FAILURE, 0, "the number of input color channels has to be "
+          "1 (for non image data, grayscale or only K channel in CMYK), "
+          "3 (for RGB) and 4 (for CMYK). You have given %zu color channels. "
+          "Note that some file formats (for example JPEG in RGB mode) can "
+          "contain more than one color channel", p->numch);
+
+
+  /* Go over the channels and make the proper checks/corrections. We won't
+     be checking blank channels here, recall that blank channels had a
+     dimension of zero. */
+  for(tmp=p->chll; tmp!=NULL; tmp=tmp->next)
+    if(tmp->ndim>0)
+      {
+        /* Set the reference size (to check and also use for the blank
+           channels). */
+        if(dsize==NULL)
+          {
+            ndim=tmp->ndim;
+            dsize=tmp->dsize;
+          }
+        else
+          {
+            if(tmp->ndim!=ndim)
+              error(EXIT_FAILURE, 0, "All channels must have the same "
+                    "number of dimensions, the first input channel had "
+                    "%zu dimensions while atleast one other has %zu",
+                    ndim, tmp->ndim);
+            for(i=0;i<ndim;++i)
+              if(dsize[i]!=tmp->dsize[i])
+                error(EXIT_FAILURE, 0, "The length along each dimension of "
+                      "the channels must be the same");
+          }
+
+        /* Incase there is WCS information, also keep a pointer to the
+           first WCS information encountered. */
+        if(wcs==NULL && tmp->wcs)
+          wcs=tmp->wcs;
+      }
+
+
+  /* If ndim is still NULL, then there were no non-blank inputs, so print
+     an error. */
+  if(dsize==NULL)
+    error(EXIT_FAILURE, 0, "all the input(s) are of type blank");
+
+
+  /* Now, fill in the blank channels with zero valued arrays. */
+  prev=NULL;
+  for(tmp=p->chll; tmp!=NULL; tmp=tmp->next)
+    {
+      /* If this is a blank structure, then set it to a zero valued
+         array. */
+      if(tmp->ndim==0)
+        {
+          /* Make the blank data structure. */
+          blank=gal_data_alloc(NULL, GAL_DATA_TYPE_UCHAR, ndim, dsize,
+                               wcs, 1, p->cp.minmapsize, "blank channel",
+                               NULL, NULL);
+
+          /* We will use the status value of the data structuer to mark it
+             as one that was originally blank. */
+          blank->status=1;
+
+          /* If a previous node pointed to this old blank structure, then
+             correct it. */
+          if(prev) prev->next=blank; else p->chll=blank;
+
+          /* Set the next pointer of this one to same pointer that the old
+             blank pointer pointed to. */
+          blank->next=tmp->next;
+
+          /* Free the old data structure and put this one in its place. */
+          gal_data_free(tmp);
+          tmp=blank;
+        }
+
+      /* This is the final (to be used) data structure, so keep its pointer
+         in case the next one is blank and this structure's `next' element
+         must be corrected. */
+      prev=tmp;
+    }
+}
+
+
+
+
+
+/* We know cp->output is a known suffix, we just don't know if it has a `.`
+   before it or not. If it doesn't, one will be added to it and the output
+   name will be set using the automatic output function. */
+void
+ui_add_dot_use_automatic_output(struct converttparams *p)
+{
+  struct gal_linkedlist_stll *stll;
+  char *tmp, *firstname="output.txt", *suffix=p->cp.output;
+
+  /* Find the first non-blank file name in the input(s). */
+  for(stll=p->inputnames; stll!=NULL; stll=stll->next)
+    if(strcmp(stll->v, BLANK_CHANNEL_NAME))
+      {
+        firstname=stll->v;
+        break;
+      }
+
+  /* If the suffix does not start with a `.', put one there. */
+  if(suffix[0]!='.')
+    {
+      asprintf(&tmp, ".%s", suffix);
+      free(suffix);
+      suffix=tmp;
+    }
+
+  /* Set the automatic output and make sure we have write access. */
+  p->cp.output=gal_checkset_automatic_output(&p->cp, firstname, suffix);
+}
+
+
+
+
+
+/* Set output name, not that for ConvertType, the output option value is
+   mandatory (in `args.h'). So by the time the program reaches here, we
+   know it exists. */
+static void
+ui_set_output(struct converttparams *p)
+{
+  struct gal_options_common_params *cp=&p->cp;
+
+  /* Determine the type */
+  if(gal_fits_name_is_fits(cp->output))
+    {
+      p->outformat=OUT_FORMAT_FITS;
+      if( gal_fits_suffix_is_fits(cp->output) )
+        ui_add_dot_use_automatic_output(p);
+    }
+  else if(nameisjpeg(cp->output))
+    {
+#ifndef HAVE_LIBJPEG
+      error(EXIT_FAILURE, 0, "you have asked for a JPEG output, "
+            "however, when %s was configured libjpeg was not "
+            "available. To write to JPEG files, libjpeg is required. "
+            "Please install it and configure, make and install %s "
+            "again", PACKAGE_STRING, PACKAGE_STRING);
+#else
+      p->outformat=OUT_FORMAT_JPEG;
+      if( nameisjpegsuffix(cp->output) )
+        ui_add_dot_use_automatic_output(p);
+      if(p->quality==0)
+        error(EXIT_FAILURE, 0, "no quality specified for %s, please use the "
+              "`--quality' (`-q') option with a value between 1 (low "
+              "quality) and 100 (high quality) to specify a level",
+              p->cp.output);
+#endif
+    }
+  else if(nameiseps(cp->output))
+    {
+      p->outformat=OUT_FORMAT_EPS;
+      if( nameisepssuffix(cp->output) )
+        ui_add_dot_use_automatic_output(p);
+    }
+  else if(nameispdf(cp->output))
+    {
+      p->outformat=OUT_FORMAT_PDF;
+      if( nameispdfsuffix(cp->output) )
+        ui_add_dot_use_automatic_output(p);
+    }
+  else
+    {
+      p->outformat=OUT_FORMAT_TXT;
+
+      /* Plain text files don't have any unique set of suffixes. So, here,
+         we will just adopt two of the most common ones: `txt' or `dat'. If
+         the output is just one of these two suffixes, then we will use
+         automatic output to generate the full name, otherwise, we'll just
+         take the user's given value as the filename. */
+      if( strcmp(cp->output, "txt") && strcmp(cp->output, ".txt")
+          && strcmp(cp->output, "dat") && strcmp(cp->output, ".dat") )
+        ui_add_dot_use_automatic_output(p);
+
+      /* If output type is not an image, there should only be one color
+         channel: */
+      if(p->numch>1)
+        error(EXIT_FAILURE, 0, "text output (`--output=%s`) can only be "
+              "completed with one input color channel. You have given "
+              "%zu. Note that some formats (for example JPEG) can have "
+              "more than one color channel in each file. You can first "
+              "convert the file to FITS, then convert the desired "
+              "channel to text by specifying the HDU",
+              cp->output, p->numch);
+    }
+}
+
+
+
+
+
+void
+ui_preparations(struct converttparams *p)
+{
+  /* Convert the change string into the proper list. */
+  if(p->changestr)
+    p->change=ui_make_change_struct(p->changestr);
+
+  /* Read the input channels. */
+  ui_prepare_input_channels(p);
+
+  /* Set the output name. */
+  ui_set_output(p);
+}
+
+
+
+
+
+
 
 
 
@@ -681,39 +780,57 @@ preparearrays(struct converttparams *p)
 /**************************************************************/
 /************         Set the parameters          *************/
 /**************************************************************/
+
 void
-setparams(int argc, char *argv[], struct converttparams *p)
+ui_read_check_inputs_setup(int argc, char *argv[], struct converttparams *p)
 {
-  struct gal_commonparams *cp=&p->cp;
+  struct gal_options_common_params *cp=&p->cp;
+
+
+  /* Include the parameters necessary for argp from this program (`args.h')
+     and for the common options to all Gnuastro (`commonopts.h'). We want
+     to directly put the pointers to the fields in `p' and `cp', so we are
+     simply including the header here to not have to use long macros in
+     those headers which make them hard to read and modify. This also helps
+     in having a clean environment: everything in those headers is only
+     available within the scope of this function. */
+#include <commonopts.h>
+#include "args.h"
 
-  /* Set the non-zero initial values, the structure was initialized to
-     have a zero value for all elements. */
-  cp->spack         = SPACK;
-  cp->verb          = 1;
-  cp->numthreads    = num_processors(NPROC_CURRENT);
-  cp->removedirinfo = 1;
-  p->invert         = 1;
 
-  /* Read the arguments. */
+  /* Initialize the options and necessary information.  */
+  ui_initialize_options(p, program_options, gal_commonopts_options);
+
+
+  /* Read the command-line options and arguments. */
   errno=0;
   if(argp_parse(&thisargp, argc, argv, 0, 0, p))
     error(EXIT_FAILURE, errno, "parsing arguments");
 
-  /* Add the user default values and save them if asked. */
-  GAL_CONFIGFILES_CHECK_SET_CONFIG;
 
-  /* Check if all the required parameters are set. */
-  checkifset(p);
+  /* Read the configuration files and set the common values. */
+  gal_options_read_config_set(&p->cp);
+
 
-  /* Print the values for each parameter. */
-  if(cp->printparams)
-    GAL_CONFIGFILES_REPORT_PARAMETERS_SET;
+  /* Read the options into the program's structure, and check them and
+     their relations prior to printing. */
+  ui_read_check_only_options(p);
 
-  /* Prepare the arrays: */
-  preparearrays(p);
 
-  /* Do a sanity check. */
-  sanitycheck(p);
+  /* Print the option values if asked. Note that this needs to be done
+     after the option checks so un-sane values are not printed in the
+     output state. */
+  gal_options_print_state(&p->cp);
+
+
+  /* Check that the options and arguments fit well with each other. Note
+     that arguments don't go in a configuration file. So this test should
+     be done after (possibly) printing the option values. */
+  ui_check_options_and_arguments(p);
+
+
+  /* Read/allocate all the necessary starting arrays. */
+  ui_preparations(p);
 }
 
 
@@ -739,24 +856,11 @@ setparams(int argc, char *argv[], struct converttparams 
*p)
 /************      Free allocated, report         *************/
 /**************************************************************/
 void
-freeandreport(struct converttparams *p)
+ui_free_report(struct converttparams *p)
 {
-  size_t i;
-  struct gal_linkedlist_stll *tmp, *ttmp;
-
-  free(p->cp.hdu);
-  free(p->up.hdu2);
-  free(p->up.hdu3);
-  free(p->up.hdu4);
-  free(p->cp.output);
-  for(i=0;i<4;++i) free(p->ch[i]);
-
-  /* Free the input file names: */
-  tmp=p->inputnames;
-  while(tmp!=NULL)
-    {
-      ttmp=tmp->next;
-      free(tmp);
-      tmp=ttmp;
-    }
+  /* Free the allocated spaces */
+  gal_data_free(p->fluxlow);
+  gal_data_free(p->fluxhigh);
+  gal_linkedlist_free_stll(p->hdus, 1);
+  gal_linkedlist_free_stll(p->inputnames, 0);
 }
diff --git a/bin/convertt/ui.h b/bin/convertt/ui.h
index b31ffc5..442770c 100644
--- a/bin/convertt/ui.h
+++ b/bin/convertt/ui.h
@@ -5,7 +5,7 @@ ConvertType is part of GNU Astronomy Utilities (Gnuastro) 
package.
 Original author:
      Mohammad Akhlaghi <address@hidden>
 Contributing author(s):
-Copyright (C) 2015, Free Software Foundation, Inc.
+Copyright (C) 2016, Free Software Foundation, Inc.
 
 Gnuastro is free software: you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
@@ -23,13 +23,10 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #ifndef UI_H
 #define UI_H
 
-struct change *
-makechangestruct(char *arg);
-
 void
-setparams(int argc, char *argv[], struct converttparams *p);
+ui_read_check_inputs_setup(int argc, char *argv[], struct converttparams *p);
 
 void
-freeandreport(struct converttparams *p);
+ui_free_report(struct converttparams *p);
 
 #endif
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index a22c959..dc91c36 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -6534,17 +6534,16 @@ might be better demonstrated with a limited flux range.
 @noindent
 Input:
 @table @option
address@hidden --hdu2
-If the second input file is a FITS file, the value to this option will
-be used to specify which HDU will be used. Note that for the first
-file, the (@option{--hdu} or @option{-h} in the common options is
-used)
-
address@hidden --hdu3
-The HDU of the third input FITS file.
-
address@hidden --hdu4
-The HDU of the fourth input FITS file.
address@hidden -h STR/INT
address@hidden --hdu=STR/INT
+In ConvertType, it is possible to call the HDU option multiple times for
+the different input FITS files (corresponding to different color channels)
+in the same order that they are called on the command-line. Except for the
+fact that multiple calls are possible, this option is identical to the
+common @option{--hdu} in @ref{Input output}. The number of calls to this
+option cannot be less than the number of input FITS files, but if there are
+more, the extra HDUs will be ignored, note that they will be read in the
+order described in @ref{Configuration file precedence}.
 @end table
 
 @noindent
@@ -6687,23 +6686,15 @@ than @option{--fluxlow}, then this option is redundant.
 @itemx --fhmaxbyte=INT
 See @option{--flminbyte}.
 
address@hidden -l
address@hidden --log
-Display the logarithm of the input data. This is done after the
-conversion and flux truncation steps, see above.
 
address@hidden -n
address@hidden --noinvert
-For 8-bit output types (JPEG and EPS for example) the final value that
-is stored is inverted so white becomes black and vice versa. The
-reason for this is that astronomical images usually have a very large
-area of blank sky in them. The result will be that a large are of the
-image will be black. Therefore, by default the 8-bit values are
-inverted so the images blend in better with the text in a document.
-
-Note that this behaviour is ideal for grayscale images, if you want a
-color image, the colors are going to be mixed up. For color images it
-is best to call this option so the image is not inverted.
address@hidden -i
address@hidden --invert
+For 8-bit output types (JPEG, EPS, and PDF for example) the final value
+that is stored is inverted so white becomes black and vice versa. The
+reason for this is that astronomical images usually have a very large area
+of blank sky in them. The result will be that a large are of the image will
+be black. Note that this behaviour is ideal for grayscale images, if you
+want a color image, the colors are going to be mixed up.
 
 @end table
 
diff --git a/lib/arithmetic.c b/lib/arithmetic.c
index 686cf99..f56decb 100644
--- a/lib/arithmetic.c
+++ b/lib/arithmetic.c
@@ -97,17 +97,17 @@ arithmetic_not(gal_data_t *data, unsigned char flags)
   /* 'value' will only be read from one of these based on the
      datatype. Which the caller assigned. If there is any problem, it is
      their responsability, not this function's.*/
-  unsigned char     *uc = data->array,   *ucf = data->array + data->size, *o;
-  char               *c = data->array,    *cf = data->array + data->size;
-  unsigned short    *us = data->array,   *usf = data->array + data->size;
-  short              *s = data->array,    *sf = data->array + data->size;
-  unsigned int      *ui = data->array,   *uif = data->array + data->size;
-  int               *in = data->array,   *inf = data->array + data->size;
-  unsigned long     *ul = data->array,   *ulf = data->array + data->size;
-  long               *l = data->array,    *lf = data->array + data->size;
-  LONGLONG           *L = data->array,    *Lf = data->array + data->size;
-  float              *f = data->array,    *ff = data->array + data->size;
-  double             *d = data->array,    *df = data->array + data->size;
+  unsigned char     *uc = data->array,   *ucf = uc + data->size, *o;
+  char               *c = data->array,    *cf = c  + data->size;
+  unsigned short    *us = data->array,   *usf = us + data->size;
+  short              *s = data->array,    *sf = s  + data->size;
+  unsigned int      *ui = data->array,   *uif = ui + data->size;
+  int               *in = data->array,   *inf = in + data->size;
+  unsigned long     *ul = data->array,   *ulf = ul + data->size;
+  long               *l = data->array,    *lf = l  + data->size;
+  LONGLONG           *L = data->array,    *Lf = L  + data->size;
+  float              *f = data->array,    *ff = f  + data->size;
+  double             *d = data->array,    *df = d  + data->size;
 
 
   /* Allocate the output array. */
@@ -164,17 +164,17 @@ arithmetic_abs(unsigned char flags, gal_data_t *in)
 {
   gal_data_t *out;
 
-  unsigned char  *ouc,  *uc = in->array,   *ucf = in->array + in->size;
-  char            *oc,   *c = in->array,    *cf = in->array + in->size;
-  unsigned short *ous,  *us = in->array,   *usf = in->array + in->size;
-  short           *os,   *s = in->array,    *sf = in->array + in->size;
-  unsigned int   *oui,  *ui = in->array,   *uif = in->array + in->size;
-  int             *oi,  *ii = in->array,   *iif = in->array + in->size;
-  unsigned long  *oul,  *ul = in->array,   *ulf = in->array + in->size;
-  long            *ol,   *l = in->array,    *lf = in->array + in->size;
-  LONGLONG        *oL,   *L = in->array,    *Lf = in->array + in->size;
-  float           *of,   *f = in->array,    *ff = in->array + in->size;
-  double          *od,   *d = in->array,    *df = in->array + in->size;
+  unsigned char  *ouc,  *uc = in->array,   *ucf = uc + in->size;
+  char            *oc,   *c = in->array,    *cf = c  + in->size;
+  unsigned short *ous,  *us = in->array,   *usf = us + in->size;
+  short           *os,   *s = in->array,    *sf = s  + in->size;
+  unsigned int   *oui,  *ui = in->array,   *uif = ui + in->size;
+  int             *oi,  *ii = in->array,   *iif = ii + in->size;
+  unsigned long  *oul,  *ul = in->array,   *ulf = ul + in->size;
+  long            *ol,   *l = in->array,    *lf = l  + in->size;
+  LONGLONG        *oL,   *L = in->array,    *Lf = L  + in->size;
+  float           *of,   *f = in->array,    *ff = f  + in->size;
+  double          *od,   *d = in->array,    *df = d  + in->size;
 
   /* Set the output array. */
   if(flags & GAL_ARITHMETIC_INPLACE)
@@ -714,9 +714,9 @@ arithmetic_binary_function_flt(int operator, unsigned char 
flags,
 /***********************************************************************/
 #define DO_WHERE_OPERATION(ITT, OT) {                                \
     ITT *it=iftrue->array;                                           \
-    OT *o=out->array, *of=out->array+out->size;                      \
+    OT *o=out->array, *of=o+out->size;                               \
     if(iftrue->size==1)                                              \
-      do   *o = *c++ ? *it : *o;         while(++o<of);              \
+      do { *o = *c++ ? *it : *o;       } while(++o<of);              \
     else                                                             \
       do { *o = *c++ ? *it : *o; ++it; } while(++o<of);              \
 }
diff --git a/lib/data.c b/lib/data.c
index 212e3a4..17157c9 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -623,6 +623,7 @@ gal_data_initialize(gal_data_t *data, void *array, int type,
   /* Do the simple copying cases. For the display elements, set them all to
      impossible (negative) values so if not explicitly set by later steps,
      the default values are used if/when printing.*/
+  data->wcs=NULL;
   data->status=0;
   data->next=NULL;
   data->ndim=ndim;
@@ -961,8 +962,16 @@ gal_data_t *
 gal_data_pop_from_ll(gal_data_t **list)
 {
   struct gal_data_t *out;
+
+  /* Keep the top pointer. */
   out=*list;
+
+  /* Move the list pointer to the next node. */
   *list=out->next;
+
+  /* Set the next poitner of the out pointer to NULL so it isn't
+     interpretted as a list any more. */
+  out->next=NULL;
   return out;
 }
 
@@ -970,6 +979,27 @@ gal_data_pop_from_ll(gal_data_t **list)
 
 
 
+void
+gal_data_reverse_ll(gal_data_t **list)
+{
+  gal_data_t *popped, *in=*list, *reversed=NULL;
+
+  /* Only do the job if the list is not NULL and has more than one node. */
+  if( in && in->next )
+    {
+      while(in!=NULL)
+        {
+          popped=gal_data_pop_from_ll(&in);
+          gal_data_add_existing_to_ll(&reversed, popped);
+        }
+      *list=reversed;
+    }
+}
+
+
+
+
+
 size_t
 gal_data_num_in_ll(gal_data_t *list)
 {
diff --git a/lib/fits.c b/lib/fits.c
index 34667de..2bb8ea3 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -1447,11 +1447,18 @@ gal_fits_write_img_fitsptr(gal_data_t *data, char 
*filename)
   else
     fits_create_file(&fptr, filename, &status);
 
-  /* Create the FITS file and remove the two initial lines of comments */
+  /* Create the FITS file. */
   fits_create_img(fptr, gal_fits_type_to_bitpix(data->type),
                   data->ndim, naxes, &status);
+  gal_fits_io_error(status, NULL);
+
+  /* Remove the two comment lines put by CFITSIO. Note that in some cases,
+     it might not exist. When this happens, the status value will be
+     non-zero. We don't care about this error, so to be safe, we will just
+     reset the status variable after these calls. */
   fits_delete_key(fptr, "COMMENT", &status);
   fits_delete_key(fptr, "COMMENT", &status);
+  status=0;
 
   /* Write the image into the file. */
   fits_write_img(fptr, datatype, fpixel, data->size, data->array, &status);
diff --git a/lib/gnuastro/data.h b/lib/gnuastro/data.h
index c3431ca..2334b6a 100644
--- a/lib/gnuastro/data.h
+++ b/lib/gnuastro/data.h
@@ -269,6 +269,9 @@ gal_data_add_to_ll(gal_data_t **list, void *array, int 
type, size_t ndim,
 gal_data_t *
 gal_data_pop_from_ll(struct gal_data_t **list);
 
+void
+gal_data_reverse_ll(gal_data_t **list);
+
 size_t
 gal_data_num_in_ll(struct gal_data_t *list);
 
diff --git a/tests/convertt/blankch.sh b/tests/convertt/blankch.sh
index 99756bf..90641f6 100755
--- a/tests/convertt/blankch.sh
+++ b/tests/convertt/blankch.sh
@@ -53,4 +53,4 @@ fi
 
 # Actual test script
 # ==================
-$execname blank $img blank --output=blankch.jpg --noinvert
+$execname blank $img blank --output=blankch.jpg
diff --git a/tests/convertt/fitstojpeg.sh b/tests/convertt/fitstojpeg.sh
index 0ef651a..fd596e7 100755
--- a/tests/convertt/fitstojpeg.sh
+++ b/tests/convertt/fitstojpeg.sh
@@ -52,4 +52,4 @@ fi
 
 # Actual test script
 # ==================
-$execname $img --output=jpg
+$execname $img --invert --output=jpg
diff --git a/tests/convertt/fitstopdf.sh b/tests/convertt/fitstopdf.sh
index 827eca3..a5a7bb3 100755
--- a/tests/convertt/fitstopdf.sh
+++ b/tests/convertt/fitstopdf.sh
@@ -53,4 +53,4 @@ fi
 
 # Actual test script
 # ==================
-$execname $img --output=pdf --log
+$execname $img --output=pdf --invert
diff --git a/tmpfs-config-make b/tmpfs-config-make
index 656087a..db5c0d0 100755
--- a/tmpfs-config-make
+++ b/tmpfs-config-make
@@ -131,9 +131,9 @@ cd $build_dir
 # ####################################
 if [ ! -f Makefile ]; then
     $srcdir/configure --srcdir=$srcdir --disable-shared CFLAGS="-g -O0"       \
-                      --enable-arithmetic --enable-convolve --enable-cosmiccal\
-                      --enable-header --enable-imgcrop --enable-mkprof        \
-                      --enable-table
+                      --enable-arithmetic --enable-convertt --enable-convolve \
+                      --enable-cosmiccal --enable-header --enable-imgcrop     \
+                      --enable-mkprof --enable-table
 fi
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]