📄 eprnfs.c
字号:
/****************************************************************************** File: $Id: eprnfs.c,v 1.6 2001/05/01 07:02:01 Martin Rel $ Contents: Floyd-Steinberg error diffusion for eprn Author: Martin Lottermoser, Greifswaldstrasse 28, 38124 Braunschweig, Germany; e-mail: Martin.Lottermoser@t-online.de.******************************************************************************** ** Copyright (C) 2001 by Martin Lottermoser ** All rights reserved ** ******************************************************************************** Information about Floyd-Steinberg error diffusion should be available in a number of places. I've used: James D. Foley, Andries van Dam, Steven K. Feiner, John F. Hughes "Computer Graphics" Second edition in C Reading/Massachusetts, etc.: Addison-Wesley, 1996 ISBN 0-201-84840-6******************************************************************************//* Configuration management identification */#ifndef lintstatic const char cm_id[] = "@(#)$Id: eprnfs.c,v 1.6 2001/05/01 07:02:01 Martin Rel $";#endif/*****************************************************************************/#ifndef _XOPEN_SOURCE#define _XOPEN_SOURCE 500#endif#include "gdeveprn.h"/*****************************************************************************//* Here follow some macros for code sections used in several routines. */#define fit_to_octet(value) ((value) < 0? 0: (value) > 255? 255: (value))#define FS_assign() \ new_value = *to + correction; \ if (new_value < 0) { \ *to = 0; \ remaining_error += new_value; \ } \ else if (255 < new_value) { \ *to = 255; \ remaining_error += new_value - 255; \ } \ else *to = new_value;#define error_propagation_Gray() \ if (error != 0) { \ remaining_error = error; \ \ /* 7/16 of the error goes to the right */ \ correction = (7*error)/16; \ remaining_error -= correction; \ if (pixel < max_pixel) { \ to = from + 1; \ FS_assign() \ if (pixel == pixels - 1 && *to > 0) { \ pixels++; \ line->length++; \ } \ } \ \ /* 3/16 of the error goes to the left and below */ \ correction = (3*error)/16; \ remaining_error -= correction; \ if (pixel > 0) { \ to = next_line->str + (pixel - 1); \ FS_assign() \ if (next_line->length < pixel && *to > 0) next_line->length = pixel; \ } \ \ /* 5/16 of the error goes below */ \ correction = (5*error)/16; \ remaining_error -= correction; \ to = next_line->str + pixel; \ FS_assign() \ if (next_line->length <= pixel && *to > 0) next_line->length = pixel + 1; \ \ /* The remainder (about 1/16 of the error) is added to the right and */ \ /* below. */ \ if (pixel < max_pixel) { \ to = next_line->str + (pixel+1); \ new_value = *to + remaining_error; \ *to = fit_to_octet(new_value); \ if (next_line->length < pixel + 2 && *to > 0) \ next_line->length = pixel + 2; \ } \ }/* Number of octets per pixel for the non-monochrome cases */#define OCTETS_PER_PIXEL 4#define error_propagation_colour() \ if (error != 0) { \ remaining_error = error; \ \ /* 7/16 of the error goes to the right */ \ correction = (7*error)/16; \ remaining_error -= correction; \ if (pixel < max_pixel) { \ to = from + OCTETS_PER_PIXEL; \ FS_assign() \ if (pixel == pixels - 1 && *to > 0) { \ pixels++; \ line->length += OCTETS_PER_PIXEL; \ } \ } \ \ /* 3/16 of the error goes to the left and below */ \ correction = (3*error)/16; \ remaining_error -= correction; \ if (pixel > 0) { \ to = next_line->str + (pixel - 1)*OCTETS_PER_PIXEL + colorant; \ FS_assign() \ if (next_line->length < pixel*OCTETS_PER_PIXEL && *to > 0) \ next_line->length = pixel*OCTETS_PER_PIXEL; \ } \ \ /* 5/16 of the error goes below */ \ correction = (5*error)/16; \ remaining_error -= correction; \ to = next_line->str + pixel*OCTETS_PER_PIXEL + colorant; \ FS_assign() \ if (next_line->length <= pixel*OCTETS_PER_PIXEL && *to > 0) \ next_line->length = (pixel + 1)*OCTETS_PER_PIXEL; \ \ /* The remainder (about 1/16 of the error) is added to the right and */ \ /* below. */ \ if (pixel < max_pixel) { \ to = next_line->str + (pixel+1)*OCTETS_PER_PIXEL + colorant; \ new_value = *to + remaining_error; \ *to = fit_to_octet(new_value); \ if (next_line->length < (pixel + 2)*OCTETS_PER_PIXEL && *to > 0) \ next_line->length = (pixel + 2)*OCTETS_PER_PIXEL; \ } \ }/****************************************************************************** Function: split_Gray_2 Floyd-Steinberg error diffusion for the process colour model Gray and 2 intensity levels.******************************************************************************/static void split_Gray_2(eprn_OctetString *line, eprn_OctetString *next_line, int max_octets, eprn_OctetString bitplanes[]){ const int max_pixel = max_octets - 1; int correction, error, new_value, pixel, pixel_mod_8, pixels = line->length, remaining_error; eprn_Octet approx, *from, *ptr, *to; ptr = bitplanes[0].str; /* Loop over pixels in the scan line. Note that 'pixels' may increase within the loop. */ for (pixel = 0, pixel_mod_8 = 8; pixel < pixels; pixel++, pixel_mod_8++) { if (pixel_mod_8 == 8) { pixel_mod_8 = 0; *ptr = 0; } /* Determine approximation and error for this pixel */ from = line->str + pixel; approx = *from >> 7; /* take the most significant bit */ error = *from - 255*approx; /* The sign of 'error' is chosen such that 'error' is positive if colorant intensity has to be added to the picture. */ /* Insert the approximation into the output plane */ *ptr = (*ptr << 1) | approx; error_propagation_Gray() if (pixel_mod_8 == 7) ptr++; } eprn_finalize(false, 0, 1, bitplanes, &ptr, pixels); return;}/****************************************************************************** Function: split_Gray() Floyd-Steinberg error diffusion for the process colour model Gray and an arbitrary number of intensity levels.******************************************************************************/static void split_Gray(eprn_OctetString *line, eprn_OctetString *next_line, int max_octets, unsigned int black_levels, eprn_OctetString bitplanes[]){ const int max_pixel = max_octets - 1, planes = eprn_bits_for_levels(black_levels); int correction, error, new_value, pixel, pixel_mod_8, pixels = line->length, plane, remaining_error; eprn_Octet approx, *from, *ptr[8], *to; const unsigned int divisor = 256/black_levels, max_level = black_levels - 1; for (plane = 0; plane < planes; plane++) ptr[plane] = bitplanes[plane].str; /* Loop over pixels in the scan line. Note that 'pixels' may increase within the loop. */ for (pixel = 0, pixel_mod_8 = 8; pixel < pixels; pixel++, pixel_mod_8++) { if (pixel_mod_8 == 8) { pixel_mod_8 = 0; for (plane = 0; plane < planes; plane++) *ptr[plane] = 0; } /* Determine approximation and error for this pixel */ from = line->str + pixel; approx = *from/divisor; error = *from - (255*approx)/max_level; /* The sign of 'error' is chosen such that 'error' is positive if colorant intensity has to be added to the picture. */ /* Distribute the approximation over the bit planes */ for (plane = 0; plane < planes; plane++) { *ptr[plane] = (*ptr[plane] << 1) | approx & 0x01; approx >>= 1; } error_propagation_Gray() if (pixel_mod_8 == 7) for (plane = 0; plane < planes; plane++) ptr[plane]++; } eprn_finalize(false, 0, planes, bitplanes, ptr, pixels); return;}/*****************************************************************************//* Index of the black colorant in a pixel value (gx_color_index) for the non-monochrome cases */#define BLACK_INDEX 3/****************************************************************************** Function: split_colour_CMYK_2() Floyd-Steinberg error diffusion for the CMYK colour model using 2 intensity levels for all colorants. This function is about 14 % faster than split_colour_at_most_2(), and every bit helps.******************************************************************************/#define PLANES 4static void split_colour_CMYK_2(eprn_OctetString *line, eprn_OctetString *next_line, int max_octets, eprn_OctetString bitplanes[]){ const int max_pixel = max_octets/OCTETS_PER_PIXEL - 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -