gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 31bb42e 1/2: Modular warping options in ImageW


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 31bb42e 1/2: Modular warping options in ImageWarp
Date: Fri, 21 Oct 2016 19:45:51 +0000 (UTC)

branch: master
commit 31bb42ec95b60a0fdd6ece25b91141a5bb58c2b6
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Modular warping options in ImageWarp
    
    ImageWarp now has options for various types of warpings: `--align',
    `--sheer', `--flip', `--project', `--rotate', `--scale',
    `--translate'. Each one of these options can be called on the command-line
    any number of times or in the configuration files. Previously the
    `--align', `--rotate' and `--scale' options could only be called once.
    
    By default the FITS coordinates (where the center of the pixel has an
    integer coordinate) are corrected with two translations at the start and
    end. However, the `--nofitscorrect' is now available to stop this
    correction if the user doesn't want it.
    
    This finishes task #13562.
---
 bin/imgwarp/args.h          |  131 ++++++---
 bin/imgwarp/astimgwarp.conf |    2 +-
 bin/imgwarp/main.h          |   25 +-
 bin/imgwarp/ui.c            |  670 +++++++++++++++++++++++++++++++------------
 bin/imgwarp/ui.h            |   25 +-
 doc/gnuastro.texi           |  194 +++++++++----
 6 files changed, 748 insertions(+), 299 deletions(-)

diff --git a/bin/imgwarp/args.h b/bin/imgwarp/args.h
index dbaa94a..ec54363 100644
--- a/bin/imgwarp/args.h
+++ b/bin/imgwarp/args.h
@@ -71,10 +71,10 @@ const char doc[] =
 
 /* Available letters for short options:
 
-   c e f g i j k l p t u v w x y
+   c g i j k l u v w x y
    A B C E F G H I J L M O Q R T U W X Y Z
 
-   Number keys used: <=502
+   Number keys used: <=503
 
    Options with keys (second structure element) larger than 500 do not
    have a short version.
@@ -110,6 +110,15 @@ static struct argp_option options[] =
       "Header keyword number to stop reading WCS.",
       1
     },
+    {
+      "nofitscorrect",
+      503,
+      0,
+      0,
+      "Do not shift to correct for FITS positioning.",
+      1
+    },
+
 
 
 
@@ -121,30 +130,6 @@ static struct argp_option options[] =
       2
     },
     {
-      "align",
-      'a',
-      0,
-      0,
-      "Align the image and celestial axes.",
-      1
-    },
-    {
-      "rotate",
-      'r',
-      "FLT",
-      0,
-      "Rotate by the given angle in degrees.",
-      1
-    },
-    {
-      "scale",
-      's',
-      "FLT",
-      0,
-      "Scale the image by the given factor.",
-      1
-    },
-    {
       "nowcscorrection",
       'n',
       0,
@@ -179,6 +164,72 @@ static struct argp_option options[] =
 
 
 
+
+    {
+      0, 0, 0, 0,
+      "Modular warpings:",
+      3
+    },
+    {
+      "align",
+      'a',
+      0,
+      0,
+      "Align the image and celestial axes.",
+      3
+    },
+    {
+      "rotate",
+      'r',
+      "FLT",
+      0,
+      "Rotate by the given angle in degrees.",
+      3
+    },
+    {
+      "scale",
+      's',
+      "FLT[,FLT]",
+      0,
+      "Scale along the given axis(es).",
+      3
+    },
+    {
+      "flip",
+      'f',
+      "FLT[,FLT]",
+      0,
+      "Flip along the given axis(es).",
+      3
+    },
+    {
+      "sheer",
+      'e',
+      "FLT[,FLT]",
+      0,
+      "Sheer along the given axis(es).",
+      3
+    },
+    {
+      "translate",
+      't',
+      "FLT[,FLT]",
+      0,
+      "Translate along the given axis(es).",
+      3
+    },
+    {
+      "project",
+      'p',
+      "FLT[,FLT]",
+      0,
+      "Project along the given axis(es).",
+      3
+    },
+
+
+
+
     {
       0, 0, 0, 0,
       "Operating modes:",
@@ -252,17 +303,33 @@ parse_opt(int key, char *arg, struct argp_state *state)
                                  SPACK, NULL, 0);
       p->up.maxblankfracset=1;
       break;
+    case 503:
+      p->up.nofitscorrect=1;
+      p->up.nofitscorrectset=1;
+      break;
+
+
+    /* Modular warpings */
     case 'a':
-      p->up.align=1;
-      p->up.alignset=1;
+      add_to_optionwapsll(&p->up.owll, ALIGN_WARP, NULL);
       break;
     case 'r':
-      gal_checkset_any_float(arg, &p->up.rotate, "rotate", key, SPACK, NULL, 
0);
-      p->up.rotateset=1;
+      add_to_optionwapsll(&p->up.owll, ROTATE_WARP, arg);
       break;
     case 's':
-      gal_checkset_any_float(arg, &p->up.scale, "scale", key, SPACK, NULL, 0);
-      p->up.scaleset=1;
+      add_to_optionwapsll(&p->up.owll, SCALE_WARP, arg);
+      break;
+    case 'f':
+      add_to_optionwapsll(&p->up.owll, FLIP_WARP, arg);
+      break;
+    case 'e':
+      add_to_optionwapsll(&p->up.owll, SHEER_WARP, arg);
+      break;
+    case 't':
+      add_to_optionwapsll(&p->up.owll, TRANSLATE_WARP, arg);
+      break;
+    case 'p':
+      add_to_optionwapsll(&p->up.owll, PROJECT_WARP, arg);
       break;
 
 
diff --git a/bin/imgwarp/astimgwarp.conf b/bin/imgwarp/astimgwarp.conf
index e3047ee..1017118 100644
--- a/bin/imgwarp/astimgwarp.conf
+++ b/bin/imgwarp/astimgwarp.conf
@@ -21,5 +21,5 @@
  hdu           0
 
 # Output:
- matrix        "0.2, 0, 0, 0.2"
+ scale         1.0
  maxblankfrac  0.8
\ No newline at end of file
diff --git a/bin/imgwarp/main.h b/bin/imgwarp/main.h
index 3c850ed..79233d7 100644
--- a/bin/imgwarp/main.h
+++ b/bin/imgwarp/main.h
@@ -41,6 +41,16 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 
 
+struct optionwarpsll
+{
+  int                   type;
+  double                  v1;
+  double                  v2;
+  struct optionwarpsll *next;
+};
+
+
+
 
 
 struct uiparams
@@ -49,12 +59,9 @@ struct uiparams
   char       *matrixname;  /* Name of transform file.                  */
   char     *matrixstring;  /* String containing transform elements.    */
 
-  int              align;  /* ==1: Align the image.                    */
-  float           rotate;  /* Rotation degrees in degrees.             */
-  float            scale;  /* Scaling factor.                          */
-  int           alignset;
-  int          rotateset;
-  int           scaleset;
+  struct optionwarpsll *owll;    /* List of 2D rotations.              */
+  int      nofitscorrect;  /* No corr the 0.5 pixel necessary in FITS. */
+  int   nofitscorrectset;
 
   int    matrixstringset;
   int    maxblankfracset;
@@ -69,16 +76,14 @@ struct uiparams
 struct imgwarpparams
 {
   /* Other structures: */
-  struct uiparams      up;  /* User interface parameters.                 */
+  struct uiparams      up;  /* User interface parameters.                */
   struct gal_commonparams cp; /* Common parameters.                      */
 
   /* Input: */
   double           *input;  /* Name of input FITS file.                  */
-  double          *matrix;  /* Warp/Transformation matrix.               */
+  double        matrix[9];  /* Warp/Transformation matrix.               */
   size_t              is0;  /* Number of rows in input image.            */
   size_t              is1;  /* Number of columns in input image.         */
-  size_t              ms0;  /* Matrix number of rows.                    */
-  size_t              ms1;  /* Matrix number of columns.                 */
   int         inputbitpix;  /* The type of the input array.              */
   int                nwcs;  /* Number of WCS structures.                 */
   struct wcsprm      *wcs;  /* Pointer to WCS structures.                */
diff --git a/bin/imgwarp/ui.c b/bin/imgwarp/ui.c
index fa4bc25..1afe816 100644
--- a/bin/imgwarp/ui.c
+++ b/bin/imgwarp/ui.c
@@ -138,28 +138,39 @@ readconfig(char *filename, struct imgwarpparams *p)
                                      SPACK, filename, lineno);
           up->maxblankfracset=1;
         }
-      else if(strcmp(name, "align")==0)
+      else if(strcmp(name, "nofitscorrect")==0)
         {
-          if(up->alignset) continue;
-          gal_checkset_int_zero_or_one(value, &up->align, name, key,
-                                       SPACK, filename, lineno);
-          up->alignset=1;
+          if(up->nofitscorrectset) continue;
+          gal_checkset_int_zero_or_one(value, &up->nofitscorrect, name,
+                                       key, SPACK, filename, lineno);
+          up->nofitscorrectset=1;
         }
+
+
+
+
+
+      /* Modular warpings */
+      else if(strcmp(name, "align")==0)
+        add_to_optionwapsll(&p->up.owll, ALIGN_WARP, NULL);
+
       else if(strcmp(name, "rotate")==0)
-        {
-          if(up->rotateset) continue;
-          gal_checkset_any_float(value, &up->rotate, name, key, SPACK,
-                                 filename, lineno);
-          up->rotateset=1;
-        }
+        add_to_optionwapsll(&p->up.owll, ROTATE_WARP, value);
+
       else if(strcmp(name, "scale")==0)
-        {
-          if(up->scaleset) continue;
-          gal_checkset_any_float(value, &up->scale, name, key, SPACK,
-                                 filename, lineno);
-          up->scaleset=1;
-        }
+        add_to_optionwapsll(&p->up.owll, SCALE_WARP, value);
+
+      else if(strcmp(name, "flip")==0)
+        add_to_optionwapsll(&p->up.owll, FLIP_WARP, value);
+
+      else if(strcmp(name, "sheer")==0)
+        add_to_optionwapsll(&p->up.owll, SHEER_WARP, value);
 
+      else if(strcmp(name, "translate")==0)
+        add_to_optionwapsll(&p->up.owll, TRANSLATE_WARP, value);
+
+      else if(strcmp(name, "project")==0)
+        add_to_optionwapsll(&p->up.owll, PROJECT_WARP, value);
 
 
 
@@ -200,12 +211,6 @@ printvalues(FILE *fp, struct imgwarpparams *p)
   fprintf(fp, "\n# Output parameters:\n");
   if(up->matrixstringset)
     GAL_CHECKSET_PRINT_STRING_MAYBE_WITH_SPACE("matrix", up->matrixstring);
-  if(up->alignset)
-    fprintf(fp, CONF_SHOWFMT"%d\n", "align", up->align);
-  if(up->rotateset)
-    fprintf(fp, CONF_SHOWFMT"%.3f\n", "rotate", up->rotate);
-  if(up->scaleset)
-    fprintf(fp, CONF_SHOWFMT"%.3f\n", "scale", up->scale);
 
   if(cp->outputset)
     GAL_CHECKSET_PRINT_STRING_MAYBE_WITH_SPACE("output", cp->output);
@@ -214,6 +219,13 @@ printvalues(FILE *fp, struct imgwarpparams *p)
     fprintf(fp, CONF_SHOWFMT"%.3f\n", "maxblankfrac", p->maxblankfrac);
 
 
+
+  fprintf(fp, "\n# Modular transformations:\n");
+  if(up->nofitscorrectset)
+    fprintf(fp, CONF_SHOWFMT"%d\n", "nofitscorrect", up->nofitscorrect);
+
+
+
   /* For the operating mode, first put the macro to print the common
      options, then the (possible options particular to this
      program). */
@@ -261,52 +273,259 @@ checkifset(struct imgwarpparams *p)
 
 
 
-
 /**************************************************************/
-/***************       Prepare Matrix       *******************/
+/**********      Modular matrix linked list       *************/
 /**************************************************************/
 void
-readmatrixoption(struct imgwarpparams *p)
+add_to_optionwapsll(struct optionwarpsll **list, int type, char *value)
 {
-  size_t counter=0;
-  char *t, *tailptr;
+  double v1=NAN, v2=NAN;
+  char *tailptr, *secondstr;
+  struct optionwarpsll *newnode;
 
   /* Allocate the necessary space. */
   errno=0;
-  p->matrix=malloc(9*sizeof *p->matrix);
-  if(p->matrix==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for temporary array to keep "
-          "the matrix option", 9*sizeof *p->matrix);
-
-  /* Go over the string and set the values. */
-  t=p->up.matrixstring;
-  while(*t!='\0')
+  newnode=malloc(sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno, "%zu bytes for newnode in "
+          "add_to_optionwarpsll", sizeof *newnode);
+
+  /* Read the numbers when necessary. */
+  if(value)
     {
-      switch(*t)
+      /* Parse the first number */
+      v1=strtod(value, &tailptr);
+      if(tailptr==value)
+        error(EXIT_FAILURE, 0, "The start of the string `%s' could not be "
+              "read as a number", value);
+
+      /* If there is any white space characters, ignore them and make sure
+         that the first character is a coma (`,'). */
+      secondstr=tailptr;
+      while(isspace(*secondstr)) ++secondstr;
+      if(*secondstr==',')
         {
-        case ' ': case '\t': case ',':
-          ++t;
-          break;
-        default:
-          errno=0;
-          p->matrix[counter++]=strtod(t, &tailptr);
-          if(errno) error(EXIT_FAILURE, errno, "In reading `%s`", t);
-          if(tailptr==t)
-            error(EXIT_FAILURE, 0, "the provided string `%s' for matrix "
-                  "could not be read as a number", t);
-          t=tailptr;
-          if(counter>9)       /* Note that it was ++'d! */
-            error(EXIT_FAILURE, 0, "there are %zu elements in `%s', there "
-                  "should be 4 or 9", counter, p->up.matrixstring);
-          /*printf("%f, %s\n", p->matrix[counter-1], t);*/
+          /* If the type is rotate, then print an error since rotate only
+             needs one input, not two. */
+          if(type==ROTATE_WARP)
+            error(EXIT_FAILURE, 0, "The `--rotate' (`-r') option only needs "
+                  "one input number, not more. It was given `%s'", value);
+
+          /* Ignore the coma. */
+          ++secondstr;
+
+          /* Read the second number: */
+          v2=strtod(secondstr, &tailptr);
+          if(tailptr==secondstr)
+            error(EXIT_FAILURE, 0, "The second part (after the coma) of "
+                  "`%s' (`%s') could not be read as a number", value,
+                  secondstr);
+        }
+
+      /* If there was only one number given, secondstr will be '\0' when
+         control reaches here. */
+      else if(*secondstr!='\0')
+        error(EXIT_FAILURE, 0, "the character between the two numbers (`%s') "
+              "must be a coma (`,')\n", value);
+    }
+
+  /* Put in the values. Note that both v1 and v2 were initialized to NaN,
+     so if v2 is not given, it will be NaN and the later function can
+     decide what it wants to replace it with.*/
+  newnode->v1=v1;
+  newnode->v2=v2;
+  newnode->type=type;
+  newnode->next=*list;
+
+  /* Set list to point to the new node. */
+  *list=newnode;
+}
+
+
+
+
+
+/* Allocate space for a new node: */
+struct optionwarpsll *
+alloc_owll_node(void)
+{
+  struct optionwarpsll *newnode;
+
+  errno=0;
+  newnode=malloc(sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno, "%zu bytes for newnode in "
+          "add_to_optionwarpsll", sizeof *newnode);
+
+  return newnode;
+}
+
+
+
+
+
+/* The input list of warpings are recorded in a last-in-first-out order. So
+   we reverse the order and also add the transformations necessary for the
+   FITS definition (where the center of the pixel has a value of 1, not its
+   corner. */
+void
+prepare_optionwapsll(struct imgwarpparams *p)
+{
+  struct optionwarpsll *tmp, *next, *newnode, *prepared=NULL;
+
+  /* Add the FITS correction for the first warp (before everything else).
+
+     IMPORTANT: This is the last transform that will be done, so we have to
+     translate the image by -0.5.*/
+  if(!p->up.nofitscorrect)
+    {
+      newnode = alloc_owll_node();
+      newnode->v1 = newnode->v2 = -0.5f;
+      newnode->type = TRANSLATE_WARP;
+      newnode->next = prepared;
+      prepared = newnode;
+    }
+
+  /* Put in the rest of the warpings */
+  tmp=p->up.owll;
+  while(tmp!=NULL)
+    {
+      /* Allocate space for the new element, and put the values in. */
+      newnode = alloc_owll_node();
+      newnode->v1 = tmp->v1;
+      newnode->v2 = tmp->v2;
+      newnode->type = tmp->type;
+      newnode->next = prepared;
+
+      /* Now that previous nodes have been linked to next, set the
+         reversed to the new node. */
+      prepared = newnode;
+
+      /* Now keep the next element and free the old allocated space. */
+      next = tmp->next;
+      free(tmp);
+      tmp = next;
+    }
+
+  /* Add the FITS correction for the last warp (after everything else).
+
+     IMPORTANT: This is the first transform that will be done, so we have
+     to translate the image by +0.5.*/
+  if(!p->up.nofitscorrect)
+    {
+      newnode = alloc_owll_node();
+      newnode->v1 = newnode->v2 = 0.5f;
+      newnode->type = TRANSLATE_WARP;
+      newnode->next = prepared;
+      prepared = newnode;
+    }
+
+  /* Put the pointer in the output */
+  p->up.owll=prepared;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**************************************************************/
+/*************      Fill temporary matrix     *****************/
+/**************************************************************/
+void
+read_matrix(struct imgwarpparams *p)
+{
+  char *t, *tailptr;
+  size_t i, counter=0, m0, m1;
+  double *matrix=p->matrix, rmatrix[9], *fmatrix;
+
+  /* Read the matrix either as a file or from the command-line. */
+  if(p->up.matrixname)
+    {
+      gal_txtarray_txt_to_array(p->up.matrixname, &fmatrix, &m0, &m1);
+      counter=m0*m1;
+      for(i=0;i<(counter<9 ? counter : 9);++i)
+        rmatrix[i]=fmatrix[i];
+      free(fmatrix);
+    }
+  else
+    {
+      t=p->up.matrixstring;
+      while(*t!='\0')
+        {
+          switch(*t)
+            {
+            case ' ': case '\t': case ',':
+              ++t;
+              break;
+            default:
+              errno=0;
+              rmatrix[counter++]=strtod(t, &tailptr);
+              if(errno) error(EXIT_FAILURE, errno, "reading `%s`", t);
+              if(tailptr==t)
+                error(EXIT_FAILURE, 0, "the provided string `%s' for "
+                      "matrix could not be read as a number", t);
+              t=tailptr;
+              if(counter>9)       /* Note that it was incremented! */
+                error(EXIT_FAILURE, 0, "there are %zu elements in `%s', "
+                      "there should be 4 or 9", counter, p->up.matrixstring);
+              /*printf("%f, %s\n", p->matrix[counter-1], t);*/
+            }
         }
     }
 
-  /* Add the other necessary information: */
+  /* If there was 4 elements (a 2 by 2 matrix), put them into a 3 by 3
+     matrix. */
   if(counter==4)
-    p->ms1=p->ms0=2;
+    {
+      /* Fill in the easy 3 by 3 matrix: */
+      matrix[0]=rmatrix[0];   matrix[1]=rmatrix[1];
+      matrix[3]=rmatrix[2];   matrix[4]=rmatrix[3];
+      matrix[6]=0.0f;         matrix[7]=0.0f;         matrix[8]=1.0f;
+
+      /* If we need to correct for the FITS standard, then correc the last
+         two elements. Recall that the coordinates of the center of the
+         first pixel in the FITS standard are 1. We want 0 to be the
+         coordinates of the bottom corner of the image.
+
+         1  0  0.5      a  b  0      a  b  0.5
+         0  1  0.5   *  c  d  0   =  c  d  0.5
+         0  0   1       0  0  1      0  0   1
+
+         and
+
+         a  b  0.5     1  0  -0.5     a  b  (a*-0.5)+(b*-0.5)+0.5
+         c  d  0.5  *  0  1  -0.5  =  c  d  (c*-0.5)+(d*-0.5)+0.5
+         0  0   1      0  0   1       0  0           1
+      */
+      if(p->up.nofitscorrect)
+        matrix[2] = matrix[5] = 0.0f;
+      else
+        {
+          matrix[2] = ((rmatrix[0] + rmatrix[1]) * -0.5f) + 0.5f;
+          matrix[5] = ((rmatrix[2] + rmatrix[3]) * -0.5f) + 0.5f;
+        }
+    }
   else if (counter==9)
-    p->ms1=p->ms0=3;
+    {
+      matrix[0]=rmatrix[0];   matrix[1]=rmatrix[1];   matrix[2]=rmatrix[2];
+      matrix[3]=rmatrix[3];   matrix[4]=rmatrix[4];   matrix[5]=rmatrix[5];
+      matrix[6]=rmatrix[6];   matrix[7]=rmatrix[7];   matrix[8]=rmatrix[8];
+    }
   else
     error(EXIT_FAILURE, 0, "there are %zu numbers in the string `%s'! "
           "It should contain 4 or 9 numbers (for a 2 by 2 or 3 by 3 "
@@ -320,9 +539,10 @@ readmatrixoption(struct imgwarpparams *p)
 /* Set the matrix so the image is aligned with the axises. Note that
    WCSLIB automatically fills the CRPI */
 void
-makealignmatrix(struct imgwarpparams *p)
+makealignmatrix(struct imgwarpparams *p, double *tmatrix)
 {
   double A, dx, dy;
+  double amatrix[4];
   double w[4]={0,0,0,0};
 
   /* Check if there is only two WCS axises: */
@@ -356,14 +576,6 @@ makealignmatrix(struct imgwarpparams *p)
      using the scale along the image X axis for both values. */
   gal_wcs_pixel_scale_deg(p->wcs, &dx, &dy);
 
-  /* Allocate space for the matrix: */
-  errno=0;
-  p->matrix=malloc(4*sizeof *p->matrix);
-  if(p->matrix==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for p->matrix in makealignmatrix",
-          4*sizeof *p->matrix);
-  p->ms0=p->ms1=2;
-
   /* Lets call the given WCS orientation `W', the rotation matrix we want
      to find as `X' and the final (aligned matrix) to have just one useful
      value: `a' (which is the pixel scale):
@@ -403,12 +615,23 @@ makealignmatrix(struct imgwarpparams *p)
        --> x3 = a / w1 / A
        --> x2 = -1 * x3 * w2 / w0
 
+    Note that when the image is already aligned, a unity matrix should be
+    output.
    */
-  A = (w[3]/w[1]) - (w[2]/w[0]);
-  p->matrix[1] = dx / w[0] / A;
-  p->matrix[3] = dx / w[1] / A;
-  p->matrix[0] = -1 * p->matrix[1] * w[3] / w[1];
-  p->matrix[2] = -1 * p->matrix[3] * w[2] / w[0];
+  if( w[1]==0.0f && w[2]==0.0f )
+    {
+      amatrix[0]=1.0f;   amatrix[1]=0.0f;
+      amatrix[2]=0.0f;   amatrix[3]=1.0f;
+    }
+  else
+    {
+      A = (w[3]/w[1]) - (w[2]/w[0]);
+      amatrix[1] = dx / w[0] / A;
+      amatrix[3] = dx / w[1] / A;
+      amatrix[0] = -1 * amatrix[1] * w[3] / w[1];
+      amatrix[2] = -1 * amatrix[3] * w[2] / w[0];
+    }
+
 
   /* For a check:
   printf("dx: %e\n", dx);
@@ -416,41 +639,73 @@ makealignmatrix(struct imgwarpparams *p)
   printf("  %.8e    %.8e\n", w[0], w[1]);
   printf("  %.8e    %.8e\n", w[2], w[3]);
   printf("x:\n");
-  printf("  %.8e    %.8e\n", p->matrix[0], p->matrix[1]);
-  printf("  %.8e    %.8e\n", p->matrix[2], p->matrix[3]);
+  printf("  %.8e    %.8e\n", amatrix[0], amatrix[1]);
+  printf("  %.8e    %.8e\n", amatrix[2], amatrix[3]);
   */
+
+
+  /* Put the matrix elements into the ouput array: */
+  tmatrix[0]=amatrix[0];  tmatrix[1]=amatrix[1]; tmatrix[2]=0.0f;
+  tmatrix[3]=amatrix[2];  tmatrix[4]=amatrix[3]; tmatrix[5]=0.0f;
+  tmatrix[6]=0.0f;        tmatrix[7]=0.0f;       tmatrix[8]=1.0f;
 }
 
 
 
 
 
-/* Create rotation matrix */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**************************************************************/
+/***************       Prepare Matrix       *******************/
+/**************************************************************/
+/* This function is mainly for easy checking/debugging. */
 void
-makebasicmatrix(struct imgwarpparams *p)
+printmatrix(double *matrix)
 {
-  struct uiparams *up=&p->up;
+  printf("%-10.3f%-10.3f%-10.3f\n", matrix[0], matrix[1], matrix[2]);
+  printf("%-10.3f%-10.3f%-10.3f\n", matrix[3], matrix[4], matrix[5]);
+  printf("%-10.3f%-10.3f%-10.3f\n", matrix[6], matrix[7], matrix[8]);
+}
 
-  /* Allocate space for the matrix: */
-  errno=0;
-  p->matrix=malloc(4*sizeof *p->matrix);
-  if(p->matrix==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for p->matrix in makerotationmatrix",
-          4*sizeof *p->matrix);
-  p->ms0=p->ms1=2;
-
-  /* Put in the elements */
-  if(up->rotateset)
-    {
-      p->matrix[1] = sin( up->rotate*M_PI/180 );
-      p->matrix[2] = p->matrix[1] * -1.0f;
-      p->matrix[3] = p->matrix[0] = cos( up->rotate*M_PI/180 );
-    }
-  else if (up->scaleset)
-    {
-      p->matrix[1] = p->matrix[2] = 0.0f;
-      p->matrix[0] = p->matrix[3] = up->scale;
-    }
+
+
+
+
+void
+inplace_matrix_multiply(double *in, double *with)
+{
+  /* `tin' will keep the values of the input array because we want to
+     write the multiplication result in the input array. */
+  double tin[9]={in[0],in[1],in[2],in[3],in[4],in[5],in[6],in[7],in[8]};
+
+  /* For easy checking, here are the matrix/memory layouts:
+          tin[0] tin[1] tin[2]     with[0] with[1] with[2]
+          tin[3] tin[4] tin[5]  *  with[3] with[4] with[5]
+          tin[6] tin[7] tin[8]     with[6] with[7] with[8]   */
+  in[0] = tin[0]*with[0] + tin[1]*with[3] + tin[2]*with[6];
+  in[1] = tin[0]*with[1] + tin[1]*with[4] + tin[2]*with[7];
+  in[2] = tin[0]*with[2] + tin[1]*with[5] + tin[2]*with[8];
+
+  in[3] = tin[3]*with[0] + tin[4]*with[3] + tin[5]*with[6];
+  in[4] = tin[3]*with[1] + tin[4]*with[4] + tin[5]*with[7];
+  in[5] = tin[3]*with[2] + tin[4]*with[5] + tin[5]*with[8];
+
+  in[6] = tin[6]*with[0] + tin[7]*with[3] + tin[8]*with[6];
+  in[7] = tin[6]*with[1] + tin[7]*with[4] + tin[8]*with[7];
+  in[8] = tin[6]*with[2] + tin[7]*with[5] + tin[8]*with[8];
 }
 
 
@@ -459,99 +714,122 @@ makebasicmatrix(struct imgwarpparams *p)
 
 /* Fill in the warping matrix elements based on the options/arguments */
 void
-preparematrix(struct imgwarpparams *p)
+prepare_modular_matrix(struct imgwarpparams *p)
 {
-  double *tmp;
-  int mcheck=0;
+  int f1, f2;                   /* For flipping. */
+  double s, c, tmatrix[9];
   struct uiparams *up=&p->up;
+  struct optionwarpsll *tmp, *next;
 
-  /* Make sure that none of the matrix creation options/arguments are given
-     together. Note that a matrix string is optional (will only be used if
-     there is no matrix file). */
-  mcheck = ( up->alignset + up->rotateset + up->scaleset +
-             (up->matrixname!=NULL) );
-  if( mcheck > 1 )
-    error(EXIT_FAILURE, 0, "More than one method to define the warping "
-          "matrix has been given. Please only specify one.");
 
+  /* Allocate space for the matrix, then initialize it. */
+  p->matrix[0]=1.0f;     p->matrix[1]=0.0f;     p->matrix[2]=0.0f;
+  p->matrix[3]=0.0f;     p->matrix[4]=1.0f;     p->matrix[5]=0.0f;
+  p->matrix[6]=0.0f;     p->matrix[7]=0.0f;     p->matrix[8]=1.0f;
 
-  /* Read the input image WCS structure. We are doing this here because
-     some of the matrix operations might need it. */
-  gal_fits_read_wcs(up->inputname, p->cp.hdu, p->hstartwcs,
-                    p->hendwcs, &p->nwcs, &p->wcs);
 
+  /* The linked list is last-in-first-out, so we need to reverse it to
+     easily apply the changes in the same order that was read in. */
+  prepare_optionwapsll(p);
 
-  /* Depending on the given situation make the matrix. */
-  if(up->alignset)
-    makealignmatrix(p);
-  else if( up->rotateset || up->scaleset)
-    makebasicmatrix(p);
-  else
+
+  /* Do all the operations */
+  tmp=up->owll;
+  while(tmp!=NULL)
     {
-      if(up->matrixname)
-        gal_txtarray_txt_to_array(up->matrixname, &p->matrix,
-                                  &p->ms0, &p->ms1);
-      else
+      /* Fill `tmatrix' depending on the type of the warp. */
+      switch(tmp->type)
         {
-          /* Check if a matrix string is actually present. */
-          if(up->matrixstringset==0)
-            error(EXIT_FAILURE, 0, "no warping matrix string has been and "
-                  "no other means of making the warping matrix (a file or "
-                  "other options have been specified");
-          readmatrixoption(p);
-        }
-  }
+        case ALIGN_WARP:
+          makealignmatrix(p, tmatrix);
+          break;
 
+        case ROTATE_WARP:
+          s = sin( tmp->v1*M_PI/180 );
+          c = cos( tmp->v1*M_PI/180 );
+          tmatrix[0]=c;        tmatrix[1]=s;     tmatrix[2]=0.0f;
+          tmatrix[3]=-1.0f*s;  tmatrix[4]=c;     tmatrix[5]=0.0f;
+          tmatrix[6]=0.0f;     tmatrix[7]=0.0f;  tmatrix[8]=1.0f;
+          break;
 
-  /* Convert a 2 by 2 matrix into a 3 by 3 matrix and also correct it for
-     the FITS definition. */
-  if(p->ms0==2 && p->ms1==2)
-    {
-      errno=0;
-      tmp=malloc(9*sizeof *tmp);
-      if(tmp==NULL)
-        error(EXIT_FAILURE, errno, "%zu bytes for 3 by 3 matrix",
-              9*sizeof *tmp);
-
-      /* Put the four identical elements in place. */
-      tmp[0]=p->matrix[0];
-      tmp[1]=p->matrix[1];
-      tmp[3]=p->matrix[2];
-      tmp[4]=p->matrix[3];
-
-      /* Add the other elements. Note that we need to correct for the FITS
-         standard that defines the coordinates of the center of the first
-         pixel in the image to be 1. We want 0 to be the coordinates of the
-         bottom corner of the image.
-
-         1  0  0.5     a  b  0     a  b  0.5
-         0  1  0.5  *  c  d  0  =  c  d  0.5
-         0  0   1      0  0  1     0  0   1
+        case SCALE_WARP:
+          if( isnan(tmp->v2) ) tmp->v2=tmp->v1;
+          tmatrix[0]=tmp->v1;  tmatrix[1]=0.0f;     tmatrix[2]=0.0f;
+          tmatrix[3]=0.0f;     tmatrix[4]=tmp->v2;  tmatrix[5]=0.0f;
+          tmatrix[6]=0.0f;     tmatrix[7]=0.0f;     tmatrix[8]=1.0f;
+          break;
 
-         and
+        case FLIP_WARP:
+          /* For the flip, the values dont really matter! As long as the
+             value is non-zero, the flip in the respective axis will be
+             made. Note that the second axis is optional (can be NaN), but
+             the first axis is required.*/
+          f1 = tmp->v1==0.0f ? 0 : 1;
+          f2 = isnan(tmp->v2) ? 0 : ( tmp->v2==0.0f ? 0 : 1);
+          if( f1 && !f2  )
+            {
+              tmatrix[0]=1.0f;   tmatrix[1]=0.0f;
+              tmatrix[3]=0.0f;   tmatrix[4]=-1.0f;
+            }
+          else if ( !f1 && f2 )
+            {
+              tmatrix[0]=-1.0f;  tmatrix[1]=0.0f;
+              tmatrix[3]=0.0f;   tmatrix[4]=1.0f;
+            }
+          else
+            {
+              tmatrix[0]=-1.0f;  tmatrix[1]=0.0f;
+              tmatrix[3]=0.0f;   tmatrix[4]=-1.0f;
+            }
+                                                      tmatrix[2]=0.0f;
+                                                      tmatrix[5]=0.0f;
+          tmatrix[6]=0.0f;       tmatrix[7]=0.0f;     tmatrix[8]=1.0f;
+          break;
 
-         a  b  0.5     1  0  -0.5     a  b  (a*-0.5)+(b*-0.5)+0.5
-         c  d  0.5  *  0  1  -0.5  =  c  d  (c*-0.5)+(d*-0.5)+0.5
-         0  0   1      0  0   1       0  0           1
+        case SHEER_WARP:
+          if( isnan(tmp->v2) ) tmp->v2=tmp->v1;
+          tmatrix[0]=1.0f;     tmatrix[1]=tmp->v1;    tmatrix[2]=0.0f;
+          tmatrix[3]=tmp->v2;  tmatrix[4]=1.0f;       tmatrix[5]=0.0f;
+          tmatrix[6]=0.0f;     tmatrix[7]=0.0f;       tmatrix[8]=1.0f;
+          break;
+
+        case TRANSLATE_WARP:
+          if( isnan(tmp->v2) ) tmp->v2=tmp->v1;
+          tmatrix[0]=1.0f;     tmatrix[1]=0.0f;       tmatrix[2]=tmp->v1;
+          tmatrix[3]=0.0f;     tmatrix[4]=1.0f;       tmatrix[5]=tmp->v2;
+          tmatrix[6]=0.0f;     tmatrix[7]=0.0f;       tmatrix[8]=1.0f;
+          break;
+
+        case PROJECT_WARP:
+          if( isnan(tmp->v2) ) tmp->v2=tmp->v1;
+          tmatrix[0]=1.0f;     tmatrix[1]=0.0f;       tmatrix[2]=0.0f;
+          tmatrix[3]=0.0f;     tmatrix[4]=1.0f;       tmatrix[5]=0.0f;
+          tmatrix[6]=tmp->v1;  tmatrix[7]=tmp->v2;    tmatrix[8]=1.0f;
+          break;
+
+        default:
+          error(EXIT_FAILURE, 0, "a bug! Please contact us at %s so we can "
+                "address the problem. For some reason the value of tmp->type "
+                "in `prepare_modular_matrix' of ui.c is not recognized. "
+                "This is an internal, not a user issue. So please let us "
+                "know.", PACKAGE_BUGREPORT);
+        }
+
+      /* Multiply this matrix with the main matrix in-place. */
+      inplace_matrix_multiply(p->matrix, tmatrix);
+
+      /* Keep the next element and free the node's allocated space. */
+      next = tmp->next;
+      free(tmp);
+      tmp = next;
+
+      /* For a check:
+      printf("tmatrix:\n");
+      printmatrix(tmatrix);
+      printf("out:\n");
+      printmatrix(p->matrix);
       */
-      tmp[8] = 1.0f;
-      tmp[6] = tmp[7] = 0.0f;
-      tmp[2] = ((p->matrix[0] + p->matrix[1]) * -0.5f) + 0.5f;
-      tmp[5] = ((p->matrix[2] + p->matrix[3]) * -0.5f) + 0.5f;
-
-      /* Free the previously allocated 2D matrix and put the put the newly
-         allocated array with correct values in it. */
-      free(p->matrix);
-      p->matrix=tmp;
-
-      /* Set the new sizes */
-      p->ms0=p->ms1==3;
     }
-  else if (p->ms0!=3 || p->ms1!=3)
-    error(EXIT_FAILURE, 0, "a bug! please contact us at %s so we can "
-          "address the problem. For some reason p->ms0=%zu and p->ms1=%zu! "
-          "They should both have a value of 3.", PACKAGE_BUGREPORT,
-          p->ms0, p->ms1);
 }
 
 
@@ -592,30 +870,37 @@ sanitycheck(struct imgwarpparams *p)
                                   p->cp.removedirinfo, p->cp.dontdelete,
                                   &p->cp.output);
 
+  /* If an actual matrix is given, then it will be used and all modular
+     warpings will be ignored. */
+  if(p->up.matrixstring || p->up.matrixname)
+    read_matrix(p);
+  else if (p->up.owll)
+    prepare_modular_matrix(p);
+  else
+    error(EXIT_FAILURE, 0, "No input matrix specified.\n\nPlease either "
+          "use the modular warp options like `--rotate' or `--scale', "
+          "or directly specify the matrix on the command-line, or in the "
+          "configuration files.\n\nRun with `--help' for the full list of "
+          "modular warpings (among other options), or see the manual's "
+          "`Warping basics' section for more on the matrix.");
 
-  /* Check the size of the input matrix, note that it might only have
-     the wrong numbers when it is read from a file. */
-  if(p->up.matrixname)
-     if( (p->ms0 != 2 && p->ms0 != 3) || p->ms0 != p->ms1 )
-       error(EXIT_FAILURE, 0, "the given matrix in %s has %zu rows and "
-             "%zu columns. Its size must be either 2x2 or 3x3",
-             p->up.matrixname, p->ms0, p->ms1);
 
   /* Check if there are any non-normal numbers in the matrix: */
-  df=(d=m)+p->ms0*p->ms1;
+  df=(d=p->matrix)+9;
   do
     if(!isfinite(*d++))
-      error(EXIT_FAILURE, 0, "%f is not a `normal' number", *(d-1));
+      {
+        printmatrix(p->matrix);
+        error(EXIT_FAILURE, 0, "%f is not a `normal' number in the "
+              "input matrix shown above", *(d-1));
+      }
   while(d<df);
 
   /* Check if the determinant is not zero: */
-  if( ( p->ms0==2 && (m[0]*m[3] - m[1]*m[2] == 0) )
-      ||
-      ( p->ms0==3 &&
-        (m[0]*m[4]*m[8] + m[1]*m[5]*m[6] + m[2]*m[3]*m[7]
-         - m[2]*m[4]*m[6] - m[1]*m[3]*m[8] - m[0]*m[5]*m[7] == 0) ) )
-      error(EXIT_FAILURE, 0, "the determinant of the given matrix "
-            "is zero");
+  if( m[0]*m[4]*m[8] + m[1]*m[5]*m[6] + m[2]*m[3]*m[7]
+      - m[2]*m[4]*m[6] - m[1]*m[3]*m[8] - m[0]*m[5]*m[7] == 0 )
+    error(EXIT_FAILURE, 0, "the determinant of the given matrix "
+          "is zero");
 
   /* Check if the transformation is spatially invariant */
 }
@@ -724,7 +1009,9 @@ setparams(int argc, char *argv[], struct imgwarpparams *p)
   cp->verb          = 1;
   cp->numthreads    = num_processors(NPROC_CURRENT);
   cp->removedirinfo = 1;
+
   p->correctwcs     = 1;
+  p->up.owll        = NULL;
 
   /* Read the arguments. */
   errno=0;
@@ -741,8 +1028,10 @@ setparams(int argc, char *argv[], struct imgwarpparams *p)
   if(cp->printparams)
     GAL_CONFIGFILES_REPORT_PARAMETERS_SET;
 
-  /* Read the input matrix */
-  preparematrix(p);
+  /* Read the input image WCS structure. We are doing this here because
+     some of the matrix operations might need it. */
+  gal_fits_read_wcs(p->up.inputname, p->cp.hdu, p->hstartwcs,
+                    p->hendwcs, &p->nwcs, &p->wcs);
 
   /* Do a sanity check. */
   sanitycheck(p);
@@ -795,7 +1084,6 @@ freeandreport(struct imgwarpparams *p, struct timeval *t1)
 {
   /* Free the allocated arrays: */
   free(p->input);
-  free(p->matrix);
   free(p->cp.hdu);
   free(p->inverse);
   free(p->cp.output);
diff --git a/bin/imgwarp/ui.h b/bin/imgwarp/ui.h
index f6b29e5..3307185 100644
--- a/bin/imgwarp/ui.h
+++ b/bin/imgwarp/ui.h
@@ -20,8 +20,29 @@ General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
 **********************************************************************/
-#ifndef IMCROPUI_H
-#define IMCROPUI_H
+#ifndef UI_H
+#define UI_H
+
+
+/* Macros for various types of standard transformation.*/
+enum standard_warps
+  {
+    ALIGN_WARP,
+    ROTATE_WARP,
+    SCALE_WARP,
+    FLIP_WARP,
+    SHEER_WARP,
+    TRANSLATE_WARP,
+    PROJECT_WARP,
+  };
+
+
+/* Functions */
+void
+add_to_optionwapsll(struct optionwarpsll **list, int type, char *value);
+
+void
+parse_two_values(char *str, double *v1, double *v2);
 
 void
 setparams(int argc, char *argv[], struct imgwarpparams *p);
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 722cbb1..03978dc 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -9178,35 +9178,18 @@ One line examples:
 @example
 $ astimgwarp matrix.txt image.fits
 $ astimgwarp --align rawimage.fits
-$ astimgwarp --scale 1.82 image.fits
-$ astimgwarp --rotate=37.92 image.fits
+$ astimgwarp --scale 1.82 --translate 2.1 image.fits
+$ astimgwarp --rotate=37.92 --scale=0.8 image.fits
 $ astimgwarp --matrix=0.2,0,0.4,0,0.2,0.4,0,0,1 image.fits
 $ astimgwarp --matrix="0.7071,-0.7071  0.7071,0.7071" image.fits
 @end example
 
 ImageWarp can accept two arguments, one (an image) is mandatory if any
 processing is to be done. An optional argument is a plain text file, which
-must contain the warp/transform matrix, see @ref{Warping basics}. There is
-also the @option{--matrix} option from which the matrix can be literally
-specified on the command-line. If both are present when calling ImageWarp,
-the contents of the plain text file have higher precedence. You can also
-specify standard transformations without an explicit matrix as discussed
-below. If multiple transformations are specified, then ImageWarp will
-inform you and abort. The general options to all Gnuastro programs can be
-seen in @ref{Common options}.
-
address@hidden WCSLIB
address@hidden World Coordinate System
-By default the WCS (World Coordinate System) information of the input
-image is going to be corrected in the output image. WCSLIB will save
-the input WCS information in the @code{PC} address@hidden
-E.W., Calabretta M.R. (2002) Representation of world coordinates in
-FITS. Astronomy and Astrophysics, 395, 1061-1075.}. To correct the
-WCS, ImageWarp multiplies the @code{PC} matrix with the inverse of the
-specified transformation matrix. Also the @code{CRPIX} point is going
-to be changed to its correct place in the output image
-coordinates. This behavior can be disabled with the
address@hidden option.
+must contain the warp/transform matrix, see @ref{Warping basics}. When this
+text file is specified, then all options related to the matrix will be
+ignored (see below for the options). The general options to all Gnuastro
+programs (including ImageWarp) can be seen in @ref{Common options}.
 
 To be the most accurate the input image will be converted to double
 precision floating points and all the processing will be done in this
@@ -9219,25 +9202,118 @@ data. This behavior can be disabled with the 
@option{--doubletype}
 option. The input file and input warping matrix elements are stored in
 the output's header.
 
address@hidden
address@hidden
address@hidden of pixel center}: Based on the FITS standard,
-integer values are assigned to the center of a pixel and the
-coordinate [1.0, 1.0] is the center of the bottom left (first) image
-pixel. So the point [0.0, 0.0] is half a pixel away (in each axis)
-from the bottom left vertice of the first address@hidden if you
-want to warp the image relative to the bottom left vertice of the
-bottom left pixel, you have to shift the warping center by [0.5, 0.5],
-apply your transform then shift back by [-0.5, -0.5]. Similar to the
-example in see @ref{Merging multiple warpings}. For example see the
-one line example above which scales the image by one fifth
-(0.2). Without this correction (if it was
address@hidden,0,0,0,0.2,0,0,0,1}), the image would not be correctly
-scaled.}.
address@hidden cartouche
+When using options, warps can be specified in a modular form, with options
+to specify each transformation (for example @option{--rotate}, or
address@hidden), or directly as a matrix (with @option{--matrix}). If
+specified together, the latter (direct matrix) will take precedence and all
+the modular warpings will be ignored. Any number of modular warpings can be
+specified on the command-line and configuration files. If more than one
+modular warping is given, all will be merged to create one warping
+matrix. As described in @ref{Merging multiple warpings}, matrix
+multiplication is not commutative, so the order of specifing the modular
+warpings on the command-line, and/or configuration files makes a difference
+(see @ref{Configuration file precedence}). Below, the modular warpings are
+first listed (see @ref{Warping basics} for the definition of each type of
+warping), then the other ImageWarp options.
+
address@hidden FITS standard
+Based on the FITS standard, integer values are assigned to the center of a
+pixel and the coordinate [1.0, 1.0] is the center of the bottom left
+(first) image pixel. So the point [0.0, 0.0] is half a pixel away (in each
+axis) from the bottom left vertice of the first pixel. The resampling that
+is done in ImageWarp (see @ref{Resampling}) is dependent on this
+coordinate. So correction is done internally. With this resampling, the
+image must be warped relative to the bottom left vertice of the bottom left
+pixel and that point should lie at [0.0, 0.0]. So for a correct sampling,
+the warping center must first be translated by [0.5, 0.5], then the warp
+should be done and finally, a [-0.5, -0.5] translation should be
+specified. This correction is done internally in the following cases and
+can be disabled with the @option{--nofitscorrect} option.
+
address@hidden
address@hidden
+A 2D matrix is given in a file (as an argument).
address@hidden
+A 2D matrix is specified with the @option{--matrix} option.
address@hidden
+When modular warpings are used.
address@hidden itemize
+
 
 @table @option
 
address@hidden -a
address@hidden --align
+Align the image and celestial (WCS) axes, such that the vertical image
+direction (when viewed in SAO ds9) corresponds to the declination and the
+horizontal axis is the inverse of the Right Ascension (RA). The inverse of
+the RA is chosen so the image can correspond to what you would actually see
+on the sky and is common in most survey images. Align is internally treated
+just like a rotation (@option{--rotation}), but uses the input image's WCS
+to find the rotation angle.
+
address@hidden -r
address@hidden --rotate
+(@option{=FLT}) Rotate the input image by the given angle in degrees. Note
+that commonly, the WCS structure of the image is set such that the RA is
+the inverse of the image horizontal axis which increases towards the right
+in the FITS standard and as viewed by SAO ds9. So the default center for
+rotation is on the right of the image. If you want to rotate about other
+points, you have to translate the warping center first (with
address@hidden) then apply your rotation and then return the center
+back to the original position (with another call to @option{--translate},z
+see @ref{Merging multiple warpings}.
+
address@hidden -s
address@hidden --scale
+(@option{=FLT[,FLT]}) Scale the input image by the given factor. If only
+one value is given, then both image axises will be scaled with the given
+value. When two values are given, the first will be used to scale the first
+axis and the second will be used for the second axis. If you only need to
+scale one axis, use @option{1} for the axis you don't need to scale.
+
address@hidden -f
address@hidden --flip
+(@option{=FLT[,FLT]}) Flip the image around the first, second or both
+axises. The first value specifies a flip on the first axis and the second
+on the second axis. The values of the option only matter if they are
+non-zero. If any of the values are zero, that axis is not flipped. So if
+you want to flip by the second axis only, use @option{--flip=0,1} (which is
+equivalent to @option{--flip=0,20} since it only matters if it is
+non-zero).
+
address@hidden -e
address@hidden --sheer
+(@option{=FLT[,FLT]}) Apply a sheer to the image along the image axises. If
+only one value is given, then both image axises will be sheered with the
+given value. When two values are given, the first will be used to sheer the
+first axis and the second will be used for the second axis. If you only
+need to sheer one axis, use @option{0} for the axis you don't need.
+
address@hidden -t
address@hidden --translate
+(@option{=FLT[,FLT]}) Apply a translation to the image along the image
+axises. If only one value is given, then both image axises will be
+translated with the given value. When two values are given, the first will
+be used to translate along the first axis and the second will be used for
+the second axis. If you only need to translate one axis, use @option{0} for
+the axis you don't need.
+
address@hidden -p
address@hidden --project
+(@option{=FLT[,FLT]}) Apply a projection to the image along the image
+axises. If only one value is given, then the projection will be applied on
+both image axises with the given value. When two values are given, the
+first will be used for the first axis and the second will be used for the
+second axis. If you only need projection along one axis, use @option{0} for
+the axis you don't need.
+
address@hidden table
+
+
+ImageWarp also provides the following options:
address@hidden @option
+
 @item -m
 @itemx --matrix
 (@option{=STR}) The warp/transformation matrix. All the elements in this
@@ -9261,28 +9337,9 @@ elements of the matrix have to be written row by row. So 
for the
 general homography matrix of @ref{Warping basics}, it should be called
 with @command{--matrix=a,b,c,d,e,f,g,h,1}.
 
address@hidden -a
address@hidden --align
-Align the image and celestial (WCS) axes, such that the vertical image
-direction (when viewed in SAO ds9) corresponds to the declination and the
-horizontal axis is the inverse of the Right Ascension (RA). The inverse of
-the RA is chosen so the image can correspond to what you would actually see
-on the sky and is common in most survey images.
-
address@hidden -r
address@hidden --rotate
-(@option{=FLT}) Rotate the input image by the given angle in degrees. Note
-that commonly, the WCS structure of the image is set such that the RA is
-the inverse of the image horizontal axis which increases towards the right
-in the FITS standard and as viewed by SAO ds9. So the default center for
-rotation is on the right of the image. If you want to rotate about other
-points, you have to define your own transformation matrix by first shifting
-the central point, then applying your rotation and then returning the
-center back to the original position, see @ref{Merging multiple warpings}.
-
address@hidden -s
address@hidden --scale
-(@option{=FLT}) Scale the input image by the given factor.
address@hidden nofitscorrect
+Do not correct for the FITS definition of the pixel center as described in
+the @option{--matrix} option.
 
 @item --hstartwcs
 (@option{=INT}) Specify the first header keyword number (line) that
@@ -9296,8 +9353,19 @@ should be used to read the WCS information, see the full 
explanation in
 
 @item -n
 @itemx --nowcscorrection
-Do not correct the WCS information of the input image and save it
-untouched to the output image.
address@hidden WCSLIB
address@hidden World Coordinate System
+Do not correct the WCS information of the input image and save it untouched
+to the output image. By default the WCS (World Coordinate System)
+information of the input image is going to be corrected in the output
+image. WCSLIB will save the input WCS information in the @code{PC}
address@hidden E.W., Calabretta M.R. (2002) Representation of
+world coordinates in FITS. Astronomy and Astrophysics, 395, 1061-1075.}. To
+correct the WCS, ImageWarp multiplies the @code{PC} matrix with the inverse
+of the specified transformation matrix. Also the @code{CRPIX} point is
+going to be changed to its correct place in the output image
+coordinates. This behavior can be disabled with the
address@hidden option.
 
 @cindex Blank pixel
 @cindex Pixel, blank



reply via email to

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