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