/* * Convert a CIEBasedDEFG color into device color. */ static int client_remap_CIEBasedDEFG(client_custom_color_params_t * pparams, const gs_client_color * pc, const gs_color_space * pcs, gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev, gs_color_select_t select) { demo_color_space_data_t * pdata = (demo_color_space_data_t *)(pcs->pclient_color_space_data); frac cmyk[4]; int i; /*** Demonstrate method to convert to XYZ ***/ if (pdata->CIEtoXYZ_pis) { frac xyz[3]; cs_concretize_color(pc, pcs, xyz, pdata->CIEtoXYZ_pis); /* We don't really do anything with these values, but this */ /* is where a real client could convert to a device color */ if_debug7('|', "[c]client_remap CIEDEFG [%g, %g, %g] -> XYZ [%g, %g, %g]\n", pc->paint.values[0], pc->paint.values[1], pc->paint.values[2], pc->paint.values[3], frac2float(xyz[0]), frac2float(xyz[1]), frac2float(xyz[2])); } /* * For demo and debug purposes, make our colors a function of the * intensity of the given color value and the object type. The color * values could represent almost anything. However we are assuming * that they are CMYK values. */ for (i = 0; i < 4; i++) cmyk[i] = convert2frac(pc->paint.values[i], pcs->params.defg->RangeDEFG.ranges[i]); return client_remap_DeviceRGB(pparams, cmyk, pcs, pdc, pis, dev, select); }
/* Fill a rectangle. */ int gz_fill_rectangle(int x, int y, int w, int h, const gx_device_color *pdevc, gs_state *pgs) { gx_device *dev = pgs->device->info; if_debug7('v', "[v]x=%d y=%d w=%d h=%d c1=%ld c2=%ld htl=%d\n", x, y, w, h, (long)pdevc->color1, (long)pdevc->color2, (long)pdevc->halftone_level); return gz_fill_rectangle_open(dev, x, y, w, h, dev->procs->fill_rectangle, dev->procs->tile_rectangle, pdevc, pgs); }
/* This is the second half of gs_screen_init_accurate. */ int gs_screen_enum_init_memory(gs_screen_enum * penum, const gx_ht_order * porder, gs_state * pgs, const gs_screen_halftone * phsp, gs_memory_t * mem) { penum->pgs = pgs; /* ensure clean for GC */ if (&penum->order != porder) /* Pacify Valgrind */ penum->order = *porder; penum->halftone.rc.memory = mem; penum->halftone.type = ht_type_screen; penum->halftone.params.screen = *phsp; penum->x = penum->y = 0; if (porder->wse == NULL) { penum->strip = porder->num_levels / porder->width; penum->shift = porder->shift; /* * We want a transformation matrix that maps the parallelogram * (0,0), (U,V), (U-V',V+U'), (-V',U') to the square (+/-1, +/-1). * If the coefficients are [a b c d e f] and we let * u = U = M/R, v = V = N/R, * r = -V' = -N'/R', s = U' = M'/R', * then we just need to solve the equations: * a*0 + c*0 + e = -1 b*0 + d*0 + f = -1 * a*u + c*v + e = 1 b*u + d*v + f = 1 * a*r + c*s + e = -1 b*r + d*s + f = 1 * This has the following solution: * Q = 2 / (M*M' + N*N') * a = Q * R * M' * b = -Q * R' * N * c = Q * R * N' * d = Q * R' * M * e = -1 * f = -1 */ { const int M = porder->params.M, N = porder->params.N, R = porder->params.R; const int M1 = porder->params.M1, N1 = porder->params.N1, R1 = porder->params.R1; double Q = 2.0 / ((long)M * M1 + (long)N * N1); penum->mat.xx = Q * (R * M1); penum->mat.xy = Q * (-R1 * N); penum->mat.yx = Q * (R * N1); penum->mat.yy = Q * (R1 * M); penum->mat.tx = -1.0; penum->mat.ty = -1.0; gs_matrix_invert(&penum->mat, &penum->mat_inv); } if_debug7('h', "[h]Screen: (%dx%d)/%d [%f %f %f %f]\n", porder->width, porder->height, porder->params.R, penum->mat.xx, penum->mat.xy, penum->mat.yx, penum->mat.yy); } return 0; }
/* Note that this involves black generation and undercolor removal. */ void color_rgb_to_cmyk(frac r, frac g, frac b, const gs_imager_state * pis, frac cmyk[4], gs_memory_t *mem) { frac c = frac_1 - r, m = frac_1 - g, y = frac_1 - b; frac k = (c < m ? min(c, y) : min(m, y)); /* * The default UCR and BG functions are pretty arbitrary, * but they must agree with the ones in gs_init.ps. */ frac bg = (pis == NULL ? k : pis->black_generation == NULL ? frac_0 : gx_map_color_frac(pis, k, black_generation)); signed_frac ucr = (pis == NULL ? k : pis->undercolor_removal == NULL ? frac_0 : gx_map_color_frac(pis, k, undercolor_removal)); if (ucr == frac_1) cmyk[0] = cmyk[1] = cmyk[2] = 0; else if (ucr == frac_0) cmyk[0] = c, cmyk[1] = m, cmyk[2] = y; else { if (!gs_currentcpsimode(mem)) { /* C = max(0.0, min(1.0, 1 - R - UCR)), etc. */ signed_frac not_ucr = (ucr < 0 ? frac_1 + ucr : frac_1); cmyk[0] = (c < ucr ? frac_0 : c > not_ucr ? frac_1 : c - ucr); cmyk[1] = (m < ucr ? frac_0 : m > not_ucr ? frac_1 : m - ucr); cmyk[2] = (y < ucr ? frac_0 : y > not_ucr ? frac_1 : y - ucr); } else { /* Adobe CPSI method */ /* C = max(0.0, min(1.0, 1 - R / (1 - UCR))), etc. */ float denom = frac2float(frac_1 - ucr); /* unscaled */ float v; v = (float)frac_1 - r / denom; /* unscaled */ cmyk[0] = (is_fneg(v) ? frac_0 : v >= (float)frac_1 ? frac_1 : (frac) v); v = (float)frac_1 - g / denom; /* unscaled */ cmyk[1] = (is_fneg(v) ? frac_0 : v >= (float)frac_1 ? frac_1 : (frac) v); v = (float)frac_1 - b / denom; /* unscaled */ cmyk[2] = (is_fneg(v) ? frac_0 : v >= (float)frac_1 ? frac_1 : (frac) v); } } cmyk[3] = bg; if_debug7('c', "[c]RGB 0x%x,0x%x,0x%x -> CMYK 0x%x,0x%x,0x%x,0x%x\n", r, g, b, cmyk[0], cmyk[1], cmyk[2], cmyk[3]); }
/* Convert CMYK to RGB. */ void color_cmyk_to_rgb(frac c, frac m, frac y, frac k, const gs_imager_state * pis, frac rgb[3], gs_memory_t *mem) { switch (k) { case frac_0: rgb[0] = frac_1 - c; rgb[1] = frac_1 - m; rgb[2] = frac_1 - y; break; case frac_1: rgb[0] = rgb[1] = rgb[2] = frac_0; break; default: if (!gs_currentcpsimode(mem)) { /* R = 1.0 - min(1.0, C + K), etc. */ frac not_k = frac_1 - k; rgb[0] = (c > not_k ? frac_0 : not_k - c); rgb[1] = (m > not_k ? frac_0 : not_k - m); rgb[2] = (y > not_k ? frac_0 : not_k - y); } else { /* R = (1.0 - C) * (1.0 - K), etc. */ ulong not_k = frac_1 - k; /* Compute not_k * (frac_1 - v) / frac_1 efficiently. */ ulong prod; #define deduct_black(v)\ (prod = (frac_1 - (v)) * not_k, frac_1_quo(prod)) rgb[0] = deduct_black(c); rgb[1] = deduct_black(m); rgb[2] = deduct_black(y); #undef deduct_black } } if_debug7('c', "[c]CMYK 0x%x,0x%x,0x%x,0x%x -> RGB 0x%x,0x%x,0x%x\n", c, m, y, k, rgb[0], rgb[1], rgb[2]); }