示例#1
0
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;
}
示例#2
0
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++)
示例#3
0
文件: gdeveprn.c 项目: hackqiang/gs
int eprn_open_device(gx_device *device)
{
  eprn_Eprn *eprn = &((eprn_Device *)device)->eprn;
  const char *epref = eprn->CUPS_messages? CUPS_ERRPREF: "";
  int rc;

#ifdef EPRN_TRACE
  if_debug0(EPRN_TRACE_CHAR, "! eprn_open_device()...\n");
#endif

  /* Checks on page size and determination of derived values */
  if (eprn_set_page_layout((eprn_Device *)device) != 0)
    return_error(gs_error_rangecheck);

  /* Check the rendering parameters */
  if (eprn_check_colour_info(eprn->cap->colour_info, &eprn->colour_model,
      &device->HWResolution[0], &device->HWResolution[1],
      &eprn->black_levels, &eprn->non_black_levels) != 0) {
    gs_param_string str;

    eprintf1("%s" ERRPREF "The requested combination of colour model (",
      epref);
    str.size = 0;
    if (eprn_get_string(eprn->colour_model, eprn_colour_model_list, &str) != 0)
      assert(0); /* Bug. No harm on NDEBUG because I've just set the size. */
    errwrite(device->memory, (const char *)str.data, str.size * sizeof(str.data[0]));
    eprintf7("),\n"
      "%s  resolution (%gx%g ppi) and intensity levels (%d, %d) is\n"
      "%s  not supported by the %s.\n",
      epref, device->HWResolution[0], device->HWResolution[1],
      eprn->black_levels, eprn->non_black_levels, epref, eprn->cap->name);
    return_error(gs_error_rangecheck);
  }

  /* Initialization for colour rendering */
  if (device->color_info.num_components == 4) {
    /* Native colour space is 'DeviceCMYK' */
    set_dev_proc(device, map_rgb_color, NULL);

    if (eprn->intensity_rendering == eprn_IR_FloydSteinberg)
      set_dev_proc(device, map_cmyk_color, &eprn_map_cmyk_color_max);
    else if (device->color_info.max_gray > 1 || device->color_info.max_color > 1)
      set_dev_proc(device, map_cmyk_color, &eprn_map_cmyk_color_flex);
    else
      set_dev_proc(device, map_cmyk_color, &eprn_map_cmyk_color);

    if (eprn->intensity_rendering == eprn_IR_FloydSteinberg)
      set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K_max);
    else if (device->color_info.max_gray > 1 || device->color_info.max_color > 1)
      set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K_flex);
    else
      set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K);

  }
  else {
    set_dev_proc(device, map_cmyk_color, NULL);

    if (eprn->colour_model == eprn_DeviceRGB) {
      if (eprn->intensity_rendering == eprn_IR_FloydSteinberg)
        set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_RGB_max);
      else if (device->color_info.max_color > 1)
        set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_RGB_flex);
      else
        set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_RGB);
    } else {
      if (eprn->intensity_rendering == eprn_IR_FloydSteinberg)
        set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K_max);
      else if (device->color_info.max_gray > 1 || device->color_info.max_color > 1)
        set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K_flex);
      else
        set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K);
    }
  }
  eprn->output_planes = eprn_bits_for_levels(eprn->black_levels) +
    3 * eprn_bits_for_levels(eprn->non_black_levels);

#if !defined(GS_REVISION) || GS_REVISION >= 600
  /*  According to my understanding, the following call should be superfluous
      (because the colour mapping functions may not be called while the device
      is closed) and I am also not aware of any situation where it does make a
      difference. It shouldn't do any harm, though, and I feel safer with it :-)
  */
  gx_device_decache_colors(device);
#endif

#ifndef EPRN_NO_PAGECOUNTFILE
  /* Read the page count value */
  if (eprn->pagecount_file != NULL) {
    unsigned long count;
    if (pcf_getcount(eprn->pagecount_file, &count) == 0)
      device->PageCount = count;
       /* unsigned to signed. The C standard permits
          an implementation to generate an overflow indication if the value is
          too large. I consider this to mean that the type of 'PageCount' is
          inappropriate :-). Note that eprn does not use 'PageCount' for
          updating the file. */
    else {
      /* pcf_getcount() has issued an error message. */
      eprintf(
        "  No further attempts will be made to access the page count file.\n");
      gs_free(device->memory->non_gc_memory, eprn->pagecount_file, strlen(eprn->pagecount_file) + 1,
        sizeof(char), "eprn_open_device");
      eprn->pagecount_file = NULL;
    }
  }
#endif  /* !EPRN_NO_PAGECOUNTFILE */

  /* Open the "prn" device part */
  if ((rc = gdev_prn_open(device)) != 0) return rc;

  /* Just in case a previous open call failed in a derived device (note that
     'octets_per_line' is still the same as then): */
  if (eprn->scan_line.str != NULL)
    gs_free(device->memory->non_gc_memory, eprn->scan_line.str, eprn->octets_per_line, sizeof(eprn_Octet),
      "eprn_open_device");
  if (eprn->next_scan_line.str != NULL) {
    gs_free(device->memory->non_gc_memory, eprn->next_scan_line.str, eprn->octets_per_line, sizeof(eprn_Octet),
      "eprn_open_device");
    eprn->next_scan_line.str = NULL;
  }

  /* Calls which might depend on prn having been initialized */
  eprn->octets_per_line = gdev_prn_raster((gx_device_printer *)device);
  eprn->scan_line.str = (eprn_Octet *) gs_malloc(device->memory->non_gc_memory, eprn->octets_per_line,
    sizeof(eprn_Octet), "eprn_open_device");
  if (eprn->intensity_rendering == eprn_IR_FloydSteinberg) {
    eprn->next_scan_line.str = (eprn_Octet *) gs_malloc(device->memory->non_gc_memory, eprn->octets_per_line,
      sizeof(eprn_Octet), "eprn_open_device");
    if (eprn->next_scan_line.str == NULL && eprn->scan_line.str != NULL) {
      gs_free(device->memory->non_gc_memory, eprn->scan_line.str, eprn->octets_per_line, sizeof(eprn_Octet),
        "eprn_open_device");
      eprn->scan_line.str = NULL;
    }
  }
  if (eprn->scan_line.str == NULL) {
    eprintf1("%s" ERRPREF
      "Memory allocation failure from gs_malloc() in eprn_open_device().\n",
      epref);
    return_error(gs_error_VMerror);
  }

  return rc;
}
示例#4
0
static void split_colour(eprn_OctetString *line, eprn_OctetString *next_line,
  int max_octets, eprn_ColourModel colour_model,
  unsigned int black_levels, unsigned int non_black_levels,
  eprn_OctetString bitplanes[])
{
  const int
    black_planes = eprn_bits_for_levels(black_levels),
    last_colorant = black_levels > 0? BLACK_INDEX: 2,
    max_pixel = max_octets/OCTETS_PER_PIXEL - 1,
    non_black_planes = eprn_bits_for_levels(non_black_levels),
    planes = black_planes + 3*non_black_planes;
  int
    colorant,
    correction,
    error,
    new_value,
    next_plane[4],
    pixel,
    pixel_mod_8,
    pixels = line->length/OCTETS_PER_PIXEL,
    plane,
    remaining_error;
  eprn_Octet
    approx[4],
    *from,
    *ptr[32],
    *to;
  unsigned int
    divisor[4],
    max_level[4];

  if (black_levels > 0) {
    divisor[BLACK_INDEX] = 256/black_levels;
    max_level[BLACK_INDEX] = black_levels - 1;
  }
  else {
    divisor[BLACK_INDEX] = 0;
    max_level[BLACK_INDEX] = 0;
  }
  next_plane[BLACK_INDEX] = black_planes;

  for (colorant = 0; colorant < BLACK_INDEX; colorant++) {
    divisor[colorant] = 256/non_black_levels;
    max_level[colorant] = non_black_levels - 1;
    next_plane[colorant] = (3 - colorant)*non_black_planes + black_planes;
  }

  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;
    }

    /* Loop over colorants within a scan line */
    for (colorant = last_colorant; colorant >= 0; colorant--) {
      from = line->str + pixel*OCTETS_PER_PIXEL + colorant;

      /* Determine approximation and error for this pixel */
      approx[colorant] = *from/divisor[colorant];
      error = *from - (255*approx[colorant])/max_level[colorant];
       /* The sign of 'error' is chosen such that 'error' is positive if
	  colorant intensity has to be added to the picture. */

      error_propagation_colour()
    }

    /* Determine the black component for CMY+K */
    if (colour_model == eprn_DeviceCMY_plus_K &&
	approx[0] == approx[1] && approx[1] == approx[2] && approx[0] > 0) {
      int value = approx[0]*(black_levels - 1);
      if (value % (non_black_levels - 1) == 0) {
	/* Black does have a level at the same intensity as the CMY levels */
	approx[BLACK_INDEX] = value/(non_black_levels - 1);
	approx[0] = approx[1] = approx[2] = 0;
      }
    }

    /* Distribute the approximation over the bit planes */
    plane = 0;
    for (colorant = last_colorant; colorant >= 0; colorant--) {
      while (plane < next_plane[colorant]) {
	*ptr[plane] = (*ptr[plane] << 1) | approx[colorant] & 0x01;
	approx[colorant] >>= 1;
	plane++;
      }
    }

    if (pixel_mod_8 == 7) {
      int j;
      for (j = 0; j < planes; j++) ptr[j]++;
    }
  }

  eprn_finalize(colour_model == eprn_DeviceRGB, non_black_levels, planes,
    bitplanes, ptr, pixels);

  return;
}