⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdevcd8-beta4.c

📁 printer driver for the HP670, HP690, HP850, HP855 HP870, HP890, HP1100 and HP1600 color printers.
💻 C
📖 第 1 页 / 共 5 页
字号:

    /* 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 + -