summaryrefslogtreecommitdiff
path: root/pcl/pcdither.c
blob: aeaf9ff31d00ee3c493fb61413133dc953bd41e1 (plain)
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* Portions Copyright (C) 2001 artofcode LLC.
   Portions Copyright (C) 1996, 2001 Artifex Software Inc.
   Portions Copyright (C) 1988, 2000 Aladdin Enterprises.
   This software is based in part on the work of the Independent JPEG Group.
   All Rights Reserved.

   This software is distributed under license and may not be copied, modified
   or distributed except as expressly authorized under the terms of that
   license.  Refer to licensing information at http://www.artifex.com/ or
   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
   San Rafael, CA  94903, (415)492-9861, for further information. */
/*$Id$ */

/* pcdither.c - PCL user-defined dither object implementation */

#include "pcommand.h"
#include "pcpalet.h"
#include "pcdither.h"

/* GC Routines */
private_st_udither_t();

/*
 * Return a pointer to the thershold array appropriate for one color plane.
 */
  const byte *
pcl_udither_get_threshold(
    const pcl_udither_t *   pdither,
    int                     indx
)
{
    uint                    nplanes = pdither->ptbl->nplanes;

    if (nplanes == 1)
        return pdither->ptbl->data;
    else
        return pdither->ptbl->data + indx * pcl_udither_get_size(pdither);
}

/*
 * Free a dither matrix structure.
 */
  static void
free_dither_matrix(
    gs_memory_t *       pmem,
    void *              pvdither,
    client_name_t       cname
)
{
    pcl_udither_t *     pdither = (pcl_udither_t *)pvdither;

    if (pdither->ptbl != 0)
        gs_free_object(pmem, (void *)pdither->ptbl, cname);
    gs_free_object(pmem, pvdither, cname);
}

/*
 * ESC * m <nbytes> W
 *
 * Download dither matrix.
 */
  static int
download_dither_matrix(
    pcl_args_t *            pargs,
    pcl_state_t *           pcs
)
{
    uint                    len = uint_arg(pargs);
    pcl_udither_t *         pdither = 0;
    const pcl__udither_t *  ptbl = (pcl__udither_t *)arg_data(pargs);
    uint                    nplanes, h, w, rlen;
    int                     code = 0;
    byte *                  bp;

    if ( pcs->raster_state.graphics_mode )
        return 0;
    /* check for legitimate parameter values */
    if (len < 7)
        return 0;
    nplanes = ptbl->nplanes;
    h = (ptbl->height[0] << 8) + ptbl->height[1];
    w = (ptbl->width[0] << 8) + ptbl->width[1];
    rlen = nplanes * h * w + 6;
    if ( ((nplanes != 1) && (nplanes != 3)) ||
         (h == 0)                           ||
         (w == 0)                           ||
         (len < rlen)                         )
        return e_Range;

    rc_alloc_struct_1( pdither,
                       pcl_udither_t,
                       &st_udither_t,
                       pcs->memory,
                       return e_Memory,
                       "download dither matrix"
                       );
    pdither->rc.free = free_dither_matrix;
    pdither->ptbl = 0;

    /* either take possession of buffer, or allocate a new one */
    if (pargs->data_on_heap)
        arg_data(pargs) = 0;
    else {
        pcl__udither_t *    ptmp = 0;

        ptmp = (pcl__udither_t *)gs_alloc_bytes( pcs->memory,
                                                 rlen,
                                                 "donwload dither matrix"
                                                 );
        if (ptmp == 0) {
            free_dither_matrix( pdither->rc.memory,
                                pdither,
                                "download dither matrix"
                                );
            return e_Memory;
        }
        memcpy(ptmp, ptbl, rlen);
        ptbl = ptmp;
    }
    pdither->height = h;
    pdither->width = w;
    pdither->ptbl = ptbl;

    /* do not allow the value 0 in the array - black must be black */
    bp = (byte *)ptbl->data;
    rlen -= 6;
    while (rlen-- > 0) {
        byte    b = *bp;

        *bp++ = (b == 0 ? 1 : b);
    }

    /* update the dither matrix; release our reference */
    code = pcl_palette_set_udither(pcs, pdither);
    pcl_udither_release(pdither);
    return code;
}

/*
 * There is no reset or copy procedure for this module, as both functions are
 * handled at the palette level.
 */
  static int
udither_do_registration(
    pcl_parser_state_t *pcl_parser_state,
    gs_memory_t *    pmem
)
{
    DEFINE_CLASS('*')
    {
        'm', 'W',
        PCL_COMMAND("Download Dither Matrix", download_dither_matrix, pca_bytes | pca_raster_graphics)
    },
    END_CLASS
    return 0;
}

const pcl_init_t    pcl_udither_init = { udither_do_registration, 0, 0 };