SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
tiff2sdds.c
Go to the documentation of this file.
1/**
2 * @file tiff2sdds.c
3 * @brief Converts a TIFF image to an SDDS file format.
4 *
5 * @details
6 * This program reads a TIFF image file and converts its pixel data into the SDDS (Self Describing Data Set) format.
7 * It supports extracting specific color channels and arranging the data in a single column or multiple columns
8 * based on user options. The input is a TIFF image in RGBA format, and the output is an SDDS binary file.
9 *
10 * @section Usage
11 * ```
12 * tiff2sdds <inputfile> <outputfile>
13 * [-redOnly]
14 * [-greenOnly]
15 * [-blueOnly]
16 * [-singleColumnMode]
17 * ```
18 *
19 * @section Options
20 * | Optional | Description |
21 * |-------------------|----------------------------------------------------------|
22 * | `-redOnly` | Extracts the red channel only. |
23 * | `-greenOnly` | Extracts the green channel only. |
24 * | `-blueOnly` | Extracts the blue channel only. |
25 * | `-singleColumnMode` | Outputs pixel data in a single column. |
26 *
27 * @subsection Incompatibilities
28 * - Only one of `-redOnly`, `-greenOnly`, or `-blueOnly` may be specified.
29 *
30 * @copyright
31 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
32 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
33 *
34 * @license
35 * This file is distributed under the terms of the Software License Agreement
36 * found in the file LICENSE included with this distribution.
37 *
38 * @author
39 * R. Soliday
40 */
41
42#include "tiffio.h"
43#include "SDDS.h"
44#include "mdb.h"
45#include "scan.h"
46
47/*
48 * Enumeration for supported command-line options.
49 */
50typedef enum {
51 OPT_REDONLY, /* Option for extracting red channel only. */
52 OPT_GREENONLY, /* Option for extracting green channel only. */
53 OPT_BLUEONLY, /* Option for extracting blue channel only. */
54 OPT_SINGLECOLUMNMODE, /* Option for single column mode in output. */
55 N_OPTIONS /* Total number of options. */
56} OptionType;
57
58/*
59 * Array of option strings corresponding to the enumeration.
60 */
61char *option[N_OPTIONS] =
62 {
63 "redOnly",
64 "greenOnly",
65 "blueOnly",
66 "singleColumnMode",
67 };
68
69/*
70 * Usage message displayed for invalid or missing arguments.
71 */
72char *usage =
73 "tiff2sdds <input> <output>\n"
74 " [-redOnly] [-greenOnly] [-blueOnly]\n"
75 " [-singleColumnMode]\n"
76 "Program by Robert Soliday. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n\n";
77
78int main(int argc, char *argv[]) {
79 SDDS_DATASET SDDS_dataset;
80 SCANNED_ARG *s_arg;
81 TIFF *tif;
82 char *input = NULL, *output = NULL;
83 char **column_names = NULL;
84 int32_t **data;
85 int32_t *indexes = NULL;
86 long rgb[3];
87 long i, j, n = 0, single_column_mode = 0;
88
90
91 rgb[0] = rgb[1] = rgb[2] = 1; /* Enable all color channels by default. */
92
93 argc = scanargs(&s_arg, argc, argv); /* Parse command-line arguments. */
94 if (argc < 3) {
95 fprintf(stderr, "%s", usage);
96 return 1;
97 }
98
99 for (i = 1; i < argc; i++) {
100 if (s_arg[i].arg_type == OPTION) {
101 switch (match_string(s_arg[i].list[0], option, N_OPTIONS, 0)) {
102 case OPT_REDONLY:
103 rgb[0] = 1;
104 rgb[1] = rgb[2] = 0; /* Enable red channel only. */
105 break;
106 case OPT_GREENONLY:
107 rgb[1] = 1;
108 rgb[0] = rgb[2] = 0; /* Enable green channel only. */
109 break;
110 case OPT_BLUEONLY:
111 rgb[2] = 1;
112 rgb[0] = rgb[1] = 0; /* Enable blue channel only. */
113 break;
114 case OPT_SINGLECOLUMNMODE:
115 single_column_mode = 1; /* Enable single column mode. */
116 break;
117 default:
118 fprintf(stderr, "invalid option seen\n%s", usage);
119 return 1;
120 }
121 } else {
122 if (!input)
123 input = s_arg[i].list[0]; /* Assign first non-option argument as input file. */
124 else if (!output)
125 output = s_arg[i].list[0]; /* Assign second non-option argument as output file. */
126 else {
127 fprintf(stderr, "too many filenames\n%s", usage);
128 return 1;
129 }
130 }
131 }
132
133 tif = TIFFOpen(input, "r"); /* Open TIFF file for reading. */
134 if (tif) {
135 uint32_t w, h;
136 size_t npixels;
137 uint32_t *raster;
138 double tmp;
139 int32_t tmp2;
140
141 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); /* Retrieve image width. */
142 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); /* Retrieve image height. */
143 npixels = w * h; /* Calculate total pixels. */
144 raster = (uint32_t *)_TIFFmalloc(npixels * sizeof(uint32_t)); /* Allocate memory for pixel data. */
145 if (raster != NULL) {
146 if (TIFFReadRGBAImage(tif, w, h, raster, 0)) {
147
148 if (!SDDS_InitializeOutput(&SDDS_dataset, SDDS_BINARY, 1, NULL, NULL, output))
149 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
150 if (single_column_mode) {
151 /* Define parameters for single column mode. */
152 if (SDDS_DefineParameter(&SDDS_dataset, "Variable1Name", NULL, NULL, NULL, NULL, SDDS_STRING, "x") < 0) {
153 fprintf(stderr, "Problem defining parameter Variable1Name.\n");
154 return 1;
155 }
156 if (SDDS_DefineParameter(&SDDS_dataset, "Variable2Name", NULL, NULL, NULL, NULL, SDDS_STRING, "y") < 0) {
157 fprintf(stderr, "Problem defining parameter Variable2Name.\n");
158 return 1;
159 }
160 tmp = 1;
161 if (SDDS_DefineParameter1(&SDDS_dataset, "xInterval", NULL, NULL, NULL, NULL, SDDS_DOUBLE, &tmp) < 0) {
162 fprintf(stderr, "Problem defining parameter xInterval.\n");
163 return 1;
164 }
165 if (SDDS_DefineParameter1(&SDDS_dataset, "yInterval", NULL, NULL, NULL, NULL, SDDS_DOUBLE, &tmp) < 0) {
166 fprintf(stderr, "Problem defining parameter yInterval.\n");
167 return 1;
168 }
169 tmp2 = w;
170 if (SDDS_DefineParameter1(&SDDS_dataset, "xDimension", NULL, NULL, NULL, NULL, SDDS_LONG, &tmp2) < 0) {
171 fprintf(stderr, "Problem defining parameter xDimension.\n");
172 return 1;
173 }
174 tmp2 = h;
175 if (SDDS_DefineParameter1(&SDDS_dataset, "yDimension", NULL, NULL, NULL, NULL, SDDS_LONG, &tmp2) < 0) {
176 fprintf(stderr, "Problem defining parameter yDimension.\n");
177 return 1;
178 }
179 tmp = 0;
180 if (SDDS_DefineParameter1(&SDDS_dataset, "xMinimum", NULL, NULL, NULL, NULL, SDDS_DOUBLE, &tmp) < 0) {
181 fprintf(stderr, "Problem defining parameter xMinimum.\n");
182 return 1;
183 }
184 if (SDDS_DefineParameter1(&SDDS_dataset, "yMinimum", NULL, NULL, NULL, NULL, SDDS_DOUBLE, &tmp) < 0) {
185 fprintf(stderr, "Problem defining parameter yMinimum.\n");
186 return 1;
187 }
188 if (SDDS_DefineSimpleColumn(&SDDS_dataset, "z", NULL, SDDS_LONG) < 0) {
189 fprintf(stderr, "Problem defining column z.\n");
190 return 1;
191 }
192 data = malloc(sizeof(*data) * 1);
193 data[0] = malloc(sizeof(*(data[0])) * npixels);
194 } else {
195 /* Define parameters for multi-column mode. */
196 if (SDDS_DefineSimpleColumn(&SDDS_dataset, "Index", NULL, SDDS_LONG) < 0) {
197 fprintf(stderr, "Problem defining column Index.\n");
198 return 1;
199 }
200 indexes = malloc(sizeof(*indexes) * w);
201 column_names = malloc(sizeof(char **) * h);
202 data = malloc(sizeof(*data) * h);
203 for (i = 0; i < h; i++) {
204 column_names[i] = malloc(sizeof(char *) * 15);
205 data[i] = malloc(sizeof(*(data[i])) * w);
206 sprintf(column_names[i], "Line%05ld", i);
207 if (SDDS_DefineSimpleColumn(&SDDS_dataset, column_names[i], NULL, SDDS_LONG) < 0) {
208 fprintf(stderr, "Problem defining column %s.\n", column_names[i]);
209 return 1;
210 }
211 }
212 }
213
214 if (!SDDS_WriteLayout(&SDDS_dataset))
215 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
216 if (single_column_mode) {
217 if (!SDDS_StartPage(&SDDS_dataset, npixels))
218 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
219 for (i = 0; i < h; i++) {
220 for (j = 0; j < w; j++) {
221 /* Process pixel values for single column mode. */
222 data[0][j * h + i] = TIFFGetR(raster[n]) * rgb[0] + TIFFGetG(raster[n]) * rgb[1] + TIFFGetB(raster[n]) * rgb[2];
223 n++;
224 }
225 }
226
227 if (!SDDS_SetColumnFromLongs(&SDDS_dataset, SDDS_SET_BY_NAME, data[0], npixels, "z"))
228 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
229 } else {
230 if (!SDDS_StartPage(&SDDS_dataset, w))
231 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
232 for (i = 0; i < w; i++)
233 indexes[i] = i; /* Initialize index values. */
234 for (i = 0; i < h; i++) {
235 for (j = 0; j < w; j++) {
236 /* Process pixel values for multi-column mode. */
237 data[i][j] = TIFFGetR(raster[n]) * rgb[0] + TIFFGetG(raster[n]) * rgb[1] + TIFFGetB(raster[n]) * rgb[2];
238 n++;
239 }
240 }
241 if (!SDDS_SetColumnFromLongs(&SDDS_dataset, SDDS_SET_BY_NAME, indexes, w, "Index"))
242 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
243 for (i = 0; i < h; i++) {
244 if (!SDDS_SetColumnFromLongs(&SDDS_dataset, SDDS_SET_BY_NAME, data[i], w, column_names[i]))
245 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
246 }
247 }
248
249 if (!SDDS_WritePage(&SDDS_dataset) || !SDDS_Terminate(&SDDS_dataset))
250 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
251
252 if (single_column_mode) {
253 free(data[0]);
254 free(data);
255 } else {
256 for (i = 0; i < h; i++) {
257 free(column_names[i]);
258 free(data[i]);
259 }
260 free(column_names);
261 free(data);
262 }
263 }
264 _TIFFfree(raster); /* Free allocated memory for pixel data. */
265 }
266 TIFFClose(tif); /* Close TIFF file. */
267 }
268 if (indexes)
269 free(indexes); /* Free allocated memory for indexes. */
270 free_scanargs(&s_arg, argc); /* Free scanned arguments. */
271 return 0;
272}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetColumnFromLongs(SDDS_DATASET *SDDS_dataset, int32_t mode, int32_t *data, int64_t rows,...)
Sets the values for a single data column using long integer numbers.
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_DefineParameter1(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, void *fixed_value)
Defines a data parameter with a fixed numerical value.
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_DefineParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, char *fixed_value)
Defines a data parameter with a fixed string value.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584