home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevcmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  9.6 KB  |  314 lines

  1. /* Copyright (C) 1998, 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevcmap.c,v 1.2 2000/09/19 19:00:12 lpd Exp $ */
  20. /* Special color mapping device */
  21. #include "gx.h"
  22. #include "gserrors.h"
  23. #include "gxdevice.h"
  24. #include "gxlum.h"
  25. #include "gxfrac.h"
  26. #include "gxdcconv.h"
  27. #include "gdevcmap.h"
  28.  
  29. /*
  30.  * The devices in this file exist only to implement the PCL5 special
  31.  * color mapping algorithms.  They are not useful for PostScript.
  32.  */
  33.  
  34. /* GC descriptor */
  35. public_st_device_cmap();
  36.  
  37. /* Device procedures */
  38. private dev_proc_map_rgb_color(cmap_map_rgb_color);
  39. private dev_proc_map_rgb_alpha_color(cmap_map_rgb_alpha_color);
  40. private dev_proc_map_cmyk_color(cmap_map_cmyk_color);
  41. private dev_proc_get_params(cmap_get_params);
  42. private dev_proc_put_params(cmap_put_params);
  43. private dev_proc_begin_typed_image(cmap_begin_typed_image);
  44.  
  45. private const gx_device_cmap gs_cmap_device = {
  46.     std_device_dci_body(gx_device_cmap, 0, "special color mapper",
  47.             0, 0, 1, 1,
  48.             3, 24, 255, 255, 256, 256),
  49.     {
  50.     0, 0, 0, 0, 0,
  51.     cmap_map_rgb_color,
  52.     0,            /* map_color_rgb */
  53.     gx_forward_fill_rectangle,
  54.     gx_forward_tile_rectangle,
  55.     gx_forward_copy_mono,
  56.     gx_forward_copy_color,
  57.     0, 0,
  58.     cmap_get_params,
  59.     cmap_put_params,
  60.     cmap_map_cmyk_color,
  61.     0, 0,
  62.     cmap_map_rgb_alpha_color,
  63.     0, 0, 0, 0, 0,
  64.     0, 0, 0, 0, 0, 0, 0,
  65.     gx_default_begin_image,
  66.     0, 0, 0, 0, 0,
  67.     cmap_begin_typed_image,
  68.     0,
  69.     0            /* map_color_rgb_alpha */
  70.     },
  71.     0,                /* target */
  72.     device_cmap_identity
  73. };
  74.  
  75. /* Set the color mapping method. */
  76. private int
  77. gdev_cmap_set_method(gx_device_cmap * cmdev,
  78.              gx_device_color_mapping_method_t method)
  79. {
  80.     gx_device *target = cmdev->target;
  81.  
  82.     /*
  83.      * If we're transforming the color, we may need to fool the graphics
  84.      * core into not halftoning.
  85.      */
  86.     set_dev_proc(cmdev, map_cmyk_color, gx_default_map_cmyk_color);
  87.     set_dev_proc(cmdev, map_color_rgb, gx_forward_map_color_rgb);
  88.  
  89.     switch (method) {
  90.  
  91.     case device_cmap_identity:
  92.         /*
  93.          * In this case, and only this case, we can allow the target's
  94.          * color model to propagate here.
  95.          */
  96.         set_dev_proc(cmdev, map_cmyk_color, gx_forward_map_cmyk_color);
  97.         cmdev->color_info.max_gray = target->color_info.max_gray;
  98.         cmdev->color_info.max_color = target->color_info.max_color;
  99.         cmdev->color_info.num_components =
  100.         target->color_info.num_components;
  101.         gx_device_copy_color_procs((gx_device *)cmdev, target);
  102.         break;
  103.  
  104.     case device_cmap_monochrome:
  105.         cmdev->color_info.max_gray = target->color_info.max_gray;
  106.         cmdev->color_info.max_color = target->color_info.max_color;
  107.         cmdev->color_info.num_components = 1;
  108.         break;
  109.  
  110.     case device_cmap_snap_to_primaries:
  111.     case device_cmap_color_to_black_over_white:
  112.         cmdev->color_info.max_gray = cmdev->color_info.max_color = 4095;
  113.         /*
  114.          * We have to be an RGB device, otherwise "primaries" doesn't
  115.          * have the proper meaning.
  116.          */
  117.         cmdev->color_info.num_components = 3;
  118.         break;
  119.  
  120.     default:
  121.         return_error(gs_error_rangecheck);
  122.     }
  123.     cmdev->mapping_method = method;
  124.     return 0;
  125. }
  126.  
  127. /* Initialize the device. */
  128. int
  129. gdev_cmap_init(gx_device_cmap * dev, gx_device * target,
  130.            gx_device_color_mapping_method_t method)
  131. {
  132.     int code;
  133.  
  134.     gx_device_init((gx_device *) dev, (const gx_device *)&gs_cmap_device,
  135.            target->memory, true);
  136.     gx_device_set_target((gx_device_forward *)dev, target);
  137.     gx_device_copy_params((gx_device *)dev, target);
  138.     gx_device_forward_fill_in_procs((gx_device_forward *) dev);
  139.     code = gdev_cmap_set_method(dev, method);
  140.     if (code < 0)
  141.     return code;
  142.     return 0;
  143. }
  144.  
  145. /* Map RGB colors, and convert to the target's native color model. */
  146. /* Return true if the target is an RGB device, false if CMYK. */
  147. private bool
  148. cmap_convert_rgb_color(const gx_device_cmap * cmdev, gx_color_value red,
  149.                gx_color_value green, gx_color_value blue,
  150.                gx_color_value cv[4])
  151. {
  152.     gx_color_value red_out, green_out, blue_out;
  153.  
  154.     switch (cmdev->mapping_method) {
  155.  
  156.     case device_cmap_snap_to_primaries:
  157.         /* Snap each RGB primary component to 0 or 1 individually. */
  158.         red_out =
  159.         (red <= gx_max_color_value / 2 ? 0 : gx_max_color_value);
  160.         green_out =
  161.         (green <= gx_max_color_value / 2 ? 0 : gx_max_color_value);
  162.         blue_out =
  163.         (blue <= gx_max_color_value / 2 ? 0 : gx_max_color_value);
  164.         break;
  165.  
  166.     case device_cmap_color_to_black_over_white:
  167.         /* Snap black to white, other colors to black. */
  168.         red_out = green_out = blue_out =
  169.         ((red | green | blue) == 0 ? gx_max_color_value : 0);
  170.         break;
  171.  
  172.     case device_cmap_identity:
  173.     case device_cmap_monochrome:
  174.     default:
  175.         red_out = red, green_out = green, blue_out = blue;
  176.         break;
  177.  
  178.     }
  179.  
  180.     /* Check for a CMYK device. */
  181.     if (cmdev->target->color_info.num_components <= 3) {
  182.     cv[0] = red_out, cv[1] = green_out, cv[2] = blue_out;
  183.     return true;
  184.     }
  185.  
  186.     /*
  187.      * Convert RGB to CMYK using default (null) black generation and
  188.      * undercolor removal.  This isn't right, but we don't have access to an
  189.      * imager state to provide the correct procedures.
  190.      */
  191.     cv[0] = gx_max_color_value - red_out;
  192.     cv[1] = gx_max_color_value - green_out;
  193.     cv[2] = gx_max_color_value - blue_out;
  194.     cv[3] = 0;
  195.     return false;
  196. }
  197.  
  198. private gx_color_index
  199. cmap_map_rgb_color(gx_device * dev, gx_color_value red,
  200.            gx_color_value green, gx_color_value blue)
  201. {
  202.     const gx_device_cmap *const cmdev = (const gx_device_cmap *)dev;
  203.     gx_device *target = cmdev->target;
  204.     gx_color_value cv[4];
  205.     bool is_rgb = cmap_convert_rgb_color(cmdev, red, green, blue, cv);
  206.  
  207.     return
  208.     (is_rgb ? target->procs.map_rgb_color(target, cv[0], cv[1], cv[2]) :
  209.      target->procs.map_cmyk_color(target, cv[0], cv[1], cv[2], cv[3]));
  210. }
  211.  
  212. private gx_color_index
  213. cmap_map_rgb_alpha_color(gx_device * dev, gx_color_value red,
  214.              gx_color_value green, gx_color_value blue,
  215.              gx_color_value alpha)
  216. {
  217.     const gx_device_cmap *const cmdev = (const gx_device_cmap *)dev;
  218.     gx_device *target = cmdev->target;
  219.     gx_color_value cv[4];
  220.     bool is_rgb = cmap_convert_rgb_color(cmdev, red, green, blue, cv);
  221.  
  222.     return
  223.     (is_rgb ? target->procs.map_rgb_alpha_color(target, cv[0], cv[1],
  224.                             cv[2], alpha) :
  225.      /****** CMYK DISREGARDS ALPHA ******/
  226.      target->procs.map_cmyk_color(target, cv[0], cv[1], cv[2], cv[3]));
  227. }
  228.  
  229. private gx_color_index
  230. cmap_map_cmyk_color(gx_device * dev, gx_color_value c,
  231.             gx_color_value m, gx_color_value y, gx_color_value k)
  232. {
  233.     const gx_device_cmap *const cmdev = (const gx_device_cmap *)dev;
  234.     gx_device *target = cmdev->target;
  235.     frac frac_rgb[3];
  236.  
  237.     if (cmdev->mapping_method == device_cmap_identity)
  238.     return target->procs.map_cmyk_color(target, c, m, y, k);
  239.     color_cmyk_to_rgb(cv2frac(c), cv2frac(m), cv2frac(y), cv2frac(k),
  240.               NULL, frac_rgb);
  241.     return cmap_map_rgb_color(dev, frac2cv(frac_rgb[0]),
  242.                   frac2cv(frac_rgb[1]),
  243.                   frac2cv(frac_rgb[2]));
  244. }
  245.  
  246. /* Get parameters. */
  247. private int
  248. cmap_get_params(gx_device * dev, gs_param_list * plist)
  249. {
  250.     int code = gx_forward_get_params(dev, plist);
  251.     int ecode = code;
  252.     gx_device_cmap * const cmdev = (gx_device_cmap *)dev;
  253.     int cmm = cmdev->mapping_method;
  254.  
  255.     if ((code = param_write_int(plist, "ColorMappingMethod", &cmm)) < 0)
  256.     ecode = code;
  257.     return ecode;
  258. }
  259.  
  260. /* Update parameters; copy the device information back afterwards. */
  261. private int
  262. cmap_put_params(gx_device * dev, gs_param_list * plist)
  263. {
  264.     int code = gx_forward_put_params(dev, plist);
  265.     int ecode = code;
  266.     gx_device_cmap * const cmdev = (gx_device_cmap *)dev;
  267.     int cmm = cmdev->mapping_method;
  268.     const char *param_name;
  269.  
  270.     switch (code = param_read_int(plist, param_name = "ColorMappingMethod",
  271.                   &cmm)) {
  272.     case 0:
  273.     if (cmm < 0 || cmm > device_cmap_max_method) {
  274.         code = gs_note_error(gs_error_rangecheck);
  275.     } else
  276.         break;
  277.     default:
  278.     ecode = code;
  279.     param_signal_error(plist, param_name, ecode);
  280.     break;
  281.     case 1:
  282.     break;
  283.     }
  284.     if (code >= 0) {
  285.     gx_device_copy_params(dev, cmdev->target);
  286.     gdev_cmap_set_method(cmdev, cmm);
  287.     }
  288.     return ecode;
  289. }
  290.  
  291. /*
  292.  * Handle high-level images.  The only reason we do this, rather than simply
  293.  * pass the operation to the target, is that the image still has to call the
  294.  * cmap device to do its color mapping.  As presently implemented, this
  295.  * disables any high-level implementation that the target may provide.
  296.  */
  297. private int
  298. cmap_begin_typed_image(gx_device * dev,
  299.                const gs_imager_state * pis, const gs_matrix * pmat,
  300.            const gs_image_common_t * pic, const gs_int_rect * prect,
  301.                const gx_drawing_color * pdcolor,
  302.                const gx_clip_path * pcpath,
  303.                gs_memory_t * memory, gx_image_enum_common_t ** pinfo)
  304. {
  305.     const gx_device_cmap *const cmdev = (const gx_device_cmap *)dev;
  306.     gx_device *target = cmdev->target;
  307.  
  308.     if (cmdev->mapping_method == device_cmap_identity)
  309.     return (*dev_proc(target, begin_typed_image))
  310.         (target, pis, pmat, pic, prect, pdcolor, pcpath, memory, pinfo);
  311.     return gx_default_begin_typed_image(dev, pis, pmat, pic, prect,
  312.                     pdcolor, pcpath, memory, pinfo);
  313. }
  314.