SDDSlib
Loading...
Searching...
No Matches
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 * This program reads a TIFF image file and converts its pixel data into the SDDS (Self Describing Data Set) format.
6 * Users can specify options for single color extraction (red, green, or blue channels) and single column mode
7 * for the output SDDS file. The program supports reading TIFF images in RGBA format and writing to SDDS binary files.
8 *
9 * ### Features:
10 * - Extract specific color channels: red, green, blue.
11 * - Convert image data into SDDS format with optional single column representation.
12 * - Flexible parameter definitions for SDDS output.
13 *
14 * ### Usage:
15 * ```
16 * tiff2sdds <input> <output>
17 * [-redOnly] [-greenOnly] [-blueOnly]
18 * [-singleColumnMode]
19 * ```
20 *
21 * @copyright
22 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
23 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
24 *
25 * @license
26 * This file is distributed under the terms of the Software License Agreement
27 * found in the file LICENSE included with this distribution.
28 *
29 * @author R. Soliday
30 */
31
32#include "tiffio.h"
33#include "SDDS.h"
34#include "mdb.h"
35#include "scan.h"
36
37/*
38 * Enumeration for supported command-line options.
39 */
40typedef enum {
41 OPT_REDONLY, /* Option for extracting red channel only. */
42 OPT_GREENONLY, /* Option for extracting green channel only. */
43 OPT_BLUEONLY, /* Option for extracting blue channel only. */
44 OPT_SINGLECOLUMNMODE, /* Option for single column mode in output. */
45 N_OPTIONS /* Total number of options. */
47
48/*
49 * Array of option strings corresponding to the enumeration.
50 */
51char *option[N_OPTIONS] =
52 {
53 "redOnly",
54 "greenOnly",
55 "blueOnly",
56 "singleColumnMode",
57 };
58
59/*
60 * Usage message displayed for invalid or missing arguments.
61 */
62char *usage =
63 "tiff2sdds <input> <output>\n"
64 " [-redOnly] [-greenOnly] [-blueOnly]\n"
65 " [-singleColumnMode]\n"
66 "Program by Robert Soliday. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n\n";
67
68int main(int argc, char *argv[]) {
69 SDDS_DATASET SDDS_dataset;
70 SCANNED_ARG *s_arg;
71 TIFF *tif;
72 char *input = NULL, *output = NULL;
73 char **column_names = NULL;
74 int32_t **data;
75 int32_t *indexes = NULL;
76 long rgb[3];
77 long i, j, n = 0, single_column_mode = 0;
78
80
81 rgb[0] = rgb[1] = rgb[2] = 1; /* Enable all color channels by default. */
82
83 argc = scanargs(&s_arg, argc, argv); /* Parse command-line arguments. */
84 if (argc < 3) {
85 fprintf(stderr, "%s", usage);
86 return 1;
87 }
88
89 for (i = 1; i < argc; i++) {
90 if (s_arg[i].arg_type == OPTION) {
91 switch (match_string(s_arg[i].list[0], option, N_OPTIONS, 0)) {
92 case OPT_REDONLY:
93 rgb[0] = 1;
94 rgb[1] = rgb[2] = 0; /* Enable red channel only. */
95 break;
96 case OPT_GREENONLY:
97 rgb[1] = 1;
98 rgb[0] = rgb[2] = 0; /* Enable green channel only. */
99 break;
100 case OPT_BLUEONLY:
101 rgb[2] = 1;
102 rgb[0] = rgb[1] = 0; /* Enable blue channel only. */
103 break;
104 case OPT_SINGLECOLUMNMODE:
105 single_column_mode = 1; /* Enable single column mode. */
106 break;
107 default:
108 fprintf(stderr, "invalid option seen\n%s", usage);
109 return 1;
110 }
111 } else {
112 if (!input)
113 input = s_arg[i].list[0]; /* Assign first non-option argument as input file. */
114 else if (!output)
115 output = s_arg[i].list[0]; /* Assign second non-option argument as output file. */
116 else {
117 fprintf(stderr, "too many filenames\n%s", usage);
118 return 1;
119 }
120 }
121 }
122
123 tif = TIFFOpen(input, "r"); /* Open TIFF file for reading. */
124 if (tif) {
125 uint32 w, h;
126 size_t npixels;
127 uint32 *raster;
128 double tmp;
129 int32_t tmp2;
130
131 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); /* Retrieve image width. */
132 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); /* Retrieve image height. */
133 npixels = w * h; /* Calculate total pixels. */
134 raster = (uint32 *)_TIFFmalloc(npixels * sizeof(uint32)); /* Allocate memory for pixel data. */
135 if (raster != NULL) {
136 if (TIFFReadRGBAImage(tif, w, h, raster, 0)) {
137
138 if (!SDDS_InitializeOutput(&SDDS_dataset, SDDS_BINARY, 1, NULL, NULL, output))
139 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
140 if (single_column_mode) {
141 /* Define parameters for single column mode. */
142 if (SDDS_DefineParameter(&SDDS_dataset, "Variable1Name", NULL, NULL, NULL, NULL, SDDS_STRING, "x") < 0) {
143 fprintf(stderr, "Problem defining parameter Variable1Name.\n");
144 return 1;
145 }
146 if (SDDS_DefineParameter(&SDDS_dataset, "Variable2Name", NULL, NULL, NULL, NULL, SDDS_STRING, "y") < 0) {
147 fprintf(stderr, "Problem defining parameter Variable2Name.\n");
148 return 1;
149 }
150 tmp = 1;
151 if (SDDS_DefineParameter1(&SDDS_dataset, "xInterval", NULL, NULL, NULL, NULL, SDDS_DOUBLE, &tmp) < 0) {
152 fprintf(stderr, "Problem defining parameter xInterval.\n");
153 return 1;
154 }
155 if (SDDS_DefineParameter1(&SDDS_dataset, "yInterval", NULL, NULL, NULL, NULL, SDDS_DOUBLE, &tmp) < 0) {
156 fprintf(stderr, "Problem defining parameter yInterval.\n");
157 return 1;
158 }
159 tmp2 = w;
160 if (SDDS_DefineParameter1(&SDDS_dataset, "xDimension", NULL, NULL, NULL, NULL, SDDS_LONG, &tmp2) < 0) {
161 fprintf(stderr, "Problem defining parameter xDimension.\n");
162 return 1;
163 }
164 tmp2 = h;
165 if (SDDS_DefineParameter1(&SDDS_dataset, "yDimension", NULL, NULL, NULL, NULL, SDDS_LONG, &tmp2) < 0) {
166 fprintf(stderr, "Problem defining parameter yDimension.\n");
167 return 1;
168 }
169 tmp = 0;
170 if (SDDS_DefineParameter1(&SDDS_dataset, "xMinimum", NULL, NULL, NULL, NULL, SDDS_DOUBLE, &tmp) < 0) {
171 fprintf(stderr, "Problem defining parameter xMinimum.\n");
172 return 1;
173 }
174 if (SDDS_DefineParameter1(&SDDS_dataset, "yMinimum", NULL, NULL, NULL, NULL, SDDS_DOUBLE, &tmp) < 0) {
175 fprintf(stderr, "Problem defining parameter yMinimum.\n");
176 return 1;
177 }
178 if (SDDS_DefineSimpleColumn(&SDDS_dataset, "z", NULL, SDDS_LONG) < 0) {
179 fprintf(stderr, "Problem defining column z.\n");
180 return 1;
181 }
182 data = malloc(sizeof(*data) * 1);
183 data[0] = malloc(sizeof(*(data[0])) * npixels);
184 } else {
185 /* Define parameters for multi-column mode. */
186 if (SDDS_DefineSimpleColumn(&SDDS_dataset, "Index", NULL, SDDS_LONG) < 0) {
187 fprintf(stderr, "Problem defining column Index.\n");
188 return 1;
189 }
190 indexes = malloc(sizeof(*indexes) * w);
191 column_names = malloc(sizeof(char **) * h);
192 data = malloc(sizeof(*data) * h);
193 for (i = 0; i < h; i++) {
194 column_names[i] = malloc(sizeof(char *) * 15);
195 data[i] = malloc(sizeof(*(data[i])) * w);
196 sprintf(column_names[i], "Line%05ld", i);
197 if (SDDS_DefineSimpleColumn(&SDDS_dataset, column_names[i], NULL, SDDS_LONG) < 0) {
198 fprintf(stderr, "Problem defining column %s.\n", column_names[i]);
199 return 1;
200 }
201 }
202 }
203
204 if (!SDDS_WriteLayout(&SDDS_dataset))
205 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
206 if (single_column_mode) {
207 if (!SDDS_StartPage(&SDDS_dataset, npixels))
208 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
209 for (i = 0; i < h; i++) {
210 for (j = 0; j < w; j++) {
211 /* Process pixel values for single column mode. */
212 data[0][j * h + i] = TIFFGetR(raster[n]) * rgb[0] + TIFFGetG(raster[n]) * rgb[1] + TIFFGetB(raster[n]) * rgb[2];
213 n++;
214 }
215 }
216
217 if (!SDDS_SetColumnFromLongs(&SDDS_dataset, SDDS_SET_BY_NAME, data[0], npixels, "z"))
218 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
219 } else {
220 if (!SDDS_StartPage(&SDDS_dataset, w))
221 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
222 for (i = 0; i < w; i++)
223 indexes[i] = i; /* Initialize index values. */
224 for (i = 0; i < h; i++) {
225 for (j = 0; j < w; j++) {
226 /* Process pixel values for multi-column mode. */
227 data[i][j] = TIFFGetR(raster[n]) * rgb[0] + TIFFGetG(raster[n]) * rgb[1] + TIFFGetB(raster[n]) * rgb[2];
228 n++;
229 }
230 }
231 if (!SDDS_SetColumnFromLongs(&SDDS_dataset, SDDS_SET_BY_NAME, indexes, w, "Index"))
232 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
233 for (i = 0; i < h; i++) {
234 if (!SDDS_SetColumnFromLongs(&SDDS_dataset, SDDS_SET_BY_NAME, data[i], w, column_names[i]))
235 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
236 }
237 }
238
239 if (!SDDS_WritePage(&SDDS_dataset) || !SDDS_Terminate(&SDDS_dataset))
240 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
241
242 if (single_column_mode) {
243 free(data[0]);
244 free(data);
245 } else {
246 for (i = 0; i < h; i++) {
247 free(column_names[i]);
248 free(data[i]);
249 }
250 free(column_names);
251 free(data);
252 }
253 }
254 _TIFFfree(raster); /* Free allocated memory for pixel data. */
255 }
256 TIFFClose(tif); /* Close TIFF file. */
257 }
258 if (indexes)
259 free(indexes); /* Free allocated memory for indexes. */
260 free_scanargs(&s_arg, argc); /* Free scanned arguments. */
261 return 0;
262}
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
OptionType
Enumeration for command-line options.