📄 gdevcd8-beta4.c
字号:
/* Send each scan line in turn */
send_scan_lines(pdev, &data_ptrs, &misc_vars,
&error_values, &gamma, prn_stream);
/* terminate page and eject paper */
(*cdj850->terminate_page) (pdev, prn_stream);
/* Free Memory */
gs_free((char *)data_ptrs.storage, misc_vars.storage_size_words, W,
"hp850_print_page");
return 0;
}
#define odd(i) ((i & 01) != 0)
private int
GetScanLine(gx_device_printer * pdev, int *lnum,
struct ptr_arrays *data_ptrs,
struct misc_struct *misc_vars,
word rmask)
{
word *data_words = (word *) data_ptrs->data[misc_vars->scan];
register word *end_data = data_words + misc_vars->line_size_words;
++(*lnum);
gdev_prn_copy_scan_lines(pdev, *lnum, (byte *) data_words, misc_vars->line_size);
misc_vars->scan = !misc_vars->scan; /* toggle scan direction */
misc_vars->is_two_pass = odd(*lnum); /* color output for odd lines */
/* Mask off 1-bits beyond the line width. */
end_data[-1] &= rmask;
/* Remove trailing 0s. */
while (end_data > data_words && end_data[-1] == 0)
end_data--;
return end_data - data_words;
}
/* Send the scan lines to the printer */
private void
send_scan_lines(gx_device_printer * pdev,
struct ptr_arrays *data_ptrs,
struct misc_struct *misc_vars,
struct error_val_field *error_values,
const Gamma *gamma,
FILE * prn_stream)
{
int lnum, lend, llen;
int num_blank_lines = 0;
word rmask =
~(word) 0 << ((-pdev->width * misc_vars->storage_bpp) & (W * 8 - 1));
lend = pdev->height - (dev_t_margin(pdev) + dev_b_margin(pdev)) * y_dpi;
error_values->c = error_values->m = error_values->y =
error_values->k = 0;
/* init the error buffer */
init_error_buffer(misc_vars, data_ptrs);
misc_vars->zero_row_count = 0;
lnum = -1;
llen = GetScanLine(pdev, &lnum, data_ptrs, misc_vars, rmask);
while (lnum < lend) {
num_blank_lines = 0;
while (lnum < lend && llen == 0) {
++num_blank_lines;
llen = GetScanLine(pdev, &lnum, data_ptrs, misc_vars, rmask);
}
if (lnum >= lend) {
break;
}
/* Skip blank lines if any */
if (num_blank_lines > 0) {
fprintf(prn_stream, "%dy", num_blank_lines / (cdj850->yscal + 1));
memset(data_ptrs->plane_data[0][0], 0,
(misc_vars->plane_size * 2 * misc_vars->num_comps));
memset(data_ptrs->plane_data_c[0][0], 0,
(misc_vars->plane_size_c * 2 * misc_vars->num_comps));
}
/* all blank lines printed, now for the non-blank lines */
if (cdj850->yscal && odd(lnum)) {
/* output a blank black plane for odd lines */
putc('v', prn_stream);
}
/* now output all non blank lines */
while (lnum < lend && llen != 0) {
misc_vars->is_color_data = 0; /* maybe we have color ? */
(*cdj850->print_non_blank_lines) (pdev, data_ptrs, misc_vars,
error_values, gamma, prn_stream);
llen = GetScanLine(pdev, &lnum, data_ptrs, misc_vars, rmask);
}
if (cdj850->yscal && odd(lnum)) { /* output empty line for odd lines */
(*cdj850->print_non_blank_lines) (pdev, data_ptrs, misc_vars,
error_values, gamma, prn_stream);
}
/* the current line is empty => run the next iteration */
}
}
/* print_line compresses (mode 9) and outputs one plane */
private void
print_c9plane(FILE * prn_stream, char plane_code, int plane_size,
const byte * curr, const byte * prev, byte * out_data)
{
/* Compress the output data */
int out_count = gdev_pcl_mode9compress(plane_size, curr, prev, out_data);
/* and output the data */
if (out_count > 0) {
fprintf(prn_stream, "%d%c", out_count, plane_code);
fwrite(out_data, sizeof(byte), out_count, prn_stream);
} else {
putc(plane_code, prn_stream);
}
}
/* Printing non-blank lines */
private void
cdj850_print_non_blank_lines(gx_device_printer * pdev,
struct ptr_arrays *data_ptrs,
struct misc_struct *misc_vars,
struct error_val_field *error_values,
const Gamma *gamma,
FILE * prn_stream)
{
static const char *const plane_code[2] =
{"wvvv", "vvvv"};
int i;
byte *kP = data_ptrs->plane_data[misc_vars->scan + 2][3];
byte *dp = data_ptrs->data[misc_vars->scan + 2];
int *ep = data_ptrs->errors[misc_vars->scan];
/* we need cmyk color separation befor all the rest, since
black may be contained in the color fields. This needs to
be done on all pixel-rows, since even unused color-bytes
might generate black */
misc_vars->is_color_data =
do_gcr(misc_vars->databuff_size, data_ptrs->data[misc_vars->scan],
gamma->k, gamma->c, gamma->m, gamma->y, gamma->correct,
(word *) data_ptrs->data[misc_vars->scan]);
/* dithering the black-plane */
FSDlinebw(misc_vars->scan, misc_vars->plane_size,
error_values, kP, misc_vars->num_comps, ep, dp);
/* output the black plane */
print_c9plane(prn_stream, 'v', misc_vars->plane_size,
data_ptrs->plane_data[misc_vars->scan][3],
data_ptrs->plane_data[1 - misc_vars->scan][3],
data_ptrs->out_data);
/* since color resolution is only half of the b/w-resolution,
we only output every second row */
if (!cdj850->yscal || misc_vars->is_two_pass) {
int plane_size_c = (*rescale_color_plane[cdj850->xscal][cdj850->yscal])
(misc_vars->databuff_size,
data_ptrs->data[misc_vars->scan],
data_ptrs->data[!misc_vars->scan],
data_ptrs->data_c[misc_vars->cscan]) / misc_vars->storage_bpp;
/* dither the color planes */
do_floyd_steinberg(misc_vars->scan, misc_vars->cscan,
misc_vars->plane_size, plane_size_c,
misc_vars->num_comps, data_ptrs, pdev, error_values);
/* Transfer raster graphics in the order C, M, Y, that is
planes 2,1,0 */
for (i = misc_vars->num_comps - 2; i >= 0; i--) {
/* output the lower color planes */
print_c9plane(prn_stream, plane_code[cdj850->intensities > 2][i],
plane_size_c,
data_ptrs->plane_data_c[misc_vars->cscan][i],
data_ptrs->plane_data_c[1 - misc_vars->cscan][i],
data_ptrs->out_data);
/* output the upper color planes */
if (cdj850->intensities > 2) {
print_c9plane(prn_stream, plane_code[0][i], plane_size_c,
data_ptrs->plane_data_c[misc_vars->cscan][i + 4],
data_ptrs->plane_data_c[1 -
misc_vars->cscan][i
+ 4],
data_ptrs->out_data);
} /* end cdj850->intensities > 2 */
} /* End For i = num_comps */
misc_vars->cscan = 1 - misc_vars->cscan;
} /* End of is_two_pass */
return;
}
/* moved that code into his own subroutine, otherwise things get
somewhat clumsy */
private void
do_floyd_steinberg(int scan, int cscan, int plane_size,
int plane_size_c, int n,
struct ptr_arrays *data_ptrs,
gx_device_printer * pdev,
struct error_val_field *error_values)
{
/* the color pointers */
byte *cPa, *mPa, *yPa, *cPb, *mPb, *yPb;
byte *dpc;
int *epc;
/* the b/w pointers */
byte *kP, *dp;
int *ep;
/* the color pointers, lower byte */
cPa = data_ptrs->plane_data_c[cscan + 2][2];
mPa = data_ptrs->plane_data_c[cscan + 2][1];
yPa = data_ptrs->plane_data_c[cscan + 2][0];
/* upper byte */
cPb = data_ptrs->plane_data_c[cscan + 2][6];
mPb = data_ptrs->plane_data_c[cscan + 2][5];
yPb = data_ptrs->plane_data_c[cscan + 2][4];
/* data and error */
dpc = data_ptrs->data_c[cscan + 2];
epc = data_ptrs->errors_c[cscan];
/* the b/w pointers */
kP = data_ptrs->plane_data[scan + 2][3];
dp = data_ptrs->data[scan + 2];
ep = data_ptrs->errors[scan];
switch (cdj850->intensities) {
case 2:
FSDlinec2(cscan, plane_size_c, error_values,
cPa, mPa, yPa, n, dpc, epc);
break;
case 3:
FSDlinec3(cscan, plane_size_c, error_values,
cPa, mPa, yPa, cPb, mPb, yPb, n, dpc, epc);
break;
case 4:
FSDlinec4(cscan, plane_size_c, error_values,
cPa, mPa, yPa, cPb, mPb, yPb, n, dpc, epc);
break;
default:
assert(0);
}
return;
}
/* here we do our own gamma-correction */
private void
do_gamma(float mastergamma, float gammaval, byte values[256])
{
int i;
float gamma;
if (gammaval > 0.0) {
gamma = gammaval;
} else {
gamma = mastergamma;
}
for (i = 0; i < 256; i++) {
values[i] = (byte) (255.0 *
(1.0 - pow(((double)(255.0 - (float)i) / 255.0),
(double)(1.0 / gamma))));
}
return;
}
/* here we calculate a lookup-table which is used to compensate the
relative loss of color due to undercolor-removal */
private void
do_black_correction(float kvalue, int kcorrect[256])
{
int i;
for (i = 0; i < 256; i++) {
kcorrect[i] = (int)
(100.0 * kvalue * (
pow(10.0,
pow((i / 255.0), 3.0)
)
- 1.0
)
);
}
return;
}
/* For Better Performance we use a macro here */
#define DOUCR(col1, col2, col3, col4)\
{\
/* determine how far we are from the grey axis. This is */\
/* traditionally done by computing MAX(CMY)-MIN(CMY). */\
/* However, if two colors are very similar, we could */\
/* as either CMYRGB and K. Therefore we calculate the */\
/* the distance col1-col2 and col2-col3, and use the */\
/* smaller one. */\
a = *col1 - *col2;\
b = *col2 - *col3;\
if (a >= b) {\
grey_distance = 1.0 - (b/255.0);\
} else {\
grey_distance = 1.0 - (a/255.0);\
}\
ucr = (byte) (*col3 * grey_distance); \
*col4 = *col4 + ucr; /* add removed black to black */\
/* remove only as much color as black is surviving the */\
/* gamma correction */\
ucr = *(kvalues + ucr);\
*col1 = *col1 - ucr ;\
*col2 = *col2 - ucr ;\
*col3 = *col3 - ucr ;\
}
/* For Better Performance we use a macro here */
#define DOGCR(col1, col2, col3, col4)\
{\
ucr = (int) *col3;\
*col1 -= ucr ;\
*col2 -= ucr ;\
*col3 -= ucr ;\
*col4 += ucr; /* add removed black to black */\
kadd = ucr + *(kcorrect + ucr);\
uca_fac = 1.0 + (kadd/255.0);\
*col1 *= uca_fac;\
*col2 *= uca_fac;\
}
/* Since resolution can be different on different planes, we need to
do real color separation, here we try a real grey component
replacement */
private int
do_gcr(int bytecount, byte * inbyte, const byte kvalues[256],
const byte cvalues[256], const byte mvalues[256],
const byte yvalues[256], const int kcorrect[256],
word * inword)
{
int i, ucr, kadd, is_color = 0;
float uca_fac;
byte *black, *cyan, *magenta, *yellow;
word last_color_value = 0;
word *last_color;
/* initialise *last_color with a dummmy value */
last_color = &last_color_value;
/* Grey component replacement */
for (i = 0; i < bytecount; i += 4) {
/* Assign to black the current address of inbyte */
black = inbyte++;
cyan = inbyte++;
magenta = inbyte++;
yellow = inbyte++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -