SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sdds2tiff.c File Reference

Detailed Description

Converts SDDS files to TIFF images.

This program reads data from an SDDS (Self Describing Data Set) file and generates TIFF images. Each page in the input file is converted to a separate TIFF image. It supports options for processing pages, specifying data columns, and adjusting the output format.

Usage

sdds2tiff <input> <output>
[-pipe[=input]]
[-fromPage=<pageNumber>]
[-toPage=<pageNumber>]
[-columnPrefix=<Line>]
[-maxContrast]
[-16bit]

Options

Option Description
-pipe Specifies that input should be read from a pipe.
-fromPage Starts conversion from the specified page number.
-toPage Stops conversion at the specified page number.
-columnPrefix Prefix for column names containing line data.
-maxContrast Adjusts the image for maximum contrast.
-16bit Outputs images in 16-bit depth.

Incompatibilities

  • -columnPrefix requires a valid column prefix; otherwise, a default prefix Line is used.
  • -16bit changes the output depth to 16 bits and requires the maximum value in the data to not exceed 65535.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
R. Soliday, M. Borland

Definition in file sdds2tiff.c.

#include "tiffio.h"
#include "SDDS.h"
#include "mdb.h"
#include "scan.h"

Go to the source code of this file.

Functions

int main (int argc, char *argv[])
 

Function Documentation

◆ main()

int main ( int argc,
char * argv[] )

Definition at line 86 of file sdds2tiff.c.

86 {
87 SDDS_DATASET SDDS_dataset;
88 SCANNED_ARG *s_arg;
89 TIFF *tif;
90 char **columnNames = NULL;
91 char *input = NULL, *output = NULL;
92 char *columnPrefix = NULL;
93 char *buffer = NULL, *outputName = NULL;
94 uint16_t *buffer16 = NULL;
95 int32_t **data = NULL;
96 long j;
97 long bit16 = 0;
98 long linesFound = 0;
99 int64_t i, k;
100 int64_t rows = 0;
101 int32_t nColumns = 0;
102 long maxvalue = 0;
103 long page = 1;
104 long index = 1;
105 long fromPage = 0;
106 long toPage = 0;
107 int maxContrast = 0;
108 double div = 1;
109 char *xVar = NULL, *yVar = NULL;
110 char zColumnName[40];
111 char xDimName[40], yDimName[40];
112 int64_t xDim;
113 int32_t yDim;
114 long style = 1;
115 unsigned long pipeFlags = 0;
116 long maxPossibleLong = 255;
117 double maxPossible = maxPossibleLong;
118
119 /* Register program name */
121
122 /* Process arguments */
123 argc = scanargs(&s_arg, argc, argv);
124 if (argc < 3) {
125 fprintf(stderr, "%s", USAGE);
126 return 1;
127 }
128
129 /* Parse options */
130 for (i = 1; i < argc; i++) {
131 if (s_arg[i].arg_type == OPTION) {
132 switch (match_string(s_arg[i].list[0], option, N_OPTIONS, 0)) {
133 case OPT_MAXCONTRAST:
134 maxContrast = 1;
135 break;
136 case OPT_FROMPAGE:
137 if (s_arg[i].n_items < 2) {
138 SDDS_Bomb("invalid -fromPage syntax");
139 }
140 if (sscanf(s_arg[i].list[1], "%ld", &fromPage) != 1 || fromPage <= 0) {
141 SDDS_Bomb("invalid -fromPage syntax or value");
142 }
143 break;
144 case OPT_TOPAGE:
145 if (s_arg[i].n_items < 2) {
146 SDDS_Bomb("invalid -toPage syntax");
147 }
148 if (sscanf(s_arg[i].list[1], "%ld", &toPage) != 1 || toPage <= 0) {
149 SDDS_Bomb("invalid -toPage syntax or value");
150 }
151 break;
152 case OPT_COLUMNPREFIX:
153 if (s_arg[i].n_items < 2) {
154 SDDS_Bomb("invalid -columnPrefix syntax");
155 }
156 SDDS_CopyString(&columnPrefix, s_arg[i].list[1]);
157 break;
158 case OPT_PIPE:
159 if (!processPipeOption(s_arg[i].list + 1, s_arg[i].n_items - 1, &pipeFlags)) {
160 fprintf(stderr, "invalid -pipe syntax\n");
161 return 1;
162 }
163 break;
164 case OPT_16BIT:
165 bit16 = 1;
166 maxPossible = maxPossibleLong = 65535;
167 break;
168 default:
169 fprintf(stderr, "sdds2tiff: invalid option seen\n%s", USAGE);
170 return 1;
171 }
172 } else {
173 if (!input) {
174 SDDS_CopyString(&input, s_arg[i].list[0]);
175 } else if (!output) {
176 SDDS_CopyString(&output, s_arg[i].list[0]);
177 } else {
178 fprintf(stderr, "sdds2tiff: too many filenames\n%s", USAGE);
179 return 1;
180 }
181 }
182 }
183
184 if (fromPage && toPage && fromPage > toPage) {
185 SDDS_Bomb("invalid -fromPage and -toPage");
186 }
187
188 if (!columnPrefix) {
189 columnPrefix = malloc(5 * sizeof(char));
190 sprintf(columnPrefix, "Line");
191 }
192
193 if (pipeFlags & USE_STDIN) {
194 processFilenames("sdds2tiff", &input, &output, USE_STDIN, 1, NULL);
195 }
196 if (!SDDS_InitializeInput(&SDDS_dataset, input)) {
197 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
198 }
199
200 outputName = malloc((strlen(output) + 10) * sizeof(char));
201
202 /* Check required parameters */
203 if (SDDS_CheckParameter(&SDDS_dataset, "Variable1Name", NULL, SDDS_STRING, NULL) != SDDS_CHECK_OKAY) {
204 style = 2;
205 }
206 if (SDDS_CheckParameter(&SDDS_dataset, "Variable2Name", NULL, SDDS_STRING, NULL) != SDDS_CHECK_OKAY) {
207 style = 2;
208 }
209
210 columnNames = SDDS_GetColumnNames(&SDDS_dataset, &nColumns);
211 if (!columnNames) {
212 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
213 }
214
215 /* Handle different styles */
216 if (style == 1) {
217 if (nColumns != 1) {
218 fprintf(stderr, "sdds2tiff: Expected one column but found more than one\n");
219 return 1;
220 }
221 sprintf(zColumnName, "%s", columnNames[0]);
222 } else if (style == 2) {
223 for (i = 0; i < nColumns; i++) {
224 if (strncmp(columnPrefix, columnNames[i], strlen(columnPrefix)) == 0) {
225 linesFound++;
226 }
227 }
228 if (linesFound == 0) {
229 fprintf(stderr, "sdds2tiff: No columns found named %s*\n", columnPrefix);
230 return 1;
231 }
232 data = malloc(linesFound * sizeof(*data));
233 }
234
235 /* Process each page */
236 while (SDDS_ReadTable(&SDDS_dataset) > 0) {
237 if ((fromPage > 0 && fromPage > page) || (toPage > 0 && toPage < page)) {
238 continue;
239 }
240
241 rows = SDDS_RowCount(&SDDS_dataset);
242
243 if (style == 1) {
244 if (!SDDS_GetParameter(&SDDS_dataset, "Variable1Name", &xVar)) {
245 fprintf(stderr, "sdds2tiff: problem getting parameter Variable1Name\n");
246 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
247 }
248 if (!SDDS_GetParameter(&SDDS_dataset, "Variable2Name", &yVar)) {
249 fprintf(stderr, "sdds2tiff: problem getting parameter Variable2Name\n");
250 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
251 }
252
253 sprintf(xDimName, "%sDimension", xVar);
254 sprintf(yDimName, "%sDimension", yVar);
255 if (!SDDS_GetParameterAsLong64(&SDDS_dataset, xDimName, &xDim)) {
256 fprintf(stderr, "sdds2tiff: problem getting parameter %s\n", xDimName);
257 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
258 }
259 if (!SDDS_GetParameterAsLong(&SDDS_dataset, yDimName, &yDim)) {
260 fprintf(stderr, "sdds2tiff: problem getting parameter %s\n", yDimName);
261 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
262 }
263
264 fprintf(stderr, "%s %s\n", xVar, yVar);
265 fprintf(stderr, "%" PRId64 " %" PRId32 "\n", xDim, yDim);
266 free(xVar);
267 free(yVar);
268
269 if (xDim * yDim != rows) {
270 fprintf(stderr, "sdds2tiff: %s * %s does not equal the number of rows in the page\n", xDimName, yDimName);
271 return 1;
272 }
273
274 data = malloc(sizeof(*data));
275 data[0] = SDDS_GetColumnInLong(&SDDS_dataset, zColumnName);
276 for (i = 0; i < rows; i++) {
277 if (data[0][i] > maxvalue) {
278 maxvalue = data[0][i];
279 }
280 }
281
282 if (!bit16) {
283 buffer = malloc(rows * sizeof(char));
284 } else {
285 buffer16 = malloc(rows * sizeof(int16_t));
286 }
287 } else if (style == 2) {
288 j = 0;
289 for (i = 0; i < nColumns; i++) {
290 if (strncmp(columnPrefix, columnNames[i], strlen(columnPrefix)) == 0) {
291 data[j] = SDDS_GetColumnInLong(&SDDS_dataset, columnNames[i]);
292 for (k = 0; k < rows; k++) {
293 if (data[j][k] > maxvalue) {
294 maxvalue = data[j][k];
295 }
296 }
297 j++;
298 }
299 }
300
301 if (!bit16) {
302 buffer = malloc(rows * linesFound * sizeof(char));
303 } else {
304 buffer16 = malloc(rows * linesFound * sizeof(uint16_t));
305 }
306
307 xDim = rows;
308 yDim = linesFound;
309 }
310
311 if (maxContrast) {
312 div = maxvalue / maxPossible;
313 } else if (maxvalue <= maxPossibleLong) {
314 div = 1;
315 } else if (maxvalue <= 3 * maxPossibleLong) {
316 div = 3;
317 } else {
318 div = maxvalue / maxPossible;
319 }
320
321 sprintf(outputName, "%s.%04ld", output, index);
322 tif = TIFFOpen(outputName, "w");
323 if (tif) {
324 TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, xDim);
325 TIFFSetField(tif, TIFFTAG_IMAGELENGTH, yDim);
326 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bit16 ? 16 : 8);
327 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
328 TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, yDim);
329 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
330 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
331 TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
332 TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
333 TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
334
335 if (style == 1) {
336 k = 0;
337 for (i = 0; i < xDim; i++) {
338 for (j = 0; j < yDim; j++) {
339 if (!bit16) {
340 buffer[xDim * (yDim - (j + 1)) + i] = (unsigned int)(round(data[0][k] / div));
341 } else {
342 buffer16[xDim * (yDim - (j + 1)) + i] = (uint16_t)(round(data[0][k] / div));
343 }
344 k++;
345 }
346 }
347 TIFFWriteEncodedStrip(tif, 0, bit16 ? (char *)buffer16 : buffer, rows * (bit16 ? 2 : 1));
348 } else if (style == 2) {
349 for (j = 0; j < yDim; j++) {
350 for (i = 0; i < xDim; i++) {
351 if (!bit16) {
352 buffer[j * xDim + i] = (unsigned int)(round(data[(yDim - j) - 1][i] / div));
353 } else {
354 buffer16[j * xDim + i] = (uint16_t)(round(data[(yDim - j) - 1][i] / div));
355 }
356 }
357 }
358 TIFFWriteEncodedStrip(tif, 0, bit16 ? (char *)buffer16 : buffer, xDim * yDim * (bit16 ? 2 : 1));
359 }
360 TIFFClose(tif);
361 }
362
363 if (buffer) {
364 free(buffer);
365 }
366 if (buffer16) {
367 free(buffer16);
368 }
369 if (style == 1) {
370 free(data[0]);
371 free(data);
372 } else if (style == 2) {
373 for (j = 0; j < yDim; j++) {
374 free(data[j]);
375 }
376 }
377
378 index++;
379 }
380
381 if (!SDDS_Terminate(&SDDS_dataset)) {
382 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
383 }
384
385 if (input) {
386 free(input);
387 }
388 if (output) {
389 free(output);
390 }
391 if (outputName) {
392 free(outputName);
393 }
394
395 for (i = 0; i < nColumns; i++) {
396 if (columnNames[i]) {
397 free(columnNames[i]);
398 }
399 }
400
401 if (columnNames) {
402 free(columnNames);
403 }
404
405 if (style == 2 && data) {
406 free(data);
407 }
408
409 free_scanargs(&s_arg, argc);
410 return 0;
411}
int32_t * SDDS_GetParameterAsLong(SDDS_DATASET *SDDS_dataset, char *parameter_name, int32_t *memory)
Retrieves the value of a specified parameter as a 32-bit integer from the current data table of a dat...
int32_t * SDDS_GetColumnInLong(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of 32-bit integers,...
void * SDDS_GetParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory)
Retrieves the value of a specified parameter from the current data table of a data set.
int64_t * SDDS_GetParameterAsLong64(SDDS_DATASET *SDDS_dataset, char *parameter_name, int64_t *memory)
Retrieves the value of a specified parameter as a 64-bit integer from the current data table of an SD...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.
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
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
int32_t SDDS_CheckParameter(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a parameter exists in the SDDS dataset with the specified name, units, and type.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
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
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584