gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master f7e2f28a 1/3: Add function for writing of tiff


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master f7e2f28a 1/3: Add function for writing of tiff files
Date: Wed, 12 Jul 2023 13:00:39 -0400 (EDT)

branch: master
commit f7e2f28ac09b46783adc9a1444a498b895facec0
Author: Fathma Mehnoor <fathmamehnoor@gmail.com>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>

    Add function for writing of tiff files
    
    Until this commit, writing tiff files was not supported. Thus, it was not
    possible to convert other image and data formats to tiff file using 
astconvertt.
    With this commit, writing tiff files and converting other image and data 
formatsto tiff file using astconverrt is provided.
    
    This fixes task #16096: https://savannah.gnu.org/task/?16096
---
 bin/convertt/convertt.c      |   9 ++++
 bin/convertt/main.h          |   5 ++
 bin/convertt/ui.c            |   9 ++--
 bin/convertt/ui.h            |   7 ++-
 doc/gnuastro.texi            |   8 +--
 lib/gnuastro/tiff.h          |   4 +-
 lib/tiff.c                   | 125 ++++++++++++++++++++++++++++++++++++++++++-
 tests/Makefile.am            |   4 +-
 tests/convertt/fitstotiff.sh |  61 +++++++++++++++++++++
 9 files changed, 221 insertions(+), 11 deletions(-)

diff --git a/bin/convertt/convertt.c b/bin/convertt/convertt.c
index 4038dd69..20e8e573 100644
--- a/bin/convertt/convertt.c
+++ b/bin/convertt/convertt.c
@@ -34,6 +34,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <gnuastro/txt.h>
 #include <gnuastro/fits.h>
 #include <gnuastro/jpeg.h>
+#include <gnuastro/tiff.h>
 #include <gnuastro/arithmetic.h>
 
 #include <gnuastro-internal/timing.h>
@@ -362,6 +363,14 @@ convertt(struct converttparams *p)
                     p->bordercolor, p->forcemin || p->forcemax, p->marks);
       break;
 
+    /* TIFF */
+    case OUT_FORMAT_TIFF:
+      if(p->colormap) color_map_prepare(p); else convertt_scale_to_uchar(p);
+      gal_tiff_write(p->chll, p->cp.output, p->widthinpx, p->heightinpx, 
+                    p->bitspersample, p->numch);
+      break;
+      
+
     /* Not recognized. */
     default:
       error(EXIT_FAILURE, 0, "%s: a bug! Please contact us so we can find "
diff --git a/bin/convertt/main.h b/bin/convertt/main.h
index d07896f7..d30986f4 100644
--- a/bin/convertt/main.h
+++ b/bin/convertt/main.h
@@ -47,6 +47,7 @@ enum output_formats
   OUT_FORMAT_PDF,
   OUT_FORMAT_FITS,
   OUT_FORMAT_JPEG,
+  OUT_FORMAT_TIFF,
 };
 
 enum colorspace_names
@@ -118,6 +119,10 @@ struct converttparams
   uint8_t      sizeinarcsec;  /* Sizes are in arcseconds (in WCS-mode).*/
   uint8_t      sizeinarcmin;  /* Sizes are in arcminutes (in WCS-mode).*/
   uint8_t marktextprecision;  /* Precision to convert floats.          */
+  int             widthinpx;  /* Width of image in pixel.              */
+  int            heightinpx;  /* Height of image in pixel.             */
+  int         bitspersample;  /* Number of bits used to represent color 
+                                 of a single pixel.                    */
 
   /* Internal */
   struct change     *change;  /* The value conversion string.          */
diff --git a/bin/convertt/ui.c b/bin/convertt/ui.c
index 478ac465..6f6e5a6b 100644
--- a/bin/convertt/ui.c
+++ b/bin/convertt/ui.c
@@ -1165,9 +1165,12 @@ ui_set_output(struct converttparams *p)
 
   /* TIFF */
   else if( gal_tiff_name_is_tiff(cp->output) )
-      error(EXIT_FAILURE, 0, "writing TIFF files is not yet supported, "
-            "please get in touch with us at %s so we implement it",
-            PACKAGE_BUGREPORT);
+    {
+      p->outformat=OUT_FORMAT_TIFF;
+       if( gal_tiff_suffix_is_tiff(cp->output) )
+          ui_add_dot_use_automatic_output(p);
+    }
+
 
   /* EPS */
   else if(gal_eps_name_is_eps(cp->output))
diff --git a/bin/convertt/ui.h b/bin/convertt/ui.h
index 888deaab..7020b39f 100644
--- a/bin/convertt/ui.h
+++ b/bin/convertt/ui.h
@@ -43,8 +43,8 @@ enum program_args_groups
 
 /* Available letters for short options:
 
-   a d e f j k l n p s t v y z
-   E G J Q R W X Y
+   a d e f j k n s t v y z
+   E G J Q R X Y
 */
 enum option_keys_enum
 {
@@ -64,6 +64,9 @@ enum option_keys_enum
   UI_KEY_INVERT              = 'i',
   UI_KEY_MODE                = 'O',
   UI_KEY_MARKCOORDS          = 'r',
+  UI_KEY_WIDTHINPX           = 'W',
+  UI_KEY_HEIGHTINPX          = 'l',
+  UI_KEY_BITSPERSAMPLE       = 'p',
 
   /* Only with long version (start with a value 1000, the rest will be set
      automatically). */
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index c637ec16..9793cbe5 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -14320,9 +14320,6 @@ Another (inconvenient) difference with the FITS 
standard is that keyword names a
 
 However, outside of astronomy, because of its support of different numeric 
data types, many fields use TIFF images for accurate (for example, 16-bit 
integer or floating point for example) imaging data.
 
-Currently ConvertType can only read TIFF images, if you are interested in
-writing TIFF images, please get in touch with us.
-
 @item EPS
 @cindex EPS
 @cindex PostScript
@@ -37392,6 +37389,11 @@ Read the @code{dir} directory within the TIFF file 
@code{filename} and return th
 If the directory's image contains multiple channels, the output will be a list 
(see @ref{List of gal_data_t}).
 @end deftypefun
 
+@deftypefun {void} gal_tiff_write (gal_data_t @code{*in}, char 
@code{*filename}, int @code{widthinpx}, int @code{heightinpix}, int 
@code{bitspersample}, int @code{numimg})
+Write the given dataset (@code{in}) into @file{filename} (a TIFF file) with 
the specified image width in pixels (@code{widthinpix}),height in pixels 
(@code{heightinpix}), bits per sample (@code{bitspersample}), and number of 
images (@code{numimg}).
+@end deftypefun
+
+
 
 
 
diff --git a/lib/gnuastro/tiff.h b/lib/gnuastro/tiff.h
index ae3b502f..744f9534 100644
--- a/lib/gnuastro/tiff.h
+++ b/lib/gnuastro/tiff.h
@@ -66,7 +66,9 @@ gal_tiff_dir_string_read(char *string);
 gal_data_t *
 gal_tiff_read(char *filename, size_t dir, size_t minmapsize, int quietmmap);
 
-
+void
+gal_tiff_write(gal_data_t *in, char *filename, int widthinpx, int heightinpx, 
+               int bitspersample, int numimg);
 
 
 __END_C_DECLS    /* From C++ preparations */
diff --git a/lib/tiff.c b/lib/tiff.c
index 88db94e5..c1a32205 100644
--- a/lib/tiff.c
+++ b/lib/tiff.c
@@ -37,6 +37,8 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <gnuastro/tiff.h>
 #include <gnuastro/pointer.h>
 
+#include <gnuastro-internal/checkset.h>
+
 
 
 
@@ -151,7 +153,7 @@ gal_tiff_dir_string_read(char *string)
 
 
 /*************************************************************
- **************        Read a JPEG image        **************
+ **************        Read a TIFF image        **************
  *************************************************************/
 #ifdef HAVE_LIBTIFF
 static void
@@ -627,3 +629,124 @@ gal_tiff_read(char *filename, size_t dir, size_t 
minmapsize, int quietmmap)
   return NULL;
 #endif  /* HAVE_LIBTIFF */
 }
+
+
+
+/*************************************************************
+ ****************    Write into a TIFF file   ****************
+ *************************************************************/
+
+/* Write image data into a TIFF file using libtiff library*/
+#ifdef HAVE_LIBTIFF
+static int
+tiff_img_write(TIFF *tif, gal_data_t *in, char *filename, int widthinpx, 
+              int heightinpx, size_t numch, int bitspersample, int numimg) 
+{
+    
+    size_t c;
+    int i, out;
+    uint32_t stripoffset, stripcount;
+    size_t bytespersample = bitspersample / 8;
+    uint32_t stripsize = TIFFDefaultStripSize(tif, widthinpx * numch 
+                                              * bytespersample);
+    uint32_t rowsperstrip = stripsize / (widthinpx * numch * bytespersample);
+  
+    /*Make sure rowspwerstrip is not 0*/
+    if (rowsperstrip == 0) {
+        rowsperstrip = 1;
+    }
+
+    /*Recalculate stripsize based on the rowsperstrip*/
+    stripsize = rowsperstrip * widthinpx * numch * bytespersample;
+    
+    /*Set TIFF tags that define image properties for image data*/
+    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, widthinpx);
+    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, heightinpx);
+    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, numch);
+    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bitspersample);
+    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
+    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_SEPARATE);
+    
+    /*For each number of image and channel, write the data into the TIFF file*/
+    for (i = 0; i < numimg; i++) {
+        for (c = 0; c < numch; c++) {
+            /*Calculate the offset of current strip*/
+            stripoffset = i * rowsperstrip * widthinpx * numch;
+
+            /*Calculate the number of rows per each strip while making sure 
+            that it does not exceed the image height*/
+            stripcount = heightinpx - stripoffset * rowsperstrip;
+            if (stripcount > rowsperstrip) {
+                stripcount = rowsperstrip;
+            }
+
+            /*Write the data of the current strip into the TIFF file*/
+            out = TIFFWriteEncodedStrip(tif, c, (void*)((char*)in + 
+                                       (stripoffset * widthinpx * numch + c)
+                                        * bytespersample), stripsize * 
stripcount);
+
+            /*If there is an error writing into TIFF file close the file and
+            return -1 */
+            if (out < 0) {
+                TIFFClose(tif);
+                return -1;
+            }
+        }
+
+        /*Write the TIFF directory for current image*/
+        TIFFWriteDirectory(tif);
+    }
+    /*return success*/
+    return 0;
+    
+    
+}
+#endif
+
+
+
+
+
+void
+gal_tiff_write(gal_data_t *in, char *filename, int widthinpx, int heightinpx,
+              int bitspersample, int numimg)
+{
+  #ifdef HAVE_LIBTIFF
+
+  int out;
+  size_t numch=gal_list_data_number(in);
+ 
+  /*Open the TIFF file*/
+  TIFF* tif = TIFFOpen(filename, "w");
+  if (tif==NULL) {
+    error(EXIT_FAILURE, 0, "%s: '%s' couldn't be opened for writing",
+          __func__, filename);
+  }
+
+  /*Check if input parameters have valid values*/
+  if( widthinpx <=0 || bitspersample <= 0 || numch <= 0){
+    error(EXIT_FAILURE, 0, "%s: '%s', widthinpx=%d, bitspersample=%d,"
+        "numch=%zu, values should be greater than 0",
+        __func__, filename, widthinpx, bitspersample, numch);
+  }
+
+  /*Check if the file already exists or has write permissions*/
+  if( gal_checkset_writable_notexist(filename)==0 )
+    error(EXIT_FAILURE, 0, "%s: already exists or its directory doesn't "
+          "write permssion. ", filename);
+
+  /*Write to TIFF file*/
+  out = tiff_img_write(tif, in, filename, widthinpx, heightinpx,
+                       numch, bitspersample, numimg);
+  if(out < 0){
+    error(EXIT_FAILURE, 0, "%s: problem in writing to %s",__func__, filename);
+    
+  }
+  /*Close file*/
+  TIFFClose(tif);
+
+  #else
+  tiff_error_no_litiff(__func__);
+  return NULL;
+  #endif /*HAVE_LIBTIFF*/
+}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e824bb8c..53dda70e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -74,7 +74,7 @@ endif
 if COND_CONVERTT
   MAYBE_CONVERTT_TESTS = convertt/fitstotxt.sh convertt/fitstojpeg.sh  \
   convertt/blankch.sh convertt/jpegtotxt.sh convertt/fitstojpegcmyk.sh \
-  convertt/jpegtofits.sh convertt/fitstopdf.sh
+  convertt/jpegtofits.sh convertt/fitstopdf.sh convertt/fitstotiff.sh 
 
   convertt/fitstotxt.sh: mkprof/mosaic1.sh.log
   convertt/fitstojpeg.sh: mkprof/mosaic1.sh.log
@@ -83,6 +83,8 @@ if COND_CONVERTT
   convertt/fitstojpegcmyk.sh: mkprof/mosaic1.sh.log
   convertt/jpegtofits.sh: convertt/blankch.sh.log
   convertt/fitstopdf.sh: crop/section.sh.log
+  convertt/fitstotiff.sh: mkprof/mosaic1.sh.log
+
 endif
 if COND_CONVOLVE
   MAYBE_CONVOLVE_TESTS = convolve/spatial.sh convolve/frequency.sh \
diff --git a/tests/convertt/fitstotiff.sh b/tests/convertt/fitstotiff.sh
new file mode 100644
index 00000000..54e863b7
--- /dev/null
+++ b/tests/convertt/fitstotiff.sh
@@ -0,0 +1,61 @@
+# Convert a FITS image into a TIFF file.
+#
+# See the Tests subsection of the manual for a complete explanation
+# (in the Installing gnuastro section).
+#
+# Original author:
+#     Mohammad Akhlaghi <mohammad@akhlaghi.org>
+# Contributing author(s):
+# Copyright (C) 2015-2023 Free Software Foundation, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.  This file is offered as-is,
+# without any warranty.
+
+
+
+
+
+# Preliminaries
+# =============
+#
+# Set the variables (The executable is in the build tree). Do the
+# basic checks to see if the executable is made or if the defaults
+# file exists (basicchecks.sh is in the source tree).
+img=psf.fits
+prog=convertt
+execname=../bin/$prog/ast$prog
+
+
+
+
+
+# Skip?
+# =====
+#
+# If the dependencies of the test don't exist, then skip it. There are two
+# types of dependencies:
+#
+#   - The executable was not made (for example due to a configure option),
+#
+#   - The input data was not made (for example the test that created the
+#     data file failed).
+#
+#   - libjtiff was not present on the system.
+if [ ! -f $execname           ];then echo "$execname not created.";exit 77;fi
+if [ ! -f $img                ];then echo "$img does not exist.";  exit 77;fi
+if [ "x$haslibtiff" != "xyes" ];then echo "libtiff not present.";  exit 77;fi
+
+
+
+
+
+
+# Actual test script
+# ==================
+#
+# 'check_with_program' can be something like Valgrind or an empty
+# string. Such programs will execute the command if present and help in
+# debugging when the developer doesn't have access to the user's system.
+$check_with_program $execname $img --output=tif



reply via email to

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