📄 eprnrend.c
字号:
Function: eprn_map_color_rgb This function is a 'map_color_rgb' method. Such a method should return an RGB triple for the specified 'color'. This is apparently intended for devices supporting colour maps. The function param_HWColorMap() in gsdparam.c tries to compile such a colour map by calling this method repeatedly for all values from 0 to 2^color_info.depth - 1, provided the depth is less than or equal to 8 and the process colour model is not DeviceCMYK. If the function for one of these values returns a negative code, the assumption seems to be that there is no such colour map. Because there is a default method which always returns zero, such a colour map is always constructed if a device does not implement its own 'map_color_rgb' method. This can be seen in the appearance of the "HWColorMap" page device parameter. The key purpose of this function is therefore to return a negative code.******************************************************************************/int eprn_map_color_rgb(gx_device *device, gx_color_index color, gx_color_value rgb[]){#ifdef EPRN_TRACE if_debug1(EPRN_TRACE_CHAR, "! eprn_map_color_rgb() called for 0x%lX.\n", (unsigned long)color);#endif /* Just to be safe we return defined values (white) */ if (((eprn_Device *)device)->eprn.colour_model == eprn_DeviceRGB) rgb[0] = rgb[1] = rgb[2] = gx_max_color_value; else rgb[0] = rgb[1] = rgb[2] = 0; return -1;}/****************************************************************************** Function: eprn_map_cmyk_color Colour mapping function for a process colour model of 'DeviceCMYK' with 2 intensity levels for all colorants.******************************************************************************/gx_color_index eprn_map_cmyk_color(gx_device *device, const gx_color_value cv[]){ gx_color_value cyan = cv[0], magenta = cv[1], yellow = cv[2], black = cv[3]; gx_color_index value = 0; static const gx_color_value threshold = gx_max_color_value/2;#ifdef EPRN_TRACE if_debug4(EPRN_TRACE_CHAR, "! eprn_map_cmyk_color() called for CMYK = (%hu, %hu, %hu, %hu),\n", cyan, magenta, yellow, black);#endif if (cyan > threshold) value |= CYAN_BIT; if (magenta > threshold) value |= MAGENTA_BIT; if (yellow > threshold) value |= YELLOW_BIT; if (black > threshold) value |= BLACK_BIT;#ifdef EPRN_TRACE if_debug1(EPRN_TRACE_CHAR, " returning 0x%lX.\n", (unsigned long)value);#endif return value;}/****************************************************************************** Function: eprn_map_cmyk_color_flex This is a 'map_cmyk_color' method supporting arbitrary numbers of intensity levels. It may be called for every colour model except DeviceRGB. Colorants not present in the model will be ignored.******************************************************************************/gx_color_index eprn_map_cmyk_color_flex(gx_device *device, const gx_color_value cv[]){ gx_color_value cyan = cv[0], magenta = cv[1], yellow = cv[2], black = cv[3]; gx_color_index value = 0; gx_color_value step; unsigned int level; const eprn_Eprn *eprn = &((eprn_Device *)device)->eprn;#ifdef EPRN_TRACE if_debug4(EPRN_TRACE_CHAR, "! eprn_map_cmyk_color_flex() called for CMYK = (%hu, %hu, %hu, %hu),\n", cyan, magenta, yellow, black);#endif /* I can think of three linear methods to extract discrete values from a continuous intensity in the range [0, 1]: (a) multiply by the number of levels minus 1 and truncate, (b) multiply by the number of levels minus 1 and round, and (c) multiply by the number of levels and truncate, except for an intensity of 1 in which case one returns the number of levels minus 1. For intensity values which can be represented exactly, i.e., intensity = i/(levels-1) for some non-negative i < levels, these three methods are identical. (a) is however inappropriate here because for less than 32 levels ghostscript already provides intensity values which have been adjusted to a representable level. A rounding error could now result in a level which is too small by one. I prefer (c) because it gives equal shares to all levels. I'm using integer arithmetic here although floating point numbers would be more accurate. This routine may, however, be called quite frequently, and the loss in accuray is acceptable as long as the values determined for 'step' are large compared to the number of levels. If you consider "large" as meaning "10 times as large", the critical boundary is at about 81 levels. The highest number of intensity levels at present supported by HP DeskJets is apparently 4. A more accurate implementation would determine 'step' as a floating point value, divide the intensity by it, and take the floor (entier) of the result as the component intensity. */ /* The order has to be (YMC)(K) from left to right */ if (eprn->colour_model != eprn_DeviceGray) { step = gx_max_color_value/eprn->non_black_levels; level = yellow/step; if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1; value = level << eprn->bits_per_colorant; level = magenta/step; if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1; value = (value | level) << eprn->bits_per_colorant; level = cyan/step; if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1; value = (value | level) << eprn->bits_per_colorant; } if (eprn->colour_model != eprn_DeviceCMY) { step = gx_max_color_value/eprn->black_levels; level = black/step; if (level >= eprn->black_levels) level = eprn->black_levels - 1; value |= level; }#ifdef EPRN_TRACE if_debug1(EPRN_TRACE_CHAR, " returning 0x%lX.\n", (unsigned long)value);#endif return value;}/****************************************************************************** Function: eprn_map_cmyk_color_max This is a 'map_cmyk_color' method retaining as much colour information as possible. The reduction to the printer's capabilities must happen in the output routine.******************************************************************************/gx_color_index eprn_map_cmyk_color_max(gx_device *device, const gx_color_value cv[]){ gx_color_value cyan = cv[0], magenta = cv[1], yellow = cv[2], black = cv[3]; gx_color_index value;#ifdef EPRN_TRACE if_debug4(EPRN_TRACE_CHAR, "! eprn_map_cmyk_color_max() called for CMYK = (%hu, %hu, %hu, %hu),\n", cyan, magenta, yellow, black);#endif value = dominant_8bits(black); value |= dominant_8bits(cyan) << 8; value |= dominant_8bits(magenta) << 16; value |= dominant_8bits(yellow) << 24;#ifdef EPRN_TRACE if_debug1(EPRN_TRACE_CHAR, " returning 0x%08lX.\n", (unsigned long)value);#endif return value;}/****************************************************************************** Function: eprn_map_cmyk_color_glob Global eprn_map_cmyk_color for all cases handled above used to be able to work together with ghostscript 8.15 and CMYK model.******************************************************************************/gx_color_index eprn_map_cmyk_color_glob(gx_device *device, const gx_color_value cv[]){ const eprn_Eprn *eprn = &((eprn_Device *)device)->eprn; if (eprn->intensity_rendering == eprn_IR_FloydSteinberg) return eprn_map_cmyk_color_max(device, cv); else if (device->color_info.max_gray > 1 || device->color_info.max_color > 1) return eprn_map_cmyk_color_flex(device, cv); else return eprn_map_cmyk_color(device, cv);}/****************************************************************************** Function: eprn_finalize This function fills the last octet in a set of bit planes with white if needed and sets the lengths of all these planes. 'is_RGB' denotes whether the colour model is eprn_DeviceRGB, 'non_black_levels' is the number of intensity levels for non-black colorants, 'planes' the number of bit planes, 'plane' points to an array of at least 'planes' bit planes, 'ptr' points to an array of at least 'planes' pointers into the bit planes, 'pixels' is the number of pixels written to the group of bit planes. If 'pixels' is divisible by 8, the 'ptr' pointers point to octets after the last completely written octets. Otherwise, they point to the last incompletely written octet in which the pixels written so far occupy the least significant bits.******************************************************************************/void eprn_finalize(bool is_RGB, unsigned int non_black_levels, int planes, eprn_OctetString *plane, eprn_Octet **ptr, int pixels){ int j; /* Execute remaining left shifts in the last octet of the output planes when the number of pixels is not a multiple of 8, and fill with white on the right */ if (pixels % 8 != 0) { int shift = 8 - pixels % 8; if (is_RGB) { /* White may be any intensity, but it's the same for all three colorants, and it's the highest. */ eprn_Octet imax = non_black_levels - 1; int c, rgb_planes = eprn_bits_for_levels(non_black_levels); j = 0; /* next output plane */ /* Loop over RGB */ for (c = 0; c < 3; c++) { eprn_Octet value = imax; int m; /* Loop over all planes for this colorant */ for (m = 0; m < rgb_planes; m++, j++) { eprn_Octet bit = value & 1; int p; value = value >> 1; /* Put the bit into all remaining pixels for this plane */ for (p = 0; p < shift; p++) *ptr[j] = (*ptr[j] << 1) | bit; } } } else /* White is zero */ for (j = 0; j < planes; j++) *ptr[j] = *ptr[j] << shift; /* Advance all plane pointers by 1 */ for (j = 0; j < planes; j++) ptr[j]++; } /* Set the lengths of the bit plane strings */ for (j = 0; j < planes; j++) { if (pixels == 0) plane[j].length = 0; else plane[j].length = ptr[j] - plane[j].str; } return;}/****************************************************************************** Function: split_line_le8 This is the first of the "split_line implementations". See the body of eprn_get_planes() for the calling conventions common to them. This particular implementation has the following restrictions: - The pixmap depth must be a divisor of 8.******************************************************************************/static void split_line_le8(eprn_Device *dev, const eprn_Octet *line, int length, eprn_OctetString plane[]){ gx_color_index pixel; int black_planes, /* number of planes to send for black */ non_black_planes, /* number of planes to send for each of CMY/RGB */ j, k, pixels, /* number of pixels transferred to bit planes */ planes; /* number of planes to send */ eprn_Octet comp_mask = 0, /* 'bits_per_component' 1s in the lowest part */ pixel_mask = 0, /* 'depth' 1s in the lowest part */ *ptr[8]; /* pointers into planes (next octet to write to) */ /* Number of planes to send */ black_planes = eprn_bits_for_levels(dev->eprn.black_levels); non_black_planes = eprn_bits_for_levels(dev->eprn.non_black_levels); planes = black_planes + 3*non_black_planes; /* Initialize the bit plane pointers */ for (j = 0; j < planes; j++) ptr[j] = plane[j].str; /* Determine some bit masks */ for (j = 0; j < dev->color_info.depth; j++) pixel_mask = (pixel_mask << 1) | 1; for (j = 0; j < dev->eprn.bits_per_colorant; j++) comp_mask = (comp_mask << 1) | 1; /* Copy from 'line' to 'plane[]', converting Z format to XY format */ pixels = 0; k = 0; /* Next octet index in the input line */ while (k < length) { int l, m, p; /* Initialize plane storage if it's a new output octet */ if (pixels % 8 == 0) for (j = 0; j < planes; j++) *ptr[j] = 0; /* Loop over pixels within the input octet, starting at the leftmost pixel (highest-order bits) */ p = 8/dev->color_info.depth - 1; do { eprn_Octet comp; /* Extract pixel */ pixel = (line[k] >> p*dev->color_info.depth) & pixel_mask; /* Extract components from the pixel and distribute each over its planes */ comp = pixel & comp_mask; /* black */ for (j = 0; j < black_planes; j++) { *ptr[j] = (*ptr[j] << 1) | comp & 1; comp >>= 1; } if (non_black_planes > 0) for (l = 1; l < 4; l++) { comp = (pixel >> l*dev->eprn.bits_per_colorant) & comp_mask; for (m = 0; m < non_black_planes; m++, j++) { *ptr[j] = (*ptr[j] << 1) | comp & 1; comp >>= 1; } } pixels++; p--; } while (p >= 0); k++; /* Increase plane pointers if an output octet boundary has been reached */ if (pixels % 8 == 0) for (j = 0; j < planes; j++) ptr[j]++; } eprn_finalize(dev->eprn.colour_model == eprn_DeviceRGB, dev->eprn.non_black_levels, planes, plane, ptr, pixels); return;}/****************************************************************************** Function: split_line_ge8 This split_line function has the following restrictions: - The pixmap depth must be a multiple of 8. - There may be at most 8 bits per colorant. (Hence the depth is at most 32.) - 'length' must be divisible by depth/8.******************************************************************************/static void split_line_ge8(eprn_Device *dev, const eprn_Octet *line, int length, eprn_OctetString plane[]){ gx_color_index
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -