about summary refs log tree commit diff
path: root/converter/pgm/psidtopgm.c
blob: 07417d1b55e97bfbedf73ec6b475bb3f38e9226d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* psidtopgm.c - convert PostScript "image" data into a portable graymap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
*/

#include "pgm.h"


static int
gethexit(FILE * const ifp) {

    for ( ; ; ) {
        int const i = getc(ifp);
        if (i == EOF)
            pm_error("EOF / read error");
        else {
            char const c = (char) i;
            if (c >= '0' && c <= '9')
                return c - '0';
            else if (c >= 'A' && c <= 'F')
                return c - 'A' + 10;
            else if (c >= 'a' && c <= 'f')
                return c - 'a' + 10;
            /* Else ignore - whitespace. */
        }
    }
}



int
main(int     argc,
     char ** argv) {

    FILE * ifP;
    gray * grayrow;
    int argn, row;
    gray maxval;
    int rows, cols, bitspersample;

    pgm_init(&argc, argv);

    argn = 1;
    
    if (argn + 3 > argc)
        pm_error("Too few arguments");

    cols = atoi(argv[argn++]);
    rows = atoi(argv[argn++]);
    bitspersample = atoi(argv[argn++]);
    if (cols <= 0)
        pm_error("Columns must be positive.  You specified %d",
                 cols);
    if (rows <= 0)
        pm_error("Rows must be positive.  You specified %d",
                 rows);
    if (bitspersample <= 0)
        pm_error("Bits per sample must be positive.  You specified %d",
                 bitspersample);

    if (argn < argc)
        ifP = pm_openr(argv[argn++]);
    else
        ifP = stdin;

    if (argn != argc)
        pm_error("Too many arguments");

    maxval = pm_bitstomaxval(bitspersample);
    if (maxval > PGM_OVERALLMAXVAL)
        pm_error("bits/sample (%d) is too large.", bitspersample);

    pgm_writepgminit(stdout, cols, rows, maxval, 0);
    grayrow = pgm_allocrow((cols + 7) / 8 * 8);
    for (row = 0; row < rows; ++row) {
        unsigned int col;
        for (col = 0; col < cols; ) {
            int val;
            val = gethexit(ifP) << 4;
            val += gethexit(ifP);
            switch (bitspersample) {
            case 1:
                grayrow[col++] = val >> 7;
                grayrow[col++] = ( val >> 6 ) & 0x1;
                grayrow[col++] = ( val >> 5 ) & 0x1;
                grayrow[col++] = ( val >> 4 ) & 0x1;
                grayrow[col++] = ( val >> 3 ) & 0x1;
                grayrow[col++] = ( val >> 2 ) & 0x1;
                grayrow[col++] = ( val >> 1 ) & 0x1;
                grayrow[col++] = val & 0x1;
                break;

            case 2:
                grayrow[col++] = val >> 6;
                grayrow[col++] = ( val >> 4 ) & 0x3;
                grayrow[col++] = ( val >> 2 ) & 0x3;
                grayrow[col++] = val & 0x3;
                break;

            case 4:
                grayrow[col++] = val >> 4;
                grayrow[col++] = val & 0xf;
                break;

            case 8:
                grayrow[col++] = val;
                break;

            default:
                pm_error("This program does not know how to interpret a"
                         "%d bitspersample image", bitspersample );
            }
        }
        pgm_writepgmrow(stdout, grayrow, cols, (gray) maxval, 0);
    }
    pgm_freerow(grayrow);
    pm_close(ifP);
    pm_close(stdout);

    return 0;
}