~ubuntu-branches/ubuntu/vivid/ghostscript/vivid-security

« back to all changes in this revision

Viewing changes to toolbin/halftone/ETS/test_ets.c

  • Committer: Package Import Robot
  • Author(s): Till Kamppeter
  • Date: 2013-08-09 20:01:36 UTC
  • mfrom: (1.1.37)
  • Revision ID: package-import@ubuntu.com-20130809200136-amb6zrr7hnjb5jq9
Tags: 9.08~rc1~dfsg-0ubuntu1
* New upstream release
   - Ghostscript 9.08rc1.
   - We are using the system's liblcms2 and libopenjpeg now.
* debian/patches/020130401-852e545-pxl-xl-driver-produced-drawing-commands-without-setting-color-space.patch:
  Removed patch backported from upstream.
* debian/patches/ojdk-8007925+8007926.patch,
  debian/patches/ojdk-8007927.patch,
  debian/patches/ojdk-8007929.patch,
  debian/patches/ojdk-8009654.patch: Removed patches on build in liblcms2, we
  use the system's liblcms2 now.
* debian/patches/2001_docdir_fix_for_debian.patch: Manually updated to new
  upstream source code.
* debian/patches/2003_support_multiarch.patch: Refreshed with quilt.
* debian/control: Added build dependencies on liblcms2-dev and
  libopenjpeg-dev.
* debian/rules: Check for removed lcms2/ and openjpeg/ subdirectories in
  the repackaging check again, also set build options for shared liblcms2
  and libopenjpeg libraries.
* debian/rules: Makefile.in and configure.ac are in the root directory of
  the source now and do not need to get linked from base/. Also there is no
  gstoraster and gstopxl CUPS filter in the package any more and no
  "install-cups" make target any more.
* debian/control, debian/rules, debian/ghostscript-cups.install,
  debian/ghostscript-cups.ppd-updater: Removed the ghostscript-cups binary
  package. The files are now provided by cups-filters.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
#include <stdlib.h>
 
3
#include <string.h>
 
4
#include <math.h>
 
5
#include "ets.h"
 
6
 
 
7
#define noDUMP_FILE_NAME "dump.ebdp"
 
8
 
 
9
#define LITTLE_ENDIAN /* Needed for PSD support */
 
10
//#define TEST_PSD_DUMP 
 
11
 
 
12
/* PSD structure.  Since this data can be compressed planar data we need an object
 
13
   to maintain our context state. */
 
14
struct psd_ctx_s {
 
15
    int width;
 
16
    int height;
 
17
    int num_channels; 
 
18
    int depth;
 
19
    int curr_row;
 
20
    void *rle_row;
 
21
    int *row_lengths;
 
22
    int *band_row_length_index;
 
23
    long *band_file_offset;
 
24
    void *output_buffer;
 
25
    void (*read_line)(ETS_SrcPixel **ibufs, int xs, FILE *fi, int planes, void *image_ctx);
 
26
    void (*write_line)(uchar **obufs, int xs, FILE *fo, int planes, void *image_ctx);
 
27
    void (*finalize)(void *image_ctx);
 
28
    uchar *permute;
 
29
};
 
30
 
 
31
typedef struct psd_ctx_s psd_ctx_t;
 
32
 
 
33
static void
 
34
die(char *why)
 
35
{
 
36
    fprintf(stderr, "%s\n", why);
 
37
    exit(1);
 
38
}
 
39
 
 
40
#define MAX_SIZE 65536
 
41
 
 
42
#define M 16
 
43
 
 
44
static const char * get_arg (int argc, char **argv, int *pi, const char *arg)
 
45
{
 
46
    if (arg[0] != 0) {
 
47
        return arg;
 
48
    } else {
 
49
        (*pi)++;
 
50
        if (*pi == argc) {
 
51
            return NULL;
 
52
        } else {
 
53
            return argv[*pi];
 
54
        }
 
55
    }
 
56
}
 
57
 
 
58
static int usage (void)
 
59
{
 
60
    printf("Usage: ETS\n");
 
61
    printf("ETS <options>\n");
 
62
    printf("    -i <inputfile      .pam or .pgm - omit for stdin\n");
 
63
    printf("    -o <outputfile>    same format as input - omit for stdout\n");
 
64
    printf("    -g <gammafile>     optional textual table of gamma values\n");
 
65
    printf("    -e <style>         ets style (0 off, 1 = normal, etc)\n");
 
66
    printf("    -r <style>         random noise style (0 off, 1 = rnd, 2 = tm\n");
 
67
    printf("    -m <0 or 1>        enable/disable multiplane optimisations\n");
 
68
    printf("    -l <levels>        number of levels in the output\n");
 
69
    printf("    -a X:Y             aspect ratio of input\n");
 
70
    printf("    -n <noise level>   noise level (0 to 8)\n");
 
71
    printf("\n\nDefaults: -e1 -r1 -m1 -l2 -a1:1 -n0\n");
 
72
    return 1;
 
73
}
 
74
 
 
75
static void get4(int *value, uchar *buf)
 
76
{
 
77
#ifdef LITTLE_ENDIAN
 
78
    *value = buf[3] + (buf[2] << 8) + (buf[1] << 16) + (buf[0] << 24);
 
79
#else
 
80
    *value = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
 
81
#endif
 
82
}
 
83
 
 
84
static void get2(int *value, uchar *buf)
 
85
{
 
86
#ifdef LITTLE_ENDIAN
 
87
    *value = buf[1] + (buf[0] << 8);
 
88
#else
 
89
    *value = buf[0] + (buf[1] << 8);
 
90
#endif
 
91
}
 
92
 
 
93
/* PSD uses PackBits RLE */
 
94
static void rle_decode(uchar *in_buff, int in_length, 
 
95
                       uchar *out_buff, int out_length)
 
96
{
 
97
    signed char hvalue, *input_buf;
 
98
    char value;
 
99
    int in_pos = 0, out_pos = 0;
 
100
 
 
101
    input_buf = (signed char*) in_buff;
 
102
    while (out_pos < out_length) 
 
103
    {
 
104
        hvalue = input_buf[in_pos];
 
105
        if (hvalue >= 0) 
 
106
        {
 
107
            /* 1+hvalue literal bytes follow */
 
108
            memcpy(&(out_buff[out_pos]), &(in_buff[in_pos + 1]), (1 + hvalue));
 
109
            in_pos += (1 + (1 + hvalue));
 
110
            out_pos += (1 + hvalue);
 
111
        } 
 
112
        else if (hvalue > -128)
 
113
        {
 
114
            /* Repeat next byte 1-n times */
 
115
            value = in_buff[in_pos+1];
 
116
            memset(&(out_buff[out_pos]), value, (1 - hvalue));
 
117
            in_pos += 2;
 
118
            out_pos += (1 - hvalue);
 
119
        }
 
120
        else
 
121
            in_pos += 1;
 
122
    }
 
123
}
 
124
 
 
125
/* Photoshop RLE 8 bit case */
 
126
static void read_psd_line_rle8(ETS_SrcPixel **ibufs, int xs, FILE *fi, int planes, 
 
127
                              void *image_ctx)
 
128
{
 
129
    int kk;
 
130
    psd_ctx_t *psd_ctx = (psd_ctx_t*) image_ctx;
 
131
    long curr_file_offset;
 
132
    int curr_row_length_index;
 
133
    int curr_length;
 
134
 
 
135
    /* Loop across each band */  
 
136
    for (kk = 0; kk < planes; kk++) 
 
137
    {
 
138
        /* Get a pointer and a length for the current one */
 
139
        curr_file_offset = psd_ctx->band_file_offset[kk];
 
140
        curr_row_length_index = psd_ctx->band_row_length_index[kk];
 
141
        curr_length = psd_ctx->row_lengths[curr_row_length_index];
 
142
        /* Get to where we are located in the file, read and decode */
 
143
        fseek(fi, curr_file_offset, SEEK_SET); 
 
144
        fread(psd_ctx->rle_row, 1, curr_length, fi);
 
145
        rle_decode((uchar*) psd_ctx->rle_row, curr_length, ibufs[psd_ctx->permute[kk]], 
 
146
                    psd_ctx->width);
 
147
        /* Update where we are in each band */
 
148
        psd_ctx->band_file_offset[kk] += curr_length;
 
149
        psd_ctx->band_row_length_index[kk] += 1;
 
150
    } 
 
151
}
 
152
 
 
153
/* Photoshop unencoded 8 bit case */
 
154
static void read_psd_line8(ETS_SrcPixel **ibufs, int xs, FILE *fi, int planes,
 
155
                          void *image_ctx)
 
156
{
 
157
    int kk;
 
158
    psd_ctx_t *psd_ctx = (psd_ctx_t*) image_ctx;
 
159
    long curr_file_offset;
 
160
    int curr_length = psd_ctx->width;
 
161
 
 
162
    /* Loop across each band */
 
163
    for (kk = 0; kk < planes; kk++) 
 
164
    {
 
165
        /* Get a pointer and a length for the current one */
 
166
        curr_file_offset = psd_ctx->band_file_offset[kk];
 
167
        /* Get to where we are located in the file, read and decode */
 
168
        fseek(fi, curr_file_offset, SEEK_SET); 
 
169
        fread(ibufs[psd_ctx->permute[kk]], 1, curr_length, fi);
 
170
        /* Update where we are in each band */
 
171
        psd_ctx->band_file_offset[kk] += curr_length;
 
172
    }
 
173
}
 
174
 
 
175
/* Photoshop 8 bit unencoded output.  Due to its planar form, this is stored in a 
 
176
   temp buffer until we reach the final line, at which point we write out the
 
177
   entire thing. */
 
178
static void write_psd_line8(uchar **obufs, int xs, FILE *fo, int planes,
 
179
                           void *image_ctx)
 
180
{
 
181
    int kk;
 
182
    psd_ctx_t *psd_ctx = (psd_ctx_t*) image_ctx;
 
183
    const void *input_buf;
 
184
    uchar *output_buff = (uchar*) psd_ctx->output_buffer;
 
185
    long plane_size = (psd_ctx->width) * (psd_ctx->height);
 
186
    long buffer_size = plane_size * planes;
 
187
    
 
188
    output_buff += ((psd_ctx->curr_row) * (psd_ctx->width));
 
189
    for (kk = 0; kk < planes; kk++)
 
190
    {
 
191
        input_buf = (const void*) obufs[psd_ctx->permute[kk]];
 
192
        memcpy(output_buff, input_buf, psd_ctx->width);
 
193
        output_buff += plane_size;
 
194
    }
 
195
    psd_ctx->curr_row += 1;
 
196
    /* If at end, then dump the buffer */
 
197
    if (psd_ctx->curr_row == psd_ctx->height)
 
198
        fwrite(psd_ctx->output_buffer, 1, buffer_size, fo);
 
199
}
 
200
 
 
201
/* Photoshop unencoded 16 bit case */
 
202
static void read_psd_line16(ETS_SrcPixel **ibufs, int xs, FILE *fi, int planes,
 
203
                          void *image_ctx)
 
204
{
 
205
    int kk;
 
206
    psd_ctx_t *psd_ctx = (psd_ctx_t*) image_ctx;
 
207
    long curr_file_offset;
 
208
    int curr_length = psd_ctx->width * 2;
 
209
    int i;
 
210
    unsigned short temp_value1, temp_value2;
 
211
 
 
212
    /* Loop across each band */
 
213
    for (kk = 0; kk < planes; kk++) 
 
214
    {
 
215
        /* Get a pointer and a length for the current one */
 
216
        curr_file_offset = psd_ctx->band_file_offset[kk];
 
217
        /* Get to where we are located in the file, read and decode */
 
218
        fseek(fi, curr_file_offset, SEEK_SET); 
 
219
        fread(ibufs[psd_ctx->permute[kk]], 1, curr_length, fi);
 
220
#ifdef LITTLE_ENDIAN
 
221
        for (i = 0; i < psd_ctx->width; i++)
 
222
        {
 
223
            temp_value1 = ibufs[psd_ctx->permute[kk]][i];
 
224
            temp_value2 = ((temp_value1 & 0xff) << 8) + ((temp_value1 & 0xff00) >> 8);
 
225
            ibufs[psd_ctx->permute[kk]][i] = temp_value2;
 
226
        }
 
227
#endif
 
228
        /* Update where we are in each band */
 
229
        psd_ctx->band_file_offset[kk] += curr_length;
 
230
    }
 
231
}
 
232
 
 
233
/* Photoshop 16 bit unencoded output.  Due to its planar form, this is stored in a 
 
234
   temp buffer until we reach the final line, at which point we write out the entire 
 
235
   thing. This is not used really, but here for completeness and some testing.
 
236
   Needs fix for little endian */
 
237
static void write_psd_line16(uchar **obufs, int xs, FILE *fo, int planes,
 
238
                           void *image_ctx)
 
239
{
 
240
    int kk;
 
241
    psd_ctx_t *psd_ctx = (psd_ctx_t*) image_ctx;
 
242
    const void *input_buf;
 
243
    uchar *output_buff = (uchar*) psd_ctx->output_buffer;
 
244
    long plane_size = (psd_ctx->width) * (psd_ctx->height) * 2;
 
245
    long buffer_size = plane_size * planes;
 
246
    
 
247
    output_buff += ((psd_ctx->curr_row) * (psd_ctx->width)) * 2;
 
248
    for (kk = 0; kk < planes; kk++)
 
249
    {
 
250
        input_buf = (const void*) obufs[psd_ctx->permute[kk]];
 
251
        memcpy(output_buff, input_buf, psd_ctx->width * 2);
 
252
        output_buff += plane_size;
 
253
    }
 
254
    psd_ctx->curr_row += 1;
 
255
    /* If at end, then dump the buffer */
 
256
    if (psd_ctx->curr_row == psd_ctx->height)
 
257
        fwrite(psd_ctx->output_buffer, 1, buffer_size, fo);
 
258
}
 
259
 
 
260
static void finalize_psd(void *image_ctx)
 
261
{
 
262
    psd_ctx_t *psd_ctx = (psd_ctx_t*) image_ctx;
 
263
 
 
264
    if (psd_ctx->output_buffer != NULL)
 
265
        free(psd_ctx->output_buffer);
 
266
    if (psd_ctx->band_row_length_index != NULL)
 
267
        free(psd_ctx->band_row_length_index);
 
268
    if (psd_ctx->band_file_offset != NULL)
 
269
        free(psd_ctx->band_file_offset);
 
270
    if (psd_ctx->rle_row != NULL)
 
271
        free(psd_ctx->rle_row);
 
272
    if (psd_ctx->permute != NULL)
 
273
        free(psd_ctx->permute);
 
274
}
 
275
 
 
276
static void read_psd(FILE *fi, psd_ctx_t *psd_ctx, FILE *fo)
 
277
{
 
278
    uchar buf[256];
 
279
    int depth;
 
280
    uchar num_channel;
 
281
    int height, width, color_mode;
 
282
    int size;
 
283
    int bytes;
 
284
    uchar *temp_buff;
 
285
    int kk, jj;
 
286
    long data_size;
 
287
    int codec, maxlength = 0;
 
288
    long count = 0;
 
289
    long curr_count = 0;
 
290
    int index = 0;
 
291
#ifdef TEST_PSD_DUMP
 
292
    uchar *in_buff, *out_buff;
 
293
#endif
 
294
    
 
295
    psd_ctx->curr_row = 0;
 
296
 
 
297
    /* rewind and get the header information */
 
298
    rewind(fi);
 
299
 
 
300
    fread(buf, 1, 26, fi);
 
301
    count += 26;
 
302
 
 
303
    num_channel = buf[13];
 
304
    get4(&height, &(buf[14]));
 
305
    get4(&width, &(buf[18]));
 
306
 
 
307
    depth = buf[23];
 
308
    color_mode = buf[25];
 
309
 
 
310
    if (!(depth == 8 || depth == 16))
 
311
        die("Only 8 or 16 bit PSD files supported");
 
312
 
 
313
    if (depth == 16 && (sizeof(ETS_SrcPixel) != 2 || ETS_SRC_MAX != 65535))
 
314
        die("ETS_SrcPixel type and ETS_SRC_MAX in ets.h not set for 16 bit support!");
 
315
 
 
316
    if (depth == 8 && (sizeof(ETS_SrcPixel) != 1 || ETS_SRC_MAX != 255))
 
317
        die("ETS_SrcPixel type and ETS_SRC_MAX in ets.h not set for 8 bit support!");
 
318
 
 
319
    /* Dont handle duotone or indexed data at this time */
 
320
    if (color_mode == 2 || color_mode == 8) 
 
321
        die("Indexed and Duotone PSD files not supported");
 
322
 
 
323
    psd_ctx->depth = depth;
 
324
    psd_ctx->height = height;
 
325
    psd_ctx->width = width;
 
326
    psd_ctx->num_channels = num_channel;
 
327
 
 
328
    if (depth == 8)
 
329
        bytes = 1;
 
330
    else 
 
331
        bytes = 2;
 
332
 
 
333
    /* Change the output to 8 bit */
 
334
    buf[23] = 8;
 
335
 
 
336
    /* Write out the header information */
 
337
    fwrite(buf, 1, 26, fo);
 
338
 
 
339
    /* Index or duotone information */
 
340
    fread(buf, 1, 4, fi);
 
341
    fwrite(buf, 1, 4, fo);
 
342
    count += 4;
 
343
 
 
344
    /* Record information. Pass along... */
 
345
    fread(buf, 1, 4, fi);
 
346
    get4(&size,  buf);
 
347
    fwrite(buf, 1, 4, fo);
 
348
    temp_buff = (uchar*) malloc(size);
 
349
    fread(temp_buff, 1, size, fi);
 
350
    fwrite(temp_buff, 1, size, fo);
 
351
    free(temp_buff);
 
352
    count += (size + 4);
 
353
 
 
354
    /* Layer information.  Pass along... */
 
355
    fread(buf, 1, 4, fi);
 
356
    get4(&size,  buf);
 
357
    fwrite(buf, 1, 4, fo);
 
358
    temp_buff = (uchar*) malloc(size);
 
359
    fread(temp_buff, 1, size, fi);
 
360
    fwrite(temp_buff, 1, size, fo);
 
361
    free(temp_buff);
 
362
    count += (size + 4);
 
363
 
 
364
    /* Image information.  The stuff we want.  Only support raw or RLE types for 
 
365
       input.  Output is uncompressed */
 
366
    fread(buf, 1, 2, fi);
 
367
    codec = buf[1];
 
368
    if (!(codec == 0 || codec == 1)) 
 
369
        die("ZIP data in PSD files not supported");
 
370
 
 
371
    buf[1] = 0;
 
372
    fwrite(buf, 1, 2, fo);
 
373
    count += 2;
 
374
 
 
375
    if (codec == 1 && depth == 16) 
 
376
        die("PSD RLE 16 bit files not supported");
 
377
 
 
378
    /* Allocate the output buffer */
 
379
    psd_ctx->output_buffer = malloc(num_channel * height * width * bytes);
 
380
 
 
381
    if (codec == 1) 
 
382
    {
 
383
        /* RLE. Need to decompress the data.  Each scan line is individually 
 
384
           compressed.  First read in the size for each compressed line */
 
385
        data_size = num_channel * height;
 
386
        psd_ctx->row_lengths = (int*) malloc(data_size * sizeof(int));
 
387
        psd_ctx->band_file_offset = (long*) malloc(num_channel * sizeof(long));
 
388
        psd_ctx->band_row_length_index = (int*) malloc(num_channel * sizeof(int));
 
389
        count += (2 * data_size); /* This gets us to the start of the image data */
 
390
        /* Here we compute where in the file we need to go, to get the start of 
 
391
           the scan line in each band, we compute the max length of all the 
 
392
           encoded bands and get the length of each encoded band */
 
393
        for (jj = 0; jj < num_channel; jj++) 
 
394
        {
 
395
            (psd_ctx->band_file_offset)[jj] = count + curr_count; 
 
396
            for (kk = 0; kk < height; kk++) 
 
397
            {
 
398
                fread(buf, 1, 2, fi);
 
399
                get2(&((psd_ctx->row_lengths)[index]), buf);
 
400
                if (maxlength < (psd_ctx->row_lengths)[index]) 
 
401
                    maxlength = (psd_ctx->row_lengths)[index];
 
402
                curr_count = curr_count + (psd_ctx->row_lengths)[index];
 
403
                index++;
 
404
            }
 
405
        }
 
406
        psd_ctx->rle_row = (void*) malloc(maxlength);
 
407
        psd_ctx->read_line = read_psd_line_rle8;
 
408
        psd_ctx->write_line = write_psd_line8;
 
409
        for (kk = 0; kk < num_channel; kk++)
 
410
        {
 
411
            (psd_ctx->band_row_length_index)[kk] = kk * height;
 
412
        }
 
413
#ifdef TEST_PSD_DUMP
 
414
        /* Now do the decode for testing */
 
415
        in_buff = (uchar*) malloc(maxlength);
 
416
        out_buff = (uchar*) malloc(width);
 
417
        for (kk = 0; kk < data_size; kk++) 
 
418
        {
 
419
            fread(in_buff, 1, (psd_ctx->row_lengths)[kk], fi);
 
420
            rle_decode(in_buff, (psd_ctx->row_lengths)[kk], out_buff, width); 
 
421
            fwrite(out_buff, 1, width, fo);
 
422
        }
 
423
        fclose(fo);
 
424
        free(in_buff);
 
425
        free(out_buff);
 
426
        die("Testing case");
 
427
#endif 
 
428
    } 
 
429
    else 
 
430
    {
 
431
        /* Uncompressed data.  Read directly */
 
432
        psd_ctx->row_lengths  = NULL;
 
433
        psd_ctx->rle_row = NULL;
 
434
        psd_ctx->band_row_length_index = NULL;
 
435
        psd_ctx->band_file_offset = (long*) malloc(num_channel * sizeof(long));
 
436
        for (kk = 0; kk < num_channel; kk++)
 
437
        {
 
438
            (psd_ctx->band_file_offset)[kk] = count + height * width * kk * bytes; 
 
439
        }
 
440
        if (depth == 8) 
 
441
        {
 
442
            psd_ctx->read_line = read_psd_line8;
 
443
            psd_ctx->write_line = write_psd_line8;
 
444
        }
 
445
        else 
 
446
        {
 
447
            psd_ctx->read_line = read_psd_line16;
 
448
            psd_ctx->write_line = write_psd_line8;
 
449
        }
 
450
    }
 
451
    psd_ctx->finalize = finalize_psd;
 
452
    psd_ctx->permute = (uchar*) malloc(num_channel);
 
453
    /* A default initialization */
 
454
    for (kk = 0; kk < num_channel; kk++)
 
455
    {
 
456
        psd_ctx->permute[kk] = kk;
 
457
    }
 
458
}
 
459
 
 
460
static void read_pgm(FILE *fi, int *xs, int *ys, FILE *fo)
 
461
{
 
462
    char buf[256];
 
463
    int depth;
 
464
 
 
465
    do
 
466
        fgets(buf, sizeof(buf), fi);
 
467
    while (buf[0] == '#');
 
468
    sscanf (buf, "%d", xs);
 
469
    do
 
470
        fgets (buf, sizeof(buf), fi);
 
471
    while (buf[0] == '#');
 
472
    sscanf (buf, "%d", ys);
 
473
    if (*xs <= 0 || *ys <= 0 || *xs > MAX_SIZE || *ys > MAX_SIZE)
 
474
        die("Input image size out of range");
 
475
 
 
476
    do
 
477
        fgets(buf, sizeof(buf), fi);
 
478
    while (buf[0] == '#');
 
479
    sscanf(buf, "%d", &depth);
 
480
    if (depth != 255)
 
481
        die("Only works with depth=255 images");
 
482
 
 
483
    fprintf(fo, "P5\n%d %d\n255\n", *xs, *ys);
 
484
}
 
485
 
 
486
static int read_pam(FILE *fi, int *xs, int *ys, FILE *fo)
 
487
{
 
488
    char buf[256];
 
489
    int i, depth;
 
490
    char c;
 
491
 
 
492
    fprintf(fo, "P7\n");
 
493
 
 
494
    do
 
495
    {
 
496
        fgets(buf, sizeof(buf), fi);
 
497
        if (buf[0] == '#')
 
498
        {
 
499
            fprintf(fo, "%s", buf);
 
500
            continue;
 
501
        }
 
502
        if (buf[0] == '\n' || buf[0] == '\r')
 
503
            continue;
 
504
        if (sscanf(buf, "WIDTH %d", xs))
 
505
        {
 
506
            fprintf(fo, "WIDTH %d\n", *xs);
 
507
        }
 
508
        else if (sscanf(buf, "HEIGHT %d", ys))
 
509
        {
 
510
            fprintf(fo, "HEIGHT %d\n", *ys);
 
511
        }
 
512
        else if (sscanf(buf, "DEPTH %d", &depth))
 
513
        {
 
514
            if (depth < 4)
 
515
                die("Only CMYK/DEVN pams supported");
 
516
            fprintf(fo, "DEPTH %d\n", depth);
 
517
        }
 
518
        else if (sscanf(buf, "MAXVAL %d", &i))
 
519
        {
 
520
            if (i != 255)
 
521
                die("Only pams with MAXVAL=255 supported");
 
522
            fprintf(fo, "MAXVAL 255\n");
 
523
        }
 
524
        else if (sscanf(buf, "TUPLTYPE DEV%c", &c) && c == 'N')
 
525
        {
 
526
            fprintf(fo, "TUPLTYPE DEVN\n");
 
527
        }
 
528
        else if (sscanf(buf, "TUPLTYPE CMY%c", &c) && c == 'K')
 
529
        {
 
530
            fprintf(fo, "TUPLTYPE CMYK\n");
 
531
        }
 
532
        else if (sscanf(buf, "TUPLTYP%c") && c == 'E')
 
533
        {
 
534
            die("Only CMYK/DEVN pams supported");
 
535
        }
 
536
        else if (sscanf(buf, "ENDHD%c", &c) && c == 'R')
 
537
        {
 
538
            fprintf(fo, "ENDHDR\n");
 
539
            break;
 
540
        }
 
541
        else
 
542
        {
 
543
            printf(stderr, "Unknown header field: %s\n", buf);
 
544
            die("Unknown header field\n");
 
545
        }
 
546
    }
 
547
    while (1);
 
548
 
 
549
    return depth;
 
550
}
 
551
 
 
552
static void read_pgm_line(ETS_SrcPixel **ibufs, int xs, FILE *fi, int planes, 
 
553
                          void *image_ctx)
 
554
{
 
555
    int nbytes;
 
556
    nbytes = fread(ibufs[0], 1, xs, fi);
 
557
    if (nbytes != xs)
 
558
        die("Error reading image (file truncated?)");
 
559
}
 
560
 
 
561
static void read_pam_line(ETS_SrcPixel **ibufs, int xs, FILE *fi, int planes, 
 
562
                          void *image_ctx)
 
563
{
 
564
    int i, j, c = 0;
 
565
 
 
566
    for (i = 0; i < xs && c != EOF; i++)
 
567
    {
 
568
        ibufs[1][i] = 255-fgetc(fi);
 
569
        ibufs[2][i] = 255-fgetc(fi);
 
570
        ibufs[3][i] = 255-fgetc(fi);
 
571
        ibufs[0][i] = 255-(c = fgetc(fi));
 
572
        for (j=4; j < planes; j++)
 
573
            ibufs[j][i] = 255-(c = fgetc(fi));
 
574
    }
 
575
    if (c == EOF)
 
576
        die("Error reading image (file truncated?)");
 
577
}
 
578
 
 
579
static void write_pgm_line(uchar **obufs, int xs, FILE *fo, int planes,
 
580
                           void *image_ctx)
 
581
{
 
582
    fwrite(obufs[0], 1, xs, fo);
 
583
}
 
584
 
 
585
static void write_pam_line(uchar **obufs, int xs, FILE *fo, int planes,
 
586
                           void *image_ctx)
 
587
{
 
588
    int i, j;
 
589
 
 
590
    for (i = 0; i < xs; i++)
 
591
    {
 
592
        fputc(255-obufs[1][i], fo);
 
593
        fputc(255-obufs[2][i], fo);
 
594
        fputc(255-obufs[3][i], fo);
 
595
        fputc(255-obufs[0][i], fo);
 
596
        for (j = 4; j < planes; j++)
 
597
        {
 
598
            fputc(255-obufs[j][i], fo);
 
599
        }
 
600
    }
 
601
}
 
602
 
 
603
int
 
604
main(int argc, char **argv)
 
605
{
 
606
    FILE *fi = stdin;
 
607
    FILE *fo = stdout;
 
608
    char buf[256];
 
609
    int xs, ys;
 
610
    int xsb;
 
611
    ETS_POLARITY polarity;
 
612
    ETS_Params params;
 
613
    ETS_Ctx *ctx;
 
614
    int lut[ETS_SRC_MAX+1], i;
 
615
    int *luts[M];
 
616
    int rs_lut[ETS_SRC_MAX+1];
 
617
    int *rs_luts[M];
 
618
    int strengths[M][M] = { { 0 },
 
619
                            { 0 },
 
620
                            { 0 },
 
621
                            { 128, 51, 51, 13 },                 // KCMY
 
622
                            { 0 },
 
623
                            { 128, 51, 51, 13, 13, 13 },         // KCMYcm
 
624
                            { 128, 51, 51, 13, 13, 13, 13 },     // KCMYcmk
 
625
                            { 128, 51, 51, 13, 13, 13, 13, 13},  // KCMYcmkk
 
626
                          };
 
627
    /* Used now in PSD case so that we can reorder the planes according to the above weights */
 
628
    uchar permutes[M][M] = { { 0 },
 
629
                        { 0 },
 
630
                        { 0 },
 
631
                        { 3, 0, 1, 2 },             // KCMY
 
632
                        { 0 },
 
633
                        { 3, 0, 1, 2, 4, 5 },       // KCMYcm
 
634
                        { 3, 0, 1, 2, 4, 5, 6 },    // KCMYcmk
 
635
                        {3, 0, 1, 2, 4, 5, 6, 7},  // KCMYcmkk
 
636
                        };
 
637
    int c1_scale[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
 
638
    ETS_SrcPixel *ibufs[M] = { 0 };
 
639
    uchar *obufs[M] = { 0 };
 
640
    int planes;
 
641
    void (*read_line)(ETS_SrcPixel **ibufs, int xs, FILE *fi, int planes, void *image_ctx);
 
642
    void (*write_line)(uchar **obufs, int xs, FILE *fo, int planes, void *image_ctx);
 
643
    void (*finalize)(void *image_ctx);
 
644
    char *gamma_tab = NULL;
 
645
    int multiplane = 1;
 
646
    int ets_style = 1;
 
647
    int r_style = 1;
 
648
    int levels = 2;
 
649
    int aspect_x = 1;
 
650
    int aspect_y = 1;
 
651
    int noise = 0;
 
652
    psd_ctx_t psd_ctx;
 
653
    void *image_ctx = NULL;
 
654
    uchar byte_count = 1;
 
655
 
 
656
    int y;
 
657
 
 
658
    for (i = 1; i < argc; i++)
 
659
    {
 
660
        const char *arg = argv[i];
 
661
        const char *arg_value;
 
662
 
 
663
        if (arg[0] == '-')
 
664
        {
 
665
            if ((arg_value = get_arg(argc, argv, &i, arg + 2)) == NULL)
 
666
                goto usage_exit;
 
667
 
 
668
            switch (arg[1])
 
669
            {
 
670
            case 'i':
 
671
                fi = fopen(arg_value,"rb");
 
672
                if (fi == NULL)
 
673
                    die ("Input not found");
 
674
                break;
 
675
            case 'o':
 
676
                fo = fopen(arg_value,"wb");
 
677
                if (fo == NULL)
 
678
                    die ("Output failed to open");
 
679
                break;
 
680
            case 'g':
 
681
                gamma_tab = arg_value;
 
682
                break;
 
683
            case 'm':
 
684
                multiplane = atoi(arg_value);
 
685
                break;
 
686
            case 'l':
 
687
                levels = atoi(arg_value);
 
688
                break;
 
689
            case 'e':
 
690
                ets_style = atoi(arg_value);
 
691
                break;
 
692
            case 'r':
 
693
                r_style = atoi(arg_value);
 
694
                break;
 
695
            case 'n':
 
696
                noise = atoi(arg_value);
 
697
                break;
 
698
            case 'a':
 
699
                sscanf(arg_value, "%d:%d", &aspect_x, &aspect_y);
 
700
                break;
 
701
            default:
 
702
                goto usage_exit;
 
703
            }
 
704
        }
 
705
    }
 
706
 
 
707
    fgets(buf, sizeof(buf), fi);
 
708
    xs = ys = 0;
 
709
    if (buf[0] == 'P' && buf[1] == '5')
 
710
    {
 
711
        read_pgm(fi, &xs, &ys, fo);
 
712
        read_line = read_pgm_line;
 
713
        write_line = write_pgm_line;
 
714
        planes = 1;
 
715
        finalize =  NULL;
 
716
        polarity = ETS_BLACK_IS_ZERO;
 
717
    }
 
718
    else if (buf[0] == 'P' && buf[1] == '7')
 
719
    {
 
720
        planes = read_pam(fi, &xs, &ys, fo);
 
721
        read_line = read_pam_line;
 
722
        write_line = write_pam_line;
 
723
        finalize =  NULL;
 
724
        polarity = ETS_BLACK_IS_ZERO;
 
725
    }
 
726
    else if (buf[0] == '8' && buf[1] == 'B' && buf[2] == 'P' && buf[3] == 'S')
 
727
    {
 
728
        read_psd(fi, &psd_ctx, fo);
 
729
        read_line = psd_ctx.read_line;
 
730
        write_line = psd_ctx.write_line;
 
731
        finalize = psd_ctx.finalize;
 
732
        planes = psd_ctx.num_channels;
 
733
        xs = psd_ctx.width;
 
734
        ys = psd_ctx.height;
 
735
        image_ctx = (void*) &psd_ctx;
 
736
        if (psd_ctx.depth == 16)
 
737
            byte_count = 2;
 
738
        polarity = ETS_BLACK_IS_ONE;
 
739
        /* Set the read and write permutation order according to permutes array */
 
740
        if (permutes[planes-1] != 0)
 
741
        {
 
742
            int sum = 0;  /* an error check */
 
743
            for (i = 0; i < planes; i++) 
 
744
            {
 
745
                psd_ctx.permute[i] = permutes[planes-1][i];
 
746
                sum += psd_ctx.permute[i];
 
747
            }
 
748
            if (sum != ((float) planes/2.0) * (float) (planes - 1.0))
 
749
                die ("Permutation vector values are not valid");
 
750
        }
 
751
    }
 
752
    else
 
753
        die("Need pgmraw, pamraw or psd image on input");
 
754
 
 
755
    xsb = xs;
 
756
    for (i = 0; i < planes; i++)
 
757
    {
 
758
        ibufs[i] = (ETS_SrcPixel*) malloc(xs * byte_count);
 
759
        obufs[i] = (uchar*) ets_malloc_aligned(xsb + 16, 16);
 
760
    }
 
761
 
 
762
    /* This sets up a simple gamma lookup table. */
 
763
    if (gamma_tab)
 
764
    {
 
765
        FILE *lutf = fopen(gamma_tab, "r");
 
766
        for (i = 0; i < (ETS_SRC_MAX+1); i++)
 
767
            fscanf(lutf, "%d", &lut[i]);
 
768
        fclose(lutf);
 
769
    }
 
770
    else
 
771
    {
 
772
        double scale = ETS_SRC_MAX;
 
773
        for (i = 0; i < (ETS_SRC_MAX+1); i++)
 
774
#if 1
 
775
            lut[i] = (int)((1 << 24) * (pow (i / scale, 1.0)));
 
776
#else
 
777
            lut[i] = (1 << 24) * (0.88 + 0.02 * i / 255.0);
 
778
#endif
 
779
    }
 
780
 
 
781
    for (i = 0; i < (ETS_SRC_MAX+1); i++)
 
782
        rs_lut[i] = 2 << 16;
 
783
 
 
784
#ifdef DUMP_FILE_NAME
 
785
    params.dump_file = fopen(DUMP_FILE_NAME, "wb");
 
786
#else
 
787
    params.dump_file = NULL;
 
788
#endif
 
789
    params.dump_level = ETS_DUMP_ALL;
 
790
 
 
791
    params.width = xs;
 
792
    params.n_planes = planes;
 
793
    params.levels = levels;
 
794
    for (i = 0; i < planes; i++)
 
795
        luts[i] = lut;
 
796
    params.luts = luts;
 
797
    params.strengths = (multiplane ? strengths[planes-1] : strengths[0]);
 
798
    params.aspect_x = aspect_x;
 
799
    params.aspect_y = aspect_y;
 
800
    params.distscale = 0;
 
801
    params.rand_scale = noise;
 
802
    params.c1_scale = c1_scale;
 
803
    params.ets_style = ets_style;
 
804
    params.r_style = r_style;
 
805
    params.polarity = polarity;
 
806
    for (i = 0; i < planes; i++)
 
807
        rs_luts[i] = rs_lut;
 
808
    params.rand_scale_luts = rs_luts;
 
809
    params.rand_scale_luts = NULL;
 
810
    ctx = ets_new(&params);
 
811
    for (y = 0; y < ys; y++)
 
812
    {
 
813
        int x;
 
814
 
 
815
        read_line(ibufs, xs, fi, planes, image_ctx);
 
816
        ets_line(ctx, obufs, (const ETS_SrcPixel *const *)&ibufs);
 
817
        
 
818
        for (i = 0; i < planes; i++)
 
819
        {
 
820
            uchar *obuf = obufs[i];
 
821
            if (polarity == ETS_BLACK_IS_ONE)
 
822
            {
 
823
                for (x = 0; x < xs; x++)
 
824
                {
 
825
                    obuf[x] = obuf[x] * 255 / (params.levels - 1);
 
826
                }
 
827
            } 
 
828
            else 
 
829
            {
 
830
                for (x = 0; x < xs; x++)
 
831
                {
 
832
                    obuf[x] = 255 - obuf[x] * 255 / (params.levels - 1);
 
833
                }
 
834
            }
 
835
        }
 
836
        write_line(obufs, xs, fo, planes, image_ctx);
 
837
    }
 
838
    if (finalize != NULL)
 
839
        finalize(image_ctx);
 
840
 
 
841
    ets_free(ctx);
 
842
    for (i=0; i < planes; i++)
 
843
    {
 
844
        ets_free_aligned(obufs[i]);
 
845
        free(ibufs[i]);
 
846
    } 
 
847
    if (fi != stdin)
 
848
        fclose(fi);
 
849
    if (fo != stdout)
 
850
        fclose(fo);
 
851
 
 
852
    return 0;
 
853
 usage_exit:
 
854
    return usage();
 
855
}