/src/ghostpdl/pcl/pcl/pcdither.c
Line | Count | Source |
1 | | /* Copyright (C) 2001-2025 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* pcdither.c - PCL user-defined dither object implementation */ |
18 | | |
19 | | #include "pcommand.h" |
20 | | #include "pcpalet.h" |
21 | | #include "pcdither.h" |
22 | | |
23 | | /* GC Routines */ |
24 | | gs_private_st_simple(st_udither_t, pcl_udither_t, |
25 | | "pcl user defined dither matrix"); |
26 | | |
27 | | /* |
28 | | * Return a pointer to the thershold array appropriate for one color plane. |
29 | | */ |
30 | | const byte * |
31 | | pcl_udither_get_threshold(const pcl_udither_t * pdither, int indx) |
32 | 0 | { |
33 | 0 | uint nplanes = pdither->ptbl->nplanes; |
34 | |
|
35 | 0 | if (nplanes == 1) |
36 | 0 | return pdither->ptbl->data; |
37 | 0 | else |
38 | 0 | return pdither->ptbl->data + indx * pcl_udither_get_size(pdither); |
39 | 0 | } |
40 | | |
41 | | /* |
42 | | * Free a dither matrix structure. |
43 | | */ |
44 | | static void |
45 | | free_dither_matrix(gs_memory_t * pmem, void *pvdither, client_name_t cname) |
46 | 0 | { |
47 | 0 | pcl_udither_t *pdither = (pcl_udither_t *) pvdither; |
48 | |
|
49 | 0 | if (pdither->ptbl != 0) |
50 | 0 | gs_free_object(pmem, (void *)pdither->ptbl, cname); |
51 | 0 | gs_free_object(pmem, pvdither, cname); |
52 | 0 | } |
53 | | |
54 | | /* |
55 | | * ESC * m <nbytes> W |
56 | | * |
57 | | * Download dither matrix. |
58 | | */ |
59 | | static int |
60 | | download_dither_matrix(pcl_args_t * pargs, pcl_state_t * pcs) |
61 | 16 | { |
62 | 16 | uint len = uint_arg(pargs); |
63 | 16 | pcl_udither_t *pdither = 0; |
64 | | |
65 | 16 | const pcl__udither_t *ptbl = (pcl__udither_t *) arg_data(pargs); |
66 | 16 | uint nplanes, h, w; |
67 | 16 | size_t rlen; |
68 | 16 | int code = 0; |
69 | 16 | byte *bp; |
70 | | |
71 | | #ifdef DEBUG |
72 | | if (gs_debug_c('i')) { |
73 | | pcl_debug_dump_data(pcs->memory, arg_data(pargs), uint_arg(pargs)); |
74 | | } |
75 | | #endif |
76 | | |
77 | 16 | if (pcs->raster_state.graphics_mode) |
78 | 12 | return 0; |
79 | | /* check for legitimate parameter values */ |
80 | 4 | if (len < 7) |
81 | 3 | return 0; |
82 | 1 | nplanes = ptbl->nplanes; |
83 | 1 | h = (ptbl->height[0] << 8) + ptbl->height[1]; |
84 | 1 | w = (ptbl->width[0] << 8) + ptbl->width[1]; |
85 | 1 | rlen = nplanes * h * w + 6; |
86 | 1 | if (((nplanes != 1) && (nplanes != 3)) || |
87 | 0 | (h == 0) || (w == 0) || (len < rlen)) |
88 | 1 | return e_Range; |
89 | | |
90 | 0 | rc_alloc_struct_1(pdither, |
91 | 0 | pcl_udither_t, |
92 | 0 | &st_udither_t, |
93 | 0 | pcs->memory, return e_Memory, "download dither matrix"); |
94 | 0 | pdither->rc.free = free_dither_matrix; |
95 | 0 | pdither->ptbl = 0; |
96 | | |
97 | | /* either take possession of buffer, or allocate a new one */ |
98 | 0 | if (pargs->data_on_heap) |
99 | 0 | arg_data(pargs) = 0; |
100 | 0 | else { |
101 | 0 | pcl__udither_t *ptmp = 0; |
102 | |
|
103 | 0 | ptmp = (pcl__udither_t *) gs_alloc_bytes(pcs->memory, |
104 | 0 | rlen, |
105 | 0 | "donwload dither matrix"); |
106 | 0 | if (ptmp == 0) { |
107 | 0 | free_dither_matrix(pdither->rc.memory, |
108 | 0 | pdither, "download dither matrix"); |
109 | 0 | return e_Memory; |
110 | 0 | } |
111 | 0 | memcpy(ptmp, ptbl, rlen); |
112 | 0 | ptbl = ptmp; |
113 | 0 | } |
114 | 0 | pdither->height = h; |
115 | 0 | pdither->width = w; |
116 | 0 | pdither->ptbl = ptbl; |
117 | | |
118 | | /* do not allow the value 0 in the array - black must be black */ |
119 | 0 | bp = (byte *) ptbl->data; |
120 | 0 | rlen -= 6; |
121 | 0 | while (rlen-- > 0) { |
122 | 0 | byte b = *bp; |
123 | |
|
124 | 0 | *bp++ = (b == 0 ? 1 : b); |
125 | 0 | } |
126 | | |
127 | | /* update the dither matrix; release our reference */ |
128 | 0 | code = pcl_palette_set_udither(pcs, pdither); |
129 | 0 | pcl_udither_release(pdither); |
130 | 0 | return code; |
131 | 0 | } |
132 | | |
133 | | /* |
134 | | * There is no reset or copy procedure for this module, as both functions are |
135 | | * handled at the palette level. |
136 | | */ |
137 | | static int |
138 | | udither_do_registration(pcl_parser_state_t * pcl_parser_state, |
139 | | gs_memory_t * pmem) |
140 | 16.0k | { |
141 | 16.0k | DEFINE_CLASS('*') { |
142 | 16.0k | 'm', 'W', |
143 | 16.0k | PCL_COMMAND("Download Dither Matrix", download_dither_matrix, |
144 | 16.0k | pca_bytes | pca_raster_graphics) |
145 | 16.0k | }, END_CLASS return 0; |
146 | 16.0k | } |
147 | | |
148 | | const pcl_init_t pcl_udither_init = { udither_do_registration, 0, 0 }; |