1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * generate_etsi_300_242_pages.c - Create the test pages defined in ETSI ETS 300 242.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2006 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2, as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 /*! \file */
27
28 #if defined(HAVE_CONFIG_H)
29 #include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <inttypes.h>
34 #include <limits.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <stdlib.h>
38 #include <time.h>
39 #include <memory.h>
40 #include <string.h>
41 #if defined(HAVE_TGMATH_H)
42 #include <tgmath.h>
43 #endif
44 #if defined(HAVE_MATH_H)
45 #include <math.h>
46 #endif
47
48 #include "spandsp.h"
49
50 struct
51 {
52 const char *name;
53 int x_res;
54 int y_res;
55 int width;
56 int length;
57 int compression;
58 int type;
59 } sequence[] =
60 {
61 {
62 "etsi_300_242_a4_diago1.tif",
63 T4_X_RESOLUTION_R8,
64 T4_Y_RESOLUTION_STANDARD,
65 T4_WIDTH_R8_A4,
66 1002,
67 COMPRESSION_CCITT_T4,
68 0
69 },
70 {
71 "etsi_300_242_a4_diago2.tif",
72 T4_X_RESOLUTION_R8,
73 T4_Y_RESOLUTION_STANDARD,
74 T4_WIDTH_R8_A4,
75 1002,
76 COMPRESSION_CCITT_T4,
77 1
78 },
79 {
80 "etsi_300_242_a4_duration1.tif",
81 T4_X_RESOLUTION_R8,
82 T4_Y_RESOLUTION_STANDARD,
83 T4_WIDTH_R8_A4,
84 237,
85 COMPRESSION_CCITT_T4,
86 2
87 },
88 {
89 "etsi_300_242_a4_duration2.tif",
90 T4_X_RESOLUTION_R8,
91 T4_Y_RESOLUTION_STANDARD,
92 T4_WIDTH_R8_A4,
93 237,
94 COMPRESSION_CCITT_T4,
95 3
96 },
97 {
98 "etsi_300_242_a4_error.tif",
99 T4_X_RESOLUTION_R8,
100 T4_Y_RESOLUTION_STANDARD,
101 T4_WIDTH_R8_A4,
102 400,
103 COMPRESSION_CCITT_T4,
104 4
105 },
106 {
107 "etsi_300_242_a4_impress.tif",
108 T4_X_RESOLUTION_R8,
109 T4_Y_RESOLUTION_STANDARD,
110 T4_WIDTH_R8_A4,
111 1079,
112 COMPRESSION_CCITT_T4,
113 5
114 },
115 {
116 "etsi_300_242_a4_stairstep.tif",
117 T4_X_RESOLUTION_R8,
118 T4_Y_RESOLUTION_STANDARD,
119 T4_WIDTH_R8_A4,
120 1728,
121 COMPRESSION_CCITT_T4,
122 6
123 },
124 {
125 "etsi_300_242_a4_white.tif",
126 T4_X_RESOLUTION_R8,
127 T4_Y_RESOLUTION_STANDARD,
128 T4_WIDTH_R8_A4,
129 1100,
130 COMPRESSION_CCITT_T4,
131 7
132 },
133 {
134 "etsi_300_242_a4_white_2p.tif",
135 T4_X_RESOLUTION_R8,
136 T4_Y_RESOLUTION_STANDARD,
137 T4_WIDTH_R8_A4,
138 1100,
139 COMPRESSION_CCITT_T4,
140 7
141 },
142 { /* Second page of the above file */
143 "",
144 T4_X_RESOLUTION_R8,
145 T4_Y_RESOLUTION_STANDARD,
146 T4_WIDTH_R8_A4,
147 1100,
148 COMPRESSION_CCITT_T4,
149 7
150 },
151 {
152 "etsi_300_242_a4_impress_white.tif",
153 T4_X_RESOLUTION_R8,
154 T4_Y_RESOLUTION_STANDARD,
155 T4_WIDTH_R8_A4,
156 1079,
157 COMPRESSION_CCITT_T4,
158 5
159 },
160 { /* Second page of the above file */
161 "",
162 T4_X_RESOLUTION_R8,
163 T4_Y_RESOLUTION_STANDARD,
164 T4_WIDTH_R8_A4,
165 1100,
166 COMPRESSION_CCITT_T4,
167 7
168 },
169 {
170 NULL,
171 0,
172 0,
173 0,
174 0
175 },
176 };
177
178 int photo_metric = PHOTOMETRIC_MINISWHITE;
179 int fill_order = FILLORDER_LSB2MSB;
180
set_pixel(uint8_t buf[],int row,int pixel)181 static void set_pixel(uint8_t buf[], int row, int pixel)
182 {
183 row--;
184 buf[row*1728/8 + pixel/8] |= (0x80 >> (pixel & 0x07));
185 }
186 /*- End of function --------------------------------------------------------*/
187
set_pixel_range(uint8_t buf[],int row,int start,int end)188 static void set_pixel_range(uint8_t buf[], int row, int start, int end)
189 {
190 int i;
191
192 for (i = start; i <= end; i++)
193 set_pixel(buf, row, i);
194 }
195 /*- End of function --------------------------------------------------------*/
196
clear_pixel(uint8_t buf[],int row,int pixel)197 static void clear_pixel(uint8_t buf[], int row, int pixel)
198 {
199 row--;
200 buf[row*1728/8 + pixel/8] &= ~(0x80 >> (pixel & 0x07));
201 }
202 /*- End of function --------------------------------------------------------*/
203
clear_pixel_range(uint8_t buf[],int row,int start,int end)204 static void clear_pixel_range(uint8_t buf[], int row, int start, int end)
205 {
206 int i;
207
208 for (i = start; i <= end; i++)
209 clear_pixel(buf, row, i);
210 }
211 /*- End of function --------------------------------------------------------*/
212
clear_row(uint8_t buf[],int width)213 static void clear_row(uint8_t buf[], int width)
214 {
215 memset(buf, 0, width/8 + 1);
216 }
217 /*- End of function --------------------------------------------------------*/
218
create_white_page(TIFF * tiff_file)219 static int create_white_page(TIFF *tiff_file)
220 {
221 uint8_t image_buffer[8192];
222 int row;
223
224 /* TSB-85 WHITE page. */
225 for (row = 0; row < 1100; row++)
226 {
227 clear_row(image_buffer, 1728);
228 if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0)
229 {
230 printf("Write error at row %d.\n", row);
231 exit(2);
232 }
233 }
234 return 1100;
235 }
236 /*- End of function --------------------------------------------------------*/
237
create_stairstep_page(TIFF * tiff_file)238 static int create_stairstep_page(TIFF *tiff_file)
239 {
240 uint8_t image_buffer[8192];
241 int row;
242 int start_pixel;
243 int i;
244
245 /* TSB-85 STAIRSTEP page. */
246 start_pixel = 0;
247 for (row = 0; row < 1728; row++)
248 {
249 clear_row(image_buffer, 1728);
250 set_pixel_range(image_buffer, 1, start_pixel, start_pixel + 63);
251 if (photo_metric != PHOTOMETRIC_MINISWHITE)
252 {
253 for (i = 0; i < 1728/8; i++)
254 image_buffer[i] = ~image_buffer[i];
255 }
256 #if 0
257 if (fill_order != FILLORDER_LSB2MSB)
258 bit_reverse(image_buffer, image_buffer, 1728/8);
259 #endif
260 if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0)
261 {
262 printf("Write error at row %d.\n", row);
263 exit(2);
264 }
265 start_pixel += 64;
266 if (start_pixel >= 1728)
267 start_pixel = 0;
268 }
269 return 1728;
270 }
271 /*- End of function --------------------------------------------------------*/
272
create_diago1_page(TIFF * tiff_file)273 static int create_diago1_page(TIFF *tiff_file)
274 {
275 uint8_t image_buffer[1728/8 + 1];
276 int row;
277
278 /* ETSI ETS 300 242 B.5.1 One dimensional coding test chart - the DIAGO1 page. */
279 for (row = 0; row < 1001; row++)
280 {
281 clear_row(image_buffer, 1728);
282 set_pixel_range(image_buffer, 1, row, 1727);
283 if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0)
284 {
285 printf("Write error at row %d.\n", row);
286 exit(2);
287 }
288 }
289 clear_row(image_buffer, 1728);
290 set_pixel_range(image_buffer, 1, 0, 1727);
291 if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0)
292 {
293 printf("Write error at row %d.\n", row);
294 exit(2);
295 }
296 return 1002;
297 }
298 /*- End of function --------------------------------------------------------*/
299
create_diago2_page(TIFF * tiff_file)300 static int create_diago2_page(TIFF *tiff_file)
301 {
302 uint8_t image_buffer[1728/8 + 1];
303 int row;
304
305 /* ETSI ETS 300 242 B.5.1 One dimensional coding test chart - the DIAGO2 page. */
306 for (row = 0; row < 1001; row++)
307 {
308 clear_row(image_buffer, 1728);
309 set_pixel_range(image_buffer, 1, row + 728, 1727);
310 if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0)
311 {
312 printf("Write error at row %d.\n", row);
313 exit(2);
314 }
315 }
316 clear_row(image_buffer, 1728);
317 set_pixel_range(image_buffer, 1, 0, 1727);
318 if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0)
319 {
320 printf("Write error at row %d.\n", row);
321 exit(2);
322 }
323 return 1002;
324 }
325 /*- End of function --------------------------------------------------------*/
326
create_impress_page(TIFF * tiff_file)327 static int create_impress_page(TIFF *tiff_file)
328 {
329 int j;
330 int row;
331 uint8_t *page;
332
333 /* ETSI ETS 300 242 B.5.2 Printing resolution - the IMPRESS page */
334 if ((page = malloc(1079*1728/8)) == NULL)
335 return 0;
336 memset(page, 0, 1079*1728/8);
337
338 set_pixel_range(page, 1, 0, 1727);
339 for (row = 2; row <= 78; row++)
340 {
341 set_pixel_range(page, row, 850, 850 + 27);
342 set_pixel_range(page, row, 850 + 27 + 745, 850 + 27 + 745 + 26);
343 }
344 for (row = 80; row <= 117; row++)
345 {
346 for (j = 0; j < 1728; j += 2)
347 set_pixel(page, row, j);
348 }
349 for (row = 118; row <= 155; row++)
350 {
351 for (j = 1; j < 1728; j += 2)
352 set_pixel(page, row, j);
353 }
354 for (row = 194; row <= 231; row += 2)
355 set_pixel_range(page, row, 0, 1727);
356 for (row = 270; row <= 276; row++)
357 set_pixel_range(page, row, 60, 60 + 1607);
358 for (j = 0; j < 1728; j += 27)
359 set_pixel(page, 315, j);
360 for (row = 354; row <= 480; row++)
361 set_pixel_range(page, row, 209, 768);
362 for (row = 358; row <= 476; row++)
363 clear_pixel_range(page, row, 488, 489);
364 clear_pixel_range(page, 417, 217, 760);
365
366 for (row = 354; row <= 357; row++)
367 set_pixel_range(page, row, 962, 1521);
368 for (row = 477; row <= 480; row++)
369 set_pixel_range(page, row, 962, 1521);
370 for (row = 358; row <= 476; row++)
371 set_pixel_range(page, row, 962, 969);
372 for (row = 358; row <= 476; row++)
373 set_pixel_range(page, row, 1514, 1521);
374 for (row = 358; row <= 476; row++)
375 set_pixel(page, row, 1241);
376 set_pixel_range(page, 417, 970, 1513);
377
378 for (row = 354; row <= 1079; row++)
379 set_pixel(page, row, 864);
380 for (row = 157; row <= 926; row++)
381 set_pixel_range(page, row, 884, 899);
382 for (row = 0; row < 1079; row++)
383 {
384 if (TIFFWriteScanline(tiff_file, page + row*1728/8, row, 0) < 0)
385 {
386 printf("Write error at row %d.\n", row);
387 exit(2);
388 }
389 }
390 free(page);
391 return 1079;
392 }
393 /*- End of function --------------------------------------------------------*/
394
create_duration1_page(TIFF * tiff_file)395 static int create_duration1_page(TIFF *tiff_file)
396 {
397 uint8_t image_buffer[1728/8 + 1];
398 int row;
399 int i;
400
401 /* ETSI ETS 300 242 B.5.3 Acceptance of total coded scan line duration - the DURATION1 page */
402 row = 0;
403 clear_row(image_buffer, 1728);
404 set_pixel_range(image_buffer, 1, 0, 1727);
405 if (TIFFWriteScanline(tiff_file, image_buffer, row++, 0) < 0)
406 {
407 printf("Write error at row %d.\n", row);
408 exit(2);
409 }
410 for ( ; row < 117; row++)
411 {
412 clear_row(image_buffer, 1728);
413 if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0)
414 {
415 printf("Write error at row %d.\n", row);
416 exit(2);
417 }
418 }
419 clear_row(image_buffer, 1728);
420 set_pixel_range(image_buffer, 1, 0, 1727);
421 if (TIFFWriteScanline(tiff_file, image_buffer, row++, 0) < 0)
422 {
423 printf("Write error at row %d.\n", row);
424 exit(2);
425 }
426 clear_row(image_buffer, 1728);
427 for (i = 1; i < 1728; i += 2)
428 set_pixel(image_buffer, 1, i);
429 if (TIFFWriteScanline(tiff_file, image_buffer, row++, 0) < 0)
430 {
431 printf("Write error at row %d.\n", row);
432 exit(2);
433 }
434 clear_row(image_buffer, 1728);
435 set_pixel_range(image_buffer, 1, 0, 1727);
436 if (TIFFWriteScanline(tiff_file, image_buffer, row++, 0) < 0)
437 {
438 printf("Write error at row %d.\n", row);
439 exit(2);
440 }
441 for ( ; row < 236; row++)
442 {
443 clear_row(image_buffer, 1728);
444 if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0)
445 {
446 printf("Write error at row %d.\n", row);
447 exit(2);
448 }
449 }
450 clear_row(image_buffer, 1728);
451 set_pixel_range(image_buffer, 1, 0, 1727);
452 if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0)
453 {
454 printf("Write error at row %d.\n", row);
455 exit(2);
456 }
457 return 237;
458 }
459 /*- End of function --------------------------------------------------------*/
460
create_duration2_page(TIFF * tiff_file)461 static int create_duration2_page(TIFF *tiff_file)
462 {
463 return create_duration1_page(tiff_file);
464 }
465 /*- End of function --------------------------------------------------------*/
466
create_error_page(TIFF * tiff_file)467 static int create_error_page(TIFF *tiff_file)
468 {
469 uint8_t image_buffer[1728/8 + 1];
470 int row;
471 int start_pixel;
472 int i;
473
474 /* ETSI ETS 300 242 B.5.4 Copy quality criteria - the ERROR page. */
475 for (row = 0; row < 68; row++)
476 {
477 clear_row(image_buffer, 1728);
478 if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0)
479 {
480 printf("Write error at row %d.\n", row);
481 exit(2);
482 }
483 }
484
485 clear_row(image_buffer, 1728);
486 set_pixel_range(image_buffer, 1, 0, 1727);
487 if (TIFFWriteScanline(tiff_file, image_buffer, row++, 0) < 0)
488 {
489 printf("Write error at row %d.\n", row);
490 exit(2);
491 }
492
493 clear_row(image_buffer, 1728);
494 if (TIFFWriteScanline(tiff_file, image_buffer, row++, 0) < 0)
495 {
496 printf("Write error at row %d.\n", row);
497 exit(2);
498 }
499
500 for (i = 0; i < 10; i++)
501 {
502 for (start_pixel = 16; start_pixel <= 1616; start_pixel += 64)
503 {
504 clear_row(image_buffer, 1728);
505 set_pixel_range(image_buffer, 1, start_pixel, start_pixel + 63);
506 if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0)
507 {
508 printf("Write error at row %d.\n", row);
509 exit(2);
510 }
511 row++;
512 }
513 }
514
515 clear_row(image_buffer, 1728);
516 if (TIFFWriteScanline(tiff_file, image_buffer, row++, 0) < 0)
517 {
518 printf("Write error at row %d.\n", row);
519 exit(2);
520 }
521
522 clear_row(image_buffer, 1728);
523 set_pixel_range(image_buffer, 1, 0, 1727);
524 if (TIFFWriteScanline(tiff_file, image_buffer, row++, 0) < 0)
525 {
526 printf("Write error at row %d.\n", row);
527 exit(2);
528 }
529
530 for (row = 332; row < 400; row++)
531 {
532 clear_row(image_buffer, 1728);
533 if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0)
534 {
535 printf("Write error at row %d.\n", row);
536 exit(2);
537 }
538 }
539
540 return 400;
541 }
542 /*- End of function --------------------------------------------------------*/
543
main(int argc,char * argv[])544 int main(int argc, char *argv[])
545 {
546 TIFF *tiff_file;
547 struct tm *tm;
548 time_t now;
549 char buf[133];
550 float x_resolution;
551 float y_resolution;
552 int i;
553 int image_length;
554 int opt;
555
556 photo_metric = PHOTOMETRIC_MINISWHITE;
557 fill_order = FILLORDER_LSB2MSB;
558 while ((opt = getopt(argc, argv, "ir")) != -1)
559 {
560 switch (opt)
561 {
562 case 'i':
563 photo_metric = PHOTOMETRIC_MINISBLACK;
564 break;
565 case 'r':
566 fill_order = FILLORDER_MSB2LSB;
567 break;
568 default:
569 //usage();
570 exit(2);
571 break;
572 }
573 }
574
575 tiff_file = NULL;
576 for (i = 0; sequence[i].name; i++)
577 {
578 if (sequence[i].name[0])
579 {
580 if (tiff_file)
581 TIFFClose(tiff_file);
582 if ((tiff_file = TIFFOpen(sequence[i].name, "w")) == NULL)
583 exit(2);
584 }
585 /* Prepare the directory entry fully before writing the image, or libtiff complains */
586 TIFFSetField(tiff_file, TIFFTAG_COMPRESSION, sequence[i].compression);
587 if (sequence[i].compression == COMPRESSION_CCITT_T4)
588 {
589 TIFFSetField(tiff_file, TIFFTAG_T4OPTIONS, GROUP3OPT_FILLBITS); // | GROUP3OPT_2DENCODING);
590 TIFFSetField(tiff_file, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
591 }
592 TIFFSetField(tiff_file, TIFFTAG_IMAGEWIDTH, sequence[i].width);
593 TIFFSetField(tiff_file, TIFFTAG_BITSPERSAMPLE, 1);
594 TIFFSetField(tiff_file, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
595 TIFFSetField(tiff_file, TIFFTAG_SAMPLESPERPIXEL, 1);
596 TIFFSetField(tiff_file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
597 TIFFSetField(tiff_file, TIFFTAG_PHOTOMETRIC, photo_metric);
598 TIFFSetField(tiff_file, TIFFTAG_FILLORDER, fill_order);
599 x_resolution = sequence[i].x_res/100.0f;
600 y_resolution = sequence[i].y_res/100.0f;
601 TIFFSetField(tiff_file, TIFFTAG_XRESOLUTION, floorf(x_resolution*2.54f + 0.5f));
602 TIFFSetField(tiff_file, TIFFTAG_YRESOLUTION, floorf(y_resolution*2.54f + 0.5f));
603 TIFFSetField(tiff_file, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
604
605 TIFFSetField(tiff_file, TIFFTAG_SOFTWARE, "spandsp");
606 if (gethostname(buf, sizeof(buf)) == 0)
607 TIFFSetField(tiff_file, TIFFTAG_HOSTCOMPUTER, buf);
608
609 TIFFSetField(tiff_file, TIFFTAG_IMAGEDESCRIPTION, "Blank test image");
610 TIFFSetField(tiff_file, TIFFTAG_MAKE, "soft-switch.org");
611 TIFFSetField(tiff_file, TIFFTAG_MODEL, "test data");
612
613 time(&now);
614 tm = localtime(&now);
615 sprintf(buf,
616 "%4d/%02d/%02d %02d:%02d:%02d",
617 tm->tm_year + 1900,
618 tm->tm_mon + 1,
619 tm->tm_mday,
620 tm->tm_hour,
621 tm->tm_min,
622 tm->tm_sec);
623 TIFFSetField(tiff_file, TIFFTAG_DATETIME, buf);
624 image_length = sequence[i].length;
625 TIFFSetField(tiff_file, TIFFTAG_PAGENUMBER, 0, 1);
626 TIFFSetField(tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_CLEAN);
627 TIFFSetField(tiff_file, TIFFTAG_ROWSPERSTRIP, 128);
628 TIFFSetField(tiff_file, TIFFTAG_IMAGELENGTH, image_length);
629 TIFFCheckpointDirectory(tiff_file);
630
631 /* Write the image first.... */
632 switch (sequence[i].type)
633 {
634 case 0:
635 /* The DIAGO1 page */
636 image_length = create_diago1_page(tiff_file);
637 break;
638 case 1:
639 /* The DIAGO2 page */
640 image_length = create_diago2_page(tiff_file);
641 break;
642 case 2:
643 /* The DURATION1 page */
644 image_length = create_duration1_page(tiff_file);
645 break;
646 case 3:
647 /* The DURATION2 page */
648 image_length = create_duration2_page(tiff_file);
649 break;
650 case 4:
651 /* The ERROR page */
652 image_length = create_error_page(tiff_file);
653 break;
654 case 5:
655 /* The IMPRESS page */
656 image_length = create_impress_page(tiff_file);
657 break;
658 case 6:
659 /* A stairstep of 64 pixel dashes */
660 image_length = create_stairstep_page(tiff_file);
661 break;
662 case 7:
663 /* A white A4 page */
664 image_length = create_white_page(tiff_file);
665 break;
666 }
667 /* ....then the directory entry, and libtiff is happy. */
668 if (image_length != sequence[i].length)
669 {
670 printf("Length mismatch - %d: %d vs %d\n", i, image_length, sequence[i].length);
671 exit(2);
672 }
673
674 TIFFWriteDirectory(tiff_file);
675 }
676 if (tiff_file)
677 TIFFClose(tiff_file);
678 return 0;
679 }
680 /*- End of function --------------------------------------------------------*/
681 /*- End of file ------------------------------------------------------------*/
682