123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578 |
- /* Copyright (C) 1989, 1995, 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
-
- This file is part of AFPL Ghostscript.
-
- AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
- distributor accepts any responsibility for the consequences of using it, or
- for whether it serves any particular purpose or works at all, unless he or
- she says so in writing. Refer to the Aladdin Free Public License (the
- "License") for full details.
-
- Every copy of AFPL Ghostscript must include a copy of the License, normally
- in a plain ASCII text file named PUBLIC. The License grants you the right
- to copy, modify and redistribute AFPL Ghostscript, but only under certain
- conditions described in the License. Among other things, the License
- requires that the copyright notice and this notice be preserved on all
- copies.
- */
- /*$Id: gxdither.c,v 1.2 2000/09/19 19:00:36 lpd Exp $ */
- #include "gx.h"
- #include "gsstruct.h"
- #include "gsdcolor.h"
- #include "gxdevice.h"
- #include "gxlum.h"
- #include "gxcmap.h"
- #include "gxdither.h"
- #include "gzht.h"
- /*
- * Binary halftoning algorithms.
- *
- * The procedures in this file use halftoning (if necessary)
- * to implement a given device color that has already gone through
- * the transfer function. There are two major cases: gray and color.
- * Gray halftoning always uses a binary screen. Color halftoning
- * uses either a fast algorithm with a binary screen that produces
- * relatively poor approximations, or a very slow algorithm with a
- * general colored screen (or screens) that faithfully implements
- * the Adobe specifications.
- */
- /* Tables for fast computation of fractional color levels. */
- /* We have to put the table before any uses of it because of a bug */
- /* in the VAX C compiler. */
- /* We have to split up the definition of the table itself because of a bug */
- /* in the IBM AIX 3.2 C compiler. */
- private const gx_color_value q0[] = {
- 0
- };
- private const gx_color_value q1[] = {
- 0, frac_color_(1, 1)
- };
- private const gx_color_value q2[] = {
- 0, frac_color_(1, 2), frac_color_(2, 2)
- };
- private const gx_color_value q3[] = {
- 0, frac_color_(1, 3), frac_color_(2, 3), frac_color_(3, 3)
- };
- private const gx_color_value q4[] = {
- 0, frac_color_(1, 4), frac_color_(2, 4), frac_color_(3, 4),
- frac_color_(4, 4)
- };
- private const gx_color_value q5[] = {
- 0, frac_color_(1, 5), frac_color_(2, 5), frac_color_(3, 5),
- frac_color_(4, 5), frac_color_(5, 5)
- };
- private const gx_color_value q6[] = {
- 0, frac_color_(1, 6), frac_color_(2, 6), frac_color_(3, 6),
- frac_color_(4, 6), frac_color_(5, 6), frac_color_(6, 6)
- };
- private const gx_color_value q7[] = {
- 0, frac_color_(1, 7), frac_color_(2, 7), frac_color_(3, 7),
- frac_color_(4, 7), frac_color_(5, 7), frac_color_(6, 7), frac_color_(7, 7)
- };
- /* We export fc_color_quo for the fractional_color macro in gzht.h. */
- const gx_color_value *const fc_color_quo[8] = {
- q0, q1, q2, q3, q4, q5, q6, q7
- };
- /* Render a gray, possibly by halftoning. */
- int
- gx_render_device_gray(frac gray, gx_color_value alpha, gx_device_color * pdevc,
- gx_device * dev, gx_device_halftone * pdht,
- const gs_int_point * ht_phase)
- {
- bool cmyk = dev->color_info.num_components == 4;
- /* Make a special check for black and white. */
- if (alpha == gx_max_color_value) {
- gx_color_value lum;
- switch (gray) {
- case frac_0:
- lum = 0;
- goto bw;
- case frac_1:
- lum = gx_max_color_value;
- bw:color_set_pure(pdevc,
- (cmyk ?
- gx_map_cmyk_color(dev, 0, 0, 0,
- gx_max_color_value - lum) :
- gx_map_rgb_color(dev, lum, lum, lum)));
- return 0;
- default:
- ;
- }
- }
- /* get a few handy values */
- {
- uint max_value = dev->color_info.dither_grays - 1;
- unsigned long hsize = (unsigned)pdht->order.num_levels;
- unsigned long nshades = hsize * max_value + 1;
- unsigned long lx = (nshades * gray) / (frac_1_long + 1);
- uint v = lx / hsize;
- gx_color_value lum = fractional_color(v, max_value);
- gx_color_index color1;
- int level = lx % hsize;
- /* The following should be a conditional expression, */
- /* but the DECStation 3100 Ultrix 4.3 compiler */
- /* generates bad code for it. */
- #define SET_COLOR_LUM(col, lum)\
- if ( cmyk )\
- col = gx_map_cmyk_color(dev, 0, 0, 0,\
- gx_max_color_value - lum);\
- else if ( alpha == gx_max_color_value )\
- col = gx_map_rgb_color(dev, lum, lum, lum);\
- else\
- col = gx_map_rgb_alpha_color(dev, lum, lum, lum, alpha)
- SET_COLOR_LUM(color1, lum);
- if_debug5('c', "[c]gray=0x%x --> (%d+%d/%lu)/%d\n",
- (unsigned)gray, v, level, hsize, max_value + 1);
- if (level == 0) { /* Close enough to a pure color, */
- /* no dithering needed. */
- color_set_pure(pdevc, color1);
- return 0;
- } else {
- gx_color_index color2;
- v++;
- lum = fractional_color(v, max_value);
- SET_COLOR_LUM(color2, lum);
- color_set_binary_halftone(pdevc, pdht,
- color1, color2, level);
- color_set_phase_mod(pdevc, ht_phase->x, ht_phase->y,
- pdht->order.width,
- pdht->order.full_height);
- return 1;
- }
- #undef SET_COLOR_LUM
- }
- }
- /*
- * Color dithering for Ghostscript. The underlying device imaging model
- * supports dithering between two colors to generate intermediate shades.
- *
- * If the device has high quality colors (at least 32 values
- * per axis), we ask it to map the color directly.
- *
- * Otherwise, things are a bit more complicated. If the device
- * supports N shades of each R, G and B independently, there are a total
- * of N*N*N colors. These colors form a 3-D grid in a cubical color
- * space. The following dithering technique works by locating the
- * color we want in this 3-D color grid and finding the eight colors
- * that surround it. In the case of dithering into 8 colors with 1
- * bit for each red, green and blue, these eight colors will always
- * be the same.
- *
- * Now we consider all possible diagonal paths between the eight colors
- * and chose the path that runs closest to our desired color in 3-D
- * color space. There are 28 such paths. Then we find the position
- * on the path that is closest to our color.
- *
- * The search is made faster by always reflecting our color into
- * the bottom octant of the cube and comparing it to 7 paths.
- * After the best path and the best position on that path are found,
- * the results are reflected back into the original color space.
- *
- * NOTE: This code has been tested for B/W and Color imaging with
- * 1, 2, 3 and 8 bits per component.
- *
- * --- original code by Paul Haeberli @ Silicon Graphics - 1990
- * --- extensively revised by L. Peter Deutsch, Aladdin Enterprises
- *
- * lpd 3/14/94: added support for CMYK.
- */
- /*
- * The weights are arbitrary, as long as their ratios are correct
- * and they will fit into the difference between a ulong and a frac
- * with room to spare. By making WEIGHT1 and WEIGHT4 powers of 2,
- * we can turn some multiplies into shifts.
- */
- #define WNUM 128000
- #define WEIGHT1 (ulong)(WNUM/1000) /* 1.0 */
- #define WEIGHT2 (ulong)(WNUM/1414) /* 1/sqrt(2.0) */
- #define WEIGHT3 (ulong)(WNUM/1732) /* 1/sqrt(3.0) */
- #define WEIGHT4 (ulong)(WNUM/2000) /* 1/sqrt(4.0) */
- #define DIAG_R (0x1)
- #define DIAG_G (0x2)
- #define DIAG_B (0x4)
- #define DIAG_W (0x8)
- #define DIAG_RG (0x3)
- #define DIAG_GB (0x6)
- #define DIAG_BR (0x5)
- #define DIAG_RGB (0x7)
- #define DIAG_RGBW (0xf)
- /* What should we do about the W/K component? For the moment, */
- /* we ignore it in the luminance computation. */
- #define lum_white_weight 0
- private const unsigned short lum_w[16] =
- {
- (0 * lum_blue_weight + 0 * lum_green_weight + 0 * lum_red_weight + 0 * lum_white_weight),
- (0 * lum_blue_weight + 0 * lum_green_weight + 1 * lum_red_weight + 0 * lum_white_weight),
- (0 * lum_blue_weight + 1 * lum_green_weight + 0 * lum_red_weight + 0 * lum_white_weight),
- (0 * lum_blue_weight + 1 * lum_green_weight + 1 * lum_red_weight + 0 * lum_white_weight),
- (1 * lum_blue_weight + 0 * lum_green_weight + 0 * lum_red_weight + 0 * lum_white_weight),
- (1 * lum_blue_weight + 0 * lum_green_weight + 1 * lum_red_weight + 0 * lum_white_weight),
- (1 * lum_blue_weight + 1 * lum_green_weight + 0 * lum_red_weight + 0 * lum_white_weight),
- (1 * lum_blue_weight + 1 * lum_green_weight + 1 * lum_red_weight + 0 * lum_white_weight),
- (0 * lum_blue_weight + 0 * lum_green_weight + 0 * lum_red_weight + 1 * lum_white_weight),
- (0 * lum_blue_weight + 0 * lum_green_weight + 1 * lum_red_weight + 1 * lum_white_weight),
- (0 * lum_blue_weight + 1 * lum_green_weight + 0 * lum_red_weight + 1 * lum_white_weight),
- (0 * lum_blue_weight + 1 * lum_green_weight + 1 * lum_red_weight + 1 * lum_white_weight),
- (1 * lum_blue_weight + 0 * lum_green_weight + 0 * lum_red_weight + 1 * lum_white_weight),
- (1 * lum_blue_weight + 0 * lum_green_weight + 1 * lum_red_weight + 1 * lum_white_weight),
- (1 * lum_blue_weight + 1 * lum_green_weight + 0 * lum_red_weight + 1 * lum_white_weight),
- (1 * lum_blue_weight + 1 * lum_green_weight + 1 * lum_red_weight + 1 * lum_white_weight)
- };
- /*
- * Render RGB or CMYK, possibly by halftoning. If we are rendering RGB,
- * white is ignored. If we are rendering CMYK, red/green/blue/white are
- * actually cyan/magenta/yellow/black.
- */
- int
- gx_render_device_color(frac red, frac green, frac blue, frac white, bool cmyk,
- gx_color_value alpha, gx_device_color * pdevc, gx_device * dev,
- gx_device_halftone * pdht, const gs_int_point * ht_phase)
- {
- uint max_value = dev->color_info.dither_colors - 1;
- uint num_levels = pdht->order.num_levels;
- frac rem_r, rem_g, rem_b, rem_w;
- uint r, g, b, w;
- gx_color_value vr, vg, vb, vw;
- #define MAP_COLOR_RGB()\
- (alpha == gx_max_color_value ?\
- gx_map_rgb_color(dev, vr, vg, vb) :\
- gx_map_rgb_alpha_color(dev, vr, vg, vb, alpha))
- #define MAP_COLOR_CMYK()\
- gx_map_cmyk_color(dev, vr, vg, vb, vw)
- #define MAP_COLOR()\
- (cmyk ? MAP_COLOR_CMYK() : MAP_COLOR_RGB())
- /* Compute the quotient and remainder of each color component */
- /* with the actual number of available colors. */
- switch (max_value) {
- case 1: /* 8 or 16 colors */
- if (red == frac_1)
- rem_r = 0, r = 1;
- else
- rem_r = red, r = 0;
- if (green == frac_1)
- rem_g = 0, g = 1;
- else
- rem_g = green, g = 0;
- if (blue == frac_1)
- rem_b = 0, b = 1;
- else
- rem_b = blue, b = 0;
- if (white == frac_1)
- rem_w = 0, w = 1;
- else
- rem_w = white, w = 0;
- break;
- default:
- {
- ulong want_r, want_g, want_b, want_w;
- want_r = (ulong) max_value * red;
- r = frac_1_quo(want_r);
- rem_r = frac_1_rem(want_r, r);
- want_g = (ulong) max_value * green;
- g = frac_1_quo(want_g);
- rem_g = frac_1_rem(want_g, g);
- want_b = (ulong) max_value * blue;
- b = frac_1_quo(want_b);
- rem_b = frac_1_rem(want_b, b);
- want_w = (ulong) max_value * white;
- w = frac_1_quo(want_w);
- rem_w = frac_1_rem(want_w, w);
- }
- }
- /* Check for no dithering required */
- if (!(rem_r | rem_g | rem_b | rem_w)) {
- vr = fractional_color(r, max_value);
- vg = fractional_color(g, max_value);
- vb = fractional_color(b, max_value);
- vw = fractional_color(w, max_value);
- color_set_pure(pdevc, MAP_COLOR());
- return 0;
- }
- if_debug12('c', "[c]rgbw=0x%x,0x%x,0x%x,0x%x -->\n %x+0x%x,%x+0x%x,%x+0x%x,%x+0x%x -->\n",
- (unsigned)red, (unsigned)green, (unsigned)blue, (unsigned)white,
- (unsigned)r, (unsigned)rem_r, (unsigned)g, (unsigned)rem_g,
- (unsigned)b, (unsigned)rem_b, (unsigned)w, (unsigned)rem_w);
- /* Dithering is required. Choose between two algorithms. */
- if (dev->color_info.num_components >= 4) {
- /* This is a CMYK device. */
- /* Use the slow, general colored halftone algorithm. */
- #define RGB_REM(rem_v, i)\
- (rem_v * (ulong)(pdht->components ? pdht->components[pdht->color_indices[i]].corder.num_levels : num_levels) / frac_1)
- uint lr = RGB_REM(rem_r, 0), lg = RGB_REM(rem_g, 1),
- lb = RGB_REM(rem_b, 2);
- if (cmyk)
- color_set_cmyk_halftone(pdevc, pdht, r, lr, g, lg, b, lb,
- w, RGB_REM(rem_w, 3));
- else
- color_set_rgb_halftone(pdevc, pdht, r, lr, g, lg, b, lb, alpha);
- #undef RGB_REM
- color_set_phase_mod(pdevc, ht_phase->x, ht_phase->y,
- pdht->lcm_width, pdht->lcm_height);
- if (!(pdevc->colors.colored.plane_mask &
- (pdevc->colors.colored.plane_mask - 1))) {
- /* We can reduce this color to a binary halftone or pure color. */
- return gx_reduce_colored_halftone(pdevc, dev, cmyk);
- }
- return 1;
- }
- /* Fast, approximate binary halftone algorithm. */
- {
- ulong hsize = num_levels;
- int adjust_r, adjust_b, adjust_g, adjust_w;
- gx_color_index color1;
- frac amax, amin;
- ulong fmax, cmax;
- int axisc, facec, cubec, diagc;
- unsigned short lum_invert;
- ulong dot1, dot2, dot3, dot4;
- int level;
- int code;
- /* Flip the remainder color into the 0, 0, 0 octant. */
- lum_invert = 0;
- #define half (frac_1/2)
- if (rem_r > half)
- rem_r = frac_1 - rem_r,
- adjust_r = -1, r++, lum_invert += lum_red_weight * 2;
- else
- adjust_r = 1;
- if (rem_g > half)
- rem_g = frac_1 - rem_g,
- adjust_g = -1, g++, lum_invert += lum_green_weight * 2;
- else
- adjust_g = 1;
- if (rem_b > half)
- rem_b = frac_1 - rem_b,
- adjust_b = -1, b++, lum_invert += lum_blue_weight * 2;
- else
- adjust_b = 1;
- vr = fractional_color(r, max_value);
- vg = fractional_color(g, max_value);
- vb = fractional_color(b, max_value);
- if (cmyk) {
- if (rem_w > half)
- rem_w = frac_1 - rem_w,
- adjust_w = -1, w++, lum_invert += lum_white_weight * 2;
- else
- adjust_w = 1;
- vw = fractional_color(w, max_value);
- color1 = MAP_COLOR_CMYK();
- } else
- color1 = MAP_COLOR_RGB();
- /*
- * Dot the color with each axis to find the best one of 15;
- * find the color at the end of the axis chosen.
- */
- cmax = (ulong) rem_r + rem_g + rem_b;
- dot4 = cmax + rem_w;
- if (rem_g > rem_r) {
- if (rem_b > rem_g)
- amax = rem_b, axisc = DIAG_B;
- else
- amax = rem_g, axisc = DIAG_G;
- if (rem_b > rem_r)
- amin = rem_r, fmax = (ulong) rem_g + rem_b, facec = DIAG_GB;
- else
- amin = rem_b, fmax = (ulong) rem_r + rem_g, facec = DIAG_RG;
- } else {
- if (rem_b > rem_r)
- amax = rem_b, axisc = DIAG_B;
- else
- amax = rem_r, axisc = DIAG_R;
- if (rem_b > rem_g)
- amin = rem_g, fmax = (ulong) rem_b + rem_r, facec = DIAG_BR;
- else
- amin = rem_b, fmax = (ulong) rem_r + rem_g, facec = DIAG_RG;
- }
- if (rem_w > amin) {
- cmax = fmax + rem_w, cubec = facec + DIAG_W;
- if (rem_w > amax)
- fmax = (ulong) amax + rem_w, facec = axisc + DIAG_W,
- amax = rem_w, axisc = DIAG_W;
- else if (rem_w > fmax - amax)
- fmax = (ulong) amax + rem_w, facec = axisc + DIAG_W;
- } else
- cubec = DIAG_RGB;
- dot1 = amax * WEIGHT1;
- dot2 = fmax * WEIGHT2;
- dot3 = cmax * WEIGHT3;
- /*dot4 see above */
- #define use_axis()\
- diagc = axisc, level = (hsize * amax + (frac_1_long / 2)) / frac_1_long
- #define use_face()\
- diagc = facec, level = (hsize * fmax + frac_1_long) / (2 * frac_1_long)
- #define use_cube()\
- diagc = cubec, level = (hsize * cmax + (3 * frac_1_long / 2)) / (3 * frac_1_long)
- #define use_tesseract()\
- diagc = DIAG_RGBW, level = (hsize * dot4 + (2 * frac_1_long)) / (4 * frac_1_long)
- if (dot1 > dot2) {
- if (dot3 > dot1) {
- if (dot4 * WEIGHT4 > dot3)
- use_tesseract();
- else
- use_cube();
- } else {
- if (dot4 * WEIGHT4 > dot1)
- use_tesseract();
- else
- use_axis();
- }
- } else {
- if (dot3 > dot2) {
- if (dot4 * WEIGHT4 > dot3)
- use_tesseract();
- else
- use_cube();
- } else {
- if (dot4 * WEIGHT4 > dot2)
- use_tesseract();
- else
- use_face();
- }
- };
- if_debug12('c', " %x+0x%x,%x+0x%x,%x+0x%x,%x+0x%x; adjust=%d,%d,%d,%d\n",
- (unsigned)r, (unsigned)rem_r, (unsigned)g, (unsigned)rem_g,
- (unsigned)b, (unsigned)rem_b, (unsigned)w, (unsigned)rem_w,
- adjust_r, adjust_g, adjust_b, adjust_w);
- if (level == 0) {
- color_set_pure(pdevc, color1);
- code = 0;
- } else {
- gx_color_index color2;
- /* construct the second color, inverting back to original space if needed */
- if (diagc & DIAG_R)
- r += adjust_r;
- if (diagc & DIAG_G)
- g += adjust_g;
- if (diagc & DIAG_B)
- b += adjust_b;
- /* get the second device color, sorting by luminance */
- vr = fractional_color(r, max_value);
- vg = fractional_color(g, max_value);
- vb = fractional_color(b, max_value);
- if (cmyk) {
- if (diagc & DIAG_W)
- w += adjust_w;
- vw = fractional_color(w, max_value);
- color2 = MAP_COLOR_CMYK();
- } else
- color2 = MAP_COLOR_RGB();
- if (level == num_levels) { /* This can only happen through rounding.... */
- color_set_pure(pdevc, color2);
- code = 0;
- } else {
- if (lum_w[diagc] < lum_invert)
- color_set_binary_halftone(pdevc, pdht, color2, color1, hsize - level);
- else
- color_set_binary_halftone(pdevc, pdht, color1, color2, level);
- color_set_phase_mod(pdevc, ht_phase->x, ht_phase->y,
- pdht->order.width,
- pdht->order.full_height);
- code = 1;
- }
- }
- if_debug7('c', "[c]diagc=%d; colors=0x%lx,0x%lx; level=%d/%d; lum=%d,diag=%d\n",
- diagc, (ulong) pdevc->colors.binary.color[0],
- (ulong) pdevc->colors.binary.color[1],
- level, (unsigned)hsize, lum_invert, lum_w[diagc]);
- return code;
- }
- }
- /* Reduce a colored halftone to a binary halftone or pure color. */
- int
- gx_reduce_colored_halftone(gx_device_color *pdevc, gx_device *dev, bool cmyk)
- {
- int planes = pdevc->colors.colored.plane_mask;
- gx_color_value max_color = dev->color_info.dither_colors - 1;
- uint b[4];
- gx_color_value v[4];
- gx_color_index c0, c1;
- b[0] = pdevc->colors.colored.c_base[0];
- v[0] = fractional_color(b[0], max_color);
- b[1] = pdevc->colors.colored.c_base[1];
- v[1] = fractional_color(b[1], max_color);
- b[2] = pdevc->colors.colored.c_base[2];
- v[2] = fractional_color(b[2], max_color);
- if (cmyk) {
- b[3] = pdevc->colors.colored.c_base[3];
- v[3] = fractional_color(b[3], max_color);
- c0 = dev_proc(dev, map_cmyk_color)(dev, v[0], v[1], v[2], v[3]);
- } else
- c0 = dev_proc(dev, map_rgb_color)(dev, v[0], v[1], v[2]);
- if (planes == 0) {
- /*
- * Use a pure color. This case is unlikely, but it can occur if
- * (and only if) the difference of each component from the nearest
- * device color is less than one halftone level.
- */
- color_set_pure(pdevc, c0);
- return 0;
- } else {
- /* Use a binary color. */
- int i = (planes >> 1) - (planes >> 3); /* log2 for 1,2,4,8 */
- uint bi = b[i] + 1;
- const gx_device_halftone *pdht = pdevc->colors.colored.c_ht;
- int index =
- (pdht->components == 0 ? -1 : pdht->color_indices[i]);
- /*
- * NB: the halftone orders are all set up for an additive color
- * space. To use these work with a cmyk color space, it is
- * necessary to invert both the color level and the color
- * pair. Note that if the original color was provided an
- * additive space, this will reverse (in an approximate sense)
- * the color conversion performed to express the color in cmyk
- * space.
- */
- bool invert = dev->color_info.num_components == 4; /****** HACK ******/
- uint level = pdevc->colors.colored.c_level[i];
- v[i] = fractional_color(bi, max_color);
- c1 = (cmyk ?
- dev_proc(dev, map_cmyk_color)(dev, v[0], v[1], v[2], v[3]) :
- dev_proc(dev, map_rgb_color)(dev, v[0], v[1], v[2]));
- if (invert) {
- level =
- (index < 0 ? &pdht->order : &pdht->components[index].corder)
- ->num_levels - level;
- color_set_binary_halftone_component(pdevc, pdht, index, c1, c0,
- level);
- } else
- color_set_binary_halftone_component(pdevc, pdht, index, c0, c1, level);
-
- return 1;
- }
- }
|