📄 eprnrend.c
字号:
/****************************************************************************** File: $Id: eprnrend.c,v 1.15 2001/08/01 05:12:56 Martin Rel $ Contents: Colour rendering functionality for the ghostscript device 'eprn' Author: Martin Lottermoser, Greifswaldstrasse 28, 38124 Braunschweig, Germany. E-mail: Martin.Lottermoser@t-online.de.******************************************************************************** ** Copyright (C) 2000, 2001 by Martin Lottermoser ** All rights reserved ** ******************************************************************************** Preprocessor variables: EPRN_TRACE Define this to enable tracing. Only useful for development. EPRN_TRAILING_BIT_BUG_FIXED Define this to deactivate compensation for a bug in ghostscript which leads to the last pixel in an RGB line being black instead of white. This occurs at least in gs 6.01 and 6.50. The correction covers only the one-bit-per-colorant case and is equivalent to clipping the pixel.******************************************************************************* The eprn device uses 'gx_color_index' values with varying interpretations, depending on the colour model and the rendering method, and stores them at different pixmaps depths, normally using the smallest depth which can accommodate all colorants at the same number of bits per colorant. To simplify matters, a field for the black component is always included, even for RGB and CMY, i.e., there are either 1 or 4 bit fields in a 'gx_color_index' value. If there are 4, the interpretation is either YMCK or BGRK, looking from left to right (most to least significant). The width of the fields can be found in the 'bits_per_colorant' variable in the eprn part of the device instance. Within each colorant field, not all bits need be used. Except when using the *_max() colour mapping functions, the values returned by eprn_bits_for_levels() for the parameters 'black_levels' and 'non_black_levels' determine the number of bits which are actually meaningful. Only the last (least significant) bits are used.******************************************************************************//* Configuration management identification */#ifndef lintstatic const char cm_id[] = "@(#)$Id: eprnrend.c,v 1.15 2001/08/01 05:12:56 Martin Rel $";#endif/*****************************************************************************/#ifndef _XOPEN_SOURCE#define _XOPEN_SOURCE 500#endif/* Special Aladdin header, must be included before <sys/types.h> on some platforms (e.g., FreeBSD). */#include "std.h"/* Standard headers */#include <assert.h>#include <stdlib.h>/* Ghostscript headers */#ifdef EPRN_TRACE#include "gdebug.h"#endif /* EPRN_TRACE *//* Special headers */#include "gdeveprn.h"/*****************************************************************************//* Macros for 'gx_color_index' values used mainly for non-monochrome modes and a pixmap depth of 4 *//* Colorants bits, numbered from 0 on the right to 3 on the left */#define COLORANT_0_BIT 1U#define COLORANT_1_BIT 2U#define COLORANT_2_BIT 4U#define COLORANT_3_BIT 8U/* Alias names for the bits in particular colour models */#define BLACK_BIT COLORANT_0_BIT#define CYAN_BIT COLORANT_1_BIT#define MAGENTA_BIT COLORANT_2_BIT#define YELLOW_BIT COLORANT_3_BIT#define RED_BIT COLORANT_1_BIT#define GREEN_BIT COLORANT_2_BIT#define BLUE_BIT COLORANT_3_BIT/* Bit plane indices for splitting */#define COLORANT_0_INDEX 0#define COLORANT_1_INDEX 1#define COLORANT_2_INDEX 2#define COLORANT_3_INDEX 3/* Macro to extract the dominant 8 bits from a 'gx_color_value'. This definition assumes that 'gx_color_value' uses the least significant 16 bits of the underlying type (unsigned short). Splitting this part off looks inefficient because left shifts will usually follow, but I'm relying on the compiler to be sufficiently intelligent to eliminate this inefficiency. This way the code is easier to check. The type cast is needed to prevent problems with negative values on platforms where 'gx_color_index' has more bits than 'int'. */#define dominant_8bits(value) ((unsigned int)((value) >> 8))/****************************************************************************** Function: eprn_number_of_bitplanes Total number of bit planes returned by eprn_get_planes(). This value is constant while the device is open.******************************************************************************/unsigned int eprn_number_of_bitplanes(eprn_Device *dev){ return dev->eprn.output_planes;}/****************************************************************************** Function: eprn_number_of_octets Maximal lengths, in terms of the number of 'eprn_Octet' instances, for each bit plane returned by eprn_get_planes() for this device. These values are constant while the device is open.******************************************************************************/void eprn_number_of_octets(eprn_Device *dev, unsigned int lenghts[]){ unsigned int j, length; length = (dev->eprn.octets_per_line + dev->color_info.depth - 1)/ dev->color_info.depth; /* This results in length >= ceiling((number of pixels per line)/8) because: 8 * octets_per_line >= pixels_per_line * depth <==> octets_per_line/depth >= pixels_per_line/8 where division is to be understood as exact. */ for (j = 0; j < dev->eprn.output_planes; j++) lenghts[j] = length; return;}/****************************************************************************** Function: eprn_map_rgb_color_for_RGB Colour mapping function for the process colour model 'DeviceRGB' and 2 intensity levels per colorant.******************************************************************************/gx_color_index eprn_map_rgb_color_for_RGB(gx_device *device, const gx_color_value cv[]){ gx_color_value red = cv[0], green = cv[1], blue = cv[2]; static const gx_color_value half = gx_max_color_value/2; gx_color_index value = 0; const eprn_Device *dev = (eprn_Device *)device;#ifdef EPRN_TRACE if_debug3(EPRN_TRACE_CHAR, "! eprn_map_rgb_color_for_RGB() called for RGB = (%hu, %hu, %hu),\n", red, green, blue);#endif assert(dev->eprn.colour_model == eprn_DeviceRGB); if (red > half) value |= RED_BIT; if (green > half) value |= GREEN_BIT; if (blue > half) value |= BLUE_BIT;#ifdef EPRN_TRACE if_debug1(EPRN_TRACE_CHAR, " returning 0x%lX.\n", (unsigned long)value);#endif return value;}/****************************************************************************** Function: eprn_map_rgb_color_for_CMY_or_K Colour mapping function for the native colour spaces DeviceGray and DeviceRGB and a process colour model using a selection of CMYK colorants with at most 2 intensity levels per colorant. This function must not be called for the process colour models 'DeviceRGB' and 'DeviceCMYK'.******************************************************************************/gx_color_index eprn_map_rgb_color_for_CMY_or_K(gx_device *device, const gx_color_value cv[]){ gx_color_value red = cv[0], green = cv[1], blue = cv[2]; static const gx_color_value half = gx_max_color_value/2; gx_color_index value = (CYAN_BIT | MAGENTA_BIT | YELLOW_BIT); const eprn_Device *dev = (eprn_Device *)device;#ifdef EPRN_TRACE if_debug3(EPRN_TRACE_CHAR, "! eprn_map_rgb_color_for_CMY_or_K() called for RGB = (%hu, %hu, %hu),\n", red, green, blue);#endif assert(dev->eprn.colour_model == eprn_DeviceGray && red == green && green == blue && (blue == 0 || blue == gx_max_color_value) || dev->eprn.colour_model == eprn_DeviceCMY || dev->eprn.colour_model == eprn_DeviceCMY_plus_K); /* Map to CMY */ if (red > half) value &= ~CYAN_BIT; if (green > half) value &= ~MAGENTA_BIT; if (blue > half) value &= ~YELLOW_BIT; /* Remap composite black to true black if available */ if (dev->eprn.colour_model != eprn_DeviceCMY && value == (CYAN_BIT | MAGENTA_BIT | YELLOW_BIT)) value = BLACK_BIT;#ifdef EPRN_TRACE if_debug1(EPRN_TRACE_CHAR, " returning 0x%lX.\n", (unsigned long)value);#endif return value;}/****************************************************************************** Function: eprn_map_rgb_color_for_RGB_flex This is a 'map_rgb_color' method for the process colour model 'DeviceRGB' supporting any number of intensity levels.******************************************************************************/gx_color_index eprn_map_rgb_color_for_RGB_flex(gx_device *device, const gx_color_value cv[]){ gx_color_value red = cv[0], green = cv[1], blue = cv[2]; gx_color_index value = 0; gx_color_value step; unsigned int level; const eprn_Eprn *eprn = &((eprn_Device *)device)->eprn;#ifdef EPRN_TRACE if_debug3(EPRN_TRACE_CHAR, "! eprn_map_rgb_color_for_RGB_flex() called for RGB = (%hu, %hu, %hu),\n", red, green, blue);#endif /* See the discussion in eprn_map_cmyk_color_flex() below. */ step = gx_max_color_value/eprn->non_black_levels; /* The order has to be BGR from left to right */ level = blue/step; if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1; value = level << eprn->bits_per_colorant; level = green/step; if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1; value = (value | level) << eprn->bits_per_colorant; level = red/step; if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1; value = (value | level) << eprn->bits_per_colorant;#ifdef EPRN_TRACE if_debug1(EPRN_TRACE_CHAR, " returning 0x%lX.\n", (unsigned long)value);#endif return value;}/****************************************************************************** Function: eprn_map_rgb_color_for_CMY_or_K_flex This is a flexible 'map_rgb_color' method. It must not be called for the process colour models 'DeviceRGB' and 'DeviceCMYK'.******************************************************************************/gx_color_index eprn_map_rgb_color_for_CMY_or_K_flex(gx_device *device, const gx_color_value cv[]){ gx_color_value red = cv[0], green = cv[1], blue = cv[2]; const eprn_Device *dev = (eprn_Device *)device;#ifdef EPRN_TRACE if_debug3(EPRN_TRACE_CHAR, "! eprn_map_rgb_color_for_CMY_or_K_flex() called for " "RGB = (%hu, %hu, %hu).\n", red, green, blue);#endif /* Treat pure grey levels differently if we have black. This implies that for CMY+K only "true" grey shades will be printed with black ink, all others will be mixed from CMY. */ gx_color_value tmpcv[4]; if (dev->eprn.colour_model != eprn_DeviceCMY && red == green && green == blue) { tmpcv[0] = 0; tmpcv[1] = 0; tmpcv[2] = 0; tmpcv[3] = gx_max_color_value - red; return eprn_map_cmyk_color_flex(device, tmpcv); } tmpcv[0] = gx_max_color_value - red; tmpcv[1] = gx_max_color_value - green; tmpcv[2] = gx_max_color_value - blue; tmpcv[3] = 0; return eprn_map_cmyk_color_flex(device, tmpcv);}/****************************************************************************** Function: eprn_map_rgb_color_for_RGB_max Colour mapping function for the process colour model 'DeviceRGB' retaining as much information as possible.******************************************************************************/gx_color_index eprn_map_rgb_color_for_RGB_max(gx_device *device, const gx_color_value cv[]){ gx_color_value red = cv[0], green = cv[1], blue = cv[2]; gx_color_index value;#ifdef EPRN_TRACE if_debug3(EPRN_TRACE_CHAR, "! eprn_map_rgb_color_for_RGB_max() called for RGB = (%hu, %hu, %hu),\n", red, green, blue);#endif value = dominant_8bits(red) << 8; value |= dominant_8bits(green) << 16; value |= dominant_8bits(blue) << 24;#ifdef EPRN_TRACE if_debug1(EPRN_TRACE_CHAR, " returning 0x%08lX.\n", (unsigned long)value);#endif return value;}/****************************************************************************** Function: eprn_map_rgb_color_for_CMY_or_K_max "Maximal" colour mapping function for the process colour models "DeviceGray", "DeviceCMY", and "CMY+K".******************************************************************************/gx_color_index eprn_map_rgb_color_for_CMY_or_K_max(gx_device *device, const gx_color_value cv[]){ gx_color_value red = cv[0], green = cv[1], blue = cv[2]; const eprn_Device *dev = (eprn_Device *)device;#ifdef EPRN_TRACE if_debug3(EPRN_TRACE_CHAR, "! eprn_map_rgb_color_for_CMY_or_K_max() called for " "RGB = (%hu, %hu, %hu).\n", red, green, blue);#endif gx_color_value tmpcv[4]; if (dev->eprn.colour_model == eprn_DeviceGray) { tmpcv[0] = 0; tmpcv[1] = 0; tmpcv[2] = 0; tmpcv[3] = gx_max_color_value - red; return eprn_map_cmyk_color_max(device, tmpcv); } /* Note that the conversion from composite black to true black for CMY+K can only happen at the output pixel level, not here. */ tmpcv[0] = gx_max_color_value - red; tmpcv[1] = gx_max_color_value - green; tmpcv[2] = gx_max_color_value - blue; tmpcv[3] = 0; return eprn_map_cmyk_color_max(device, tmpcv);}/******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -