1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/*$Id: gsht1.c 8250 2007-09-25 13:31:24Z giles $ */
15
/* Extended halftone operators for Ghostscript library */
21
#include "gsutil.h" /* for gs_next_ids */
23
#include "gxdevice.h" /* for gzht.h */
29
/* Imports from gscolor.c */
30
void load_transfer_map(gs_state *, gx_transfer_map *, floatp);
32
/* Forward declarations */
33
static int process_spot(gx_ht_order *, gs_state *,
34
gs_spot_halftone *, gs_memory_t *);
35
static int process_threshold(gx_ht_order *, gs_state *,
36
gs_threshold_halftone *, gs_memory_t *);
37
static int process_threshold2(gx_ht_order *, gs_state *,
38
gs_threshold2_halftone *, gs_memory_t *);
39
static int process_client_order(gx_ht_order *, gs_state *,
40
gs_client_order_halftone *, gs_memory_t *);
42
gs_sethalftone_try_wts(gs_halftone *pht, gs_state *pgs,
43
gx_device_halftone *pdht);
46
public_st_halftone_component();
47
public_st_ht_component_element();
52
ENUM_PTRS_WITH(halftone_component_enum_ptrs, gs_halftone_component *hptr) return 0;
57
ENUM_RETURN((hptr->params.spot.transfer == 0 ?
58
hptr->params.spot.transfer_closure.data :
60
case ht_type_threshold:
61
ENUM_RETURN_CONST_STRING_PTR(gs_halftone_component,
62
params.threshold.thresholds);
63
case ht_type_threshold2:
64
return ENUM_CONST_BYTESTRING(&hptr->params.threshold2.thresholds);
65
case ht_type_client_order:
66
ENUM_RETURN(hptr->params.client_order.client_data);
67
default: /* not possible */
72
case ht_type_threshold:
73
ENUM_RETURN((hptr->params.threshold.transfer == 0 ?
74
hptr->params.threshold.transfer_closure.data :
76
case ht_type_threshold2:
77
ENUM_RETURN(hptr->params.threshold2.transfer_closure.data);
78
case ht_type_client_order:
79
ENUM_RETURN(hptr->params.client_order.transfer_closure.data);
84
static RELOC_PTRS_WITH(halftone_component_reloc_ptrs, gs_halftone_component *hptr)
88
if (hptr->params.spot.transfer == 0)
89
RELOC_VAR(hptr->params.spot.transfer_closure.data);
91
case ht_type_threshold:
92
RELOC_CONST_STRING_VAR(hptr->params.threshold.thresholds);
93
if (hptr->params.threshold.transfer == 0)
94
RELOC_VAR(hptr->params.threshold.transfer_closure.data);
96
case ht_type_threshold2:
97
RELOC_CONST_BYTESTRING_VAR(hptr->params.threshold2.thresholds);
98
RELOC_OBJ_VAR(hptr->params.threshold2.transfer_closure.data);
100
case ht_type_client_order:
101
RELOC_VAR(hptr->params.client_order.client_data);
102
RELOC_VAR(hptr->params.client_order.transfer_closure.data);
112
gs_setcolorscreen(gs_state * pgs, gs_colorscreen_halftone * pht)
116
ht.type = ht_type_colorscreen;
117
ht.params.colorscreen = *pht;
118
return gs_sethalftone(pgs, &ht);
121
/* currentcolorscreen */
123
gs_currentcolorscreen(gs_state * pgs, gs_colorscreen_halftone * pht)
127
switch (pgs->halftone->type) {
128
case ht_type_colorscreen:
129
*pht = pgs->halftone->params.colorscreen;
132
code = gs_currentscreen(pgs, &pht->screens.colored.gray);
135
pht->screens.colored.red = pht->screens.colored.gray;
136
pht->screens.colored.green = pht->screens.colored.gray;
137
pht->screens.colored.blue = pht->screens.colored.gray;
142
/* Set the halftone in the graphics state. */
144
gs_sethalftone(gs_state * pgs, gs_halftone * pht)
149
ht.rc.memory = pgs->memory;
150
return gs_sethalftone_allocated(pgs, &ht);
153
gs_sethalftone_allocated(gs_state * pgs, gs_halftone * pht)
155
gx_device_halftone dev_ht;
156
int code = gs_sethalftone_prepare(pgs, pht, &dev_ht);
160
dev_ht.rc.memory = pht->rc.memory;
161
if ((code = gx_ht_install(pgs, pht, &dev_ht)) < 0)
162
gx_device_halftone_release(&dev_ht, pht->rc.memory);
166
/* Prepare the halftone, but don't install it. */
168
gs_sethalftone_prepare(gs_state * pgs, gs_halftone * pht,
169
gx_device_halftone * pdht)
171
gs_memory_t *mem = pht->rc.memory;
172
gx_ht_order_component *pocs = 0;
175
if (gs_currentusewts() && gs_sethalftone_try_wts(pht, pgs, pdht) == 0)
179
case ht_type_colorscreen:
181
gs_screen_halftone *phc =
182
pht->params.colorscreen.screens.indexed;
183
static const int cindex[4] = {3, 0, 1, 2};
184
static const char * color_names[4] = {"Gray", "Red", "Green", "Blue"};
187
pocs = gs_alloc_struct_array(mem, 4,
188
gx_ht_order_component,
189
&st_ht_order_component_element,
192
return_error(gs_error_VMerror);
193
for (i = 0; i < 4; i++) {
194
gs_screen_enum senum;
196
gx_ht_order_component *poc = &pocs[i];
198
code = gx_ht_process_screen_memory(&senum, pgs,
199
&phc[ci], gs_currentaccuratescreens(), mem);
202
poc->corder = senum.order;
203
poc->comp_number = gs_color_name_component_number(pgs->device,
204
color_names[i], strlen(color_names[i]), pht->type);
205
poc->cname = 0; /* name index values are not known (or needed) */
206
if (i == 0) /* Gray = Default */
207
pdht->order = poc->corder; /* Save default value */
211
pdht->components = pocs;
216
code = process_spot(&pdht->order, pgs, &pht->params.spot, mem);
219
pdht->components = 0;
221
case ht_type_threshold:
222
code = process_threshold(&pdht->order, pgs,
223
&pht->params.threshold, mem);
226
pdht->components = 0;
228
case ht_type_threshold2:
229
code = process_threshold2(&pdht->order, pgs,
230
&pht->params.threshold2, mem);
233
pdht->components = 0;
235
case ht_type_client_order:
236
code = process_client_order(&pdht->order, pgs,
237
&pht->params.client_order, mem);
240
pdht->components = 0;
242
case ht_type_multiple:
243
case ht_type_multiple_colorscreen:
245
uint count = pht->params.multiple.num_comp;
246
bool have_Default = false;
248
gs_halftone_component *phc = pht->params.multiple.components;
249
gx_ht_order_component *poc_next;
251
pocs = gs_alloc_struct_array(mem, count,
252
gx_ht_order_component,
253
&st_ht_order_component_element,
256
return_error(gs_error_VMerror);
258
for (i = 0; i < count; i++, phc++) {
259
gx_ht_order_component *poc = poc_next;
261
if (phc->comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
263
/* Duplicate Default */
264
code = gs_note_error(gs_error_rangecheck);
269
} else if (i == count - 1 && !have_Default) {
271
code = gs_note_error(gs_error_rangecheck);
276
poc->comp_number = phc->comp_number;
277
poc->cname = phc->cname;
280
code = process_spot(&poc->corder, pgs,
281
&phc->params.spot, mem);
283
case ht_type_threshold:
284
code = process_threshold(&poc->corder, pgs,
285
&phc->params.threshold, mem);
287
case ht_type_threshold2:
288
code = process_threshold2(&poc->corder, pgs,
289
&phc->params.threshold2, mem);
291
case ht_type_client_order:
292
code = process_client_order(&poc->corder, pgs,
293
&phc->params.client_order, mem);
296
code = gs_note_error(gs_error_rangecheck);
304
pdht->order = pocs[0].corder; /* Default */
306
/* We have only a Default; */
307
/* we don't need components. */
308
gs_free_object(mem, pocs, "gs_sethalftone");
309
pdht->components = 0;
312
pdht->components = pocs;
313
pdht->num_comp = count;
318
return_error(gs_error_rangecheck);
321
gs_free_object(mem, pocs, "gs_sethalftone");
325
/* ------ Internal routines ------ */
327
/* Process a transfer function override, if any. */
329
process_transfer(gx_ht_order * porder, gs_state * pgs,
330
gs_mapping_proc proc, gs_mapping_closure_t * pmc,
333
gx_transfer_map *pmap;
335
if (proc == 0 && pmc->proc == 0)
338
* The transfer funtion is referenced by the order, so start the
339
* reference count at 1.
341
rc_alloc_struct_1(pmap, gx_transfer_map, &st_transfer_map, mem,
342
return_error(gs_error_VMerror),
344
pmap->proc = proc; /* 0 => use closure */
345
pmap->closure = *pmc;
346
pmap->id = gs_next_ids(mem, 1);
347
load_transfer_map(pgs, pmap, 0.0);
348
porder->transfer = pmap;
352
/* Process a spot plane. */
354
process_spot(gx_ht_order * porder, gs_state * pgs,
355
gs_spot_halftone * phsp, gs_memory_t * mem)
357
gs_screen_enum senum;
359
int code = gx_ht_process_screen_memory(&senum, pgs, &phsp->screen,
360
phsp->accurate_screens, mem);
364
*porder = senum.order;
365
return process_transfer(porder, pgs, phsp->transfer,
366
&phsp->transfer_closure, mem);
369
/* Construct the halftone order from a threshold array. */
371
gx_ht_complete_threshold_order(gx_ht_order * porder)
373
int num_levels = porder->num_levels;
374
uint *levels = porder->levels;
375
uint size = porder->num_bits;
376
gx_ht_bit *bits = porder->bit_data;
379
/* The caller has set bits[i] = max(1, thresholds[i]). */
380
gx_sort_ht_order(bits, size);
381
/* We want to set levels[j] to the lowest value of i */
382
/* such that bits[i].mask > j. */
383
for (i = 0, j = 0; i < size; i++) {
384
if (bits[i].mask != j) {
385
if_debug3('h', "[h]levels[%u..%u] = %u\n",
386
j, (uint) bits[i].mask, i);
387
while (j < bits[i].mask)
391
while (j < num_levels)
393
gx_ht_construct_bits(porder);
396
gx_ht_construct_threshold_order(gx_ht_order * porder, const byte * thresholds)
398
return porder->procs->construct_order(porder, thresholds);
401
/* Process a threshold plane. */
403
process_threshold(gx_ht_order * porder, gs_state * pgs,
404
gs_threshold_halftone * phtp, gs_memory_t * mem)
408
porder->params.M = phtp->width, porder->params.N = 0;
409
porder->params.R = 1;
410
porder->params.M1 = phtp->height, porder->params.N1 = 0;
411
porder->params.R1 = 1;
412
code = gx_ht_alloc_threshold_order(porder, phtp->width, phtp->height,
416
gx_ht_construct_threshold_order(porder, phtp->thresholds.data);
417
return process_transfer(porder, pgs, phtp->transfer,
418
&phtp->transfer_closure, mem);
421
/* Process an extended threshold plane. */
423
process_threshold2(gx_ht_order * porder, gs_state * pgs,
424
gs_threshold2_halftone * phtp, gs_memory_t * mem)
428
* There are potentially 64K different levels for this plane, but this
429
* is more than we're willing to handle. Try to reduce the number of
430
* levels by dropping leading or trailing zero bits from the thresholds;
431
* as a last resort, drop (possibly significant) trailing bits.
433
#define LOG2_MAX_HT_LEVELS 14
434
#define MAX_HT_LEVELS (1 << LOG2_MAX_HT_LEVELS)
435
int bps = phtp->bytes_per_sample;
436
const byte *data = phtp->thresholds.data;
437
const int w1 = phtp->width, h1 = phtp->height, size1 = w1 * h1;
438
const int w2 = phtp->width2, h2 = phtp->height2, size2 = w2 * h2;
439
const uint size = size1 + size2;
440
const int d = (h2 == 0 ? h1 : igcd(h1, h2));
441
const int sod = size / d;
448
uint mask = 0, max_thr = 0;
450
for (i = 0; i < size; ++i) {
452
(bps == 1 ? data[i] : (data[i * 2] << 8) + data[i * 2 + 1]);
455
max_thr = max(max_thr, thr);
458
mask = 1, max_thr = 1;
459
while (!(mask & 1) || max_thr > MAX_HT_LEVELS)
460
mask >>= 1, max_thr >>= 1, rshift++;
461
num_levels = max_thr + 1;
464
* Set nominal values for the params, and don't bother to call
465
* gx_compute_cell_values -- the values are only needed for spot
468
porder->params.M = sod, porder->params.N = d;
469
porder->params.R = 1;
470
porder->params.M1 = d, porder->params.N1 = sod;
471
porder->params.R1 = 1;
473
* Determine the shift between strips. We don't know a closed formula
474
* for this, so we do it by enumeration.
489
code = gx_ht_alloc_ht_order(porder, sod, d, num_levels, size, shift,
490
&ht_order_procs_default, mem);
494
gx_ht_bit *bits = (gx_ht_bit *)porder->bit_data;
497
if_debug7('h', "[h]rect1=(%d,%d), rect2=(%d,%d), strip=(%d,%d), shift=%d\n",
498
w1, h1, w2, h2, sod, d, shift);
499
for (row = 0, di = 0; row < d; ++row) {
500
/* Iterate over destination rows. */
501
int dx, sy = row; /* sy = row mod d */
504
for (dx = 0; dx < sod; dx += w) {
505
/* Iterate within a destination row, over source rows. */
509
/* Copy a row from rect1. */
514
/* Copy a row from rect2. */
515
si = size1 + (sy - h1) * w2;
519
for (j = 0; j < w; ++j, ++si, ++di) {
521
(bps == 1 ? data[si] :
522
(data[si * 2] << 8) + data[si * 2 + 1])
525
if_debug3('H', "[H]sy=%d, si=%d, di=%d\n", sy, si, di);
526
bits[di].mask = max(thr, 1);
531
gx_ht_complete_threshold_order(porder);
532
return process_transfer(porder, pgs, NULL, &phtp->transfer_closure, mem);
533
#undef LOG2_MAX_HT_LEVELS
537
/* Process a client-order plane. */
539
process_client_order(gx_ht_order * porder, gs_state * pgs,
540
gs_client_order_halftone * phcop, gs_memory_t * mem)
542
int code = (*phcop->procs->create_order) (porder, pgs, phcop, mem);
546
return process_transfer(porder, pgs, NULL,
547
&phcop->transfer_closure, mem);
550
static const gx_ht_order_procs_t wts_order_procs = { 0
554
* gs_sethalftone_try_wts: Try creating a wts-based device halftone.
555
* @pht: Client halftone.
556
* @pdht: Device halftone to initialize.
558
* Tries initializing @pdht based on data from @pht, using WTS.
560
* Return value: 0 on success, 1 to indicate that the initialization
561
* was not done, and that the legacy initialization code path should
565
gs_sethalftone_try_wts(gs_halftone *pht, gs_state *pgs,
566
gx_device_halftone *pdht)
568
gx_device *dev = pgs->device;
569
int num_comps = dev->color_info.num_components;
570
int depth = dev->color_info.depth;
572
if (pht->type != ht_type_multiple)
573
/* Only work with Type 5 halftones. todo: we probably want
577
if_debug2('h', "[h]%s, num_comp = %d\n",
578
dev->color_info.separable_and_linear == GX_CINFO_SEP_LIN ? "Separable and linear" : "Not separable and linear!",
579
pht->params.multiple.num_comp);
581
if (dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN &&
582
pht->params.multiple.num_comp > 1)
583
/* WTS is only enabled for separable or monochrome devices. */
586
/* only work with bilevel (not multilevel) devices */
587
if (depth > num_comps) {
588
if (depth >= 2 * num_comps)
590
if (dev->color_info.gray_index != GX_CINFO_COMP_NO_INDEX &&
591
(dev->color_info.max_gray > 1 ||
592
(num_comps > 1 && dev->color_info.max_color > 1)))
596
if (pht->type == ht_type_multiple) {
597
gs_halftone_component *components = pht->params.multiple.components;
598
uint num_comp = pht->params.multiple.num_comp;
600
gx_ht_order_component *pocs;
601
gx_ht_order_component *poc_next;
603
bool have_Default = false;
605
for (i = 0; i < num_comp; i++) {
606
if (components[i].type != ht_type_spot)
609
gs_spot_halftone *spot = &components[i].params.spot;
610
if (!spot->accurate_screens)
615
pocs = gs_alloc_struct_array( pgs->memory,
617
gx_ht_order_component,
618
&st_ht_order_component_element,
619
"gs_sethalftone_try_wts" );
620
/* pocs = malloc(num_comp * sizeof(gx_ht_order_component)); */
622
for (i = 0; i < num_comp; i++) {
623
gs_halftone_component *component = &components[i];
624
gs_spot_halftone *spot = &component->params.spot;
625
gs_screen_halftone *h = &spot->screen;
626
gx_wts_cell_params_t *wcp;
627
gs_wts_screen_enum_t *wse;
629
gx_ht_order_component *poc;
631
if (component->comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
633
/* Duplicate Default */
634
code = gs_note_error(gs_error_rangecheck);
639
} else if (i == num_comp - 1 && !have_Default) {
641
code = gs_note_error(gs_error_rangecheck);
646
gs_deviceinitialmatrix(gs_currentdevice(pgs), &imat);
648
wcp = wts_pick_cell_size(h, &imat);
649
wse = gs_wts_screen_enum_new(wcp);
651
poc->corder.wse = wse;
652
poc->corder.wts = NULL;
653
poc->corder.procs = &wts_order_procs;
654
poc->corder.data_memory = NULL;
655
poc->corder.num_levels = 0;
656
poc->corder.num_bits = 0;
657
poc->corder.levels = NULL;
658
poc->corder.bit_data = NULL;
659
poc->corder.cache = NULL;
660
poc->corder.transfer = NULL;
661
poc->comp_number = component->comp_number;
662
poc->cname = component->cname;
663
code = process_transfer( &poc->corder,
666
&spot->transfer_closure,
671
/* todo: cleanup on error */
672
pdht->components = pocs;
673
pdht->num_comp = num_comp;