[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