diff options
Diffstat (limited to 'doc/gimpprint.info-2')
-rw-r--r-- | doc/gimpprint.info-2 | 1080 |
1 files changed, 1080 insertions, 0 deletions
diff --git a/doc/gimpprint.info-2 b/doc/gimpprint.info-2 new file mode 100644 index 0000000..3539915 --- /dev/null +++ b/doc/gimpprint.info-2 @@ -0,0 +1,1080 @@ +This is gimpprint.info, produced by makeinfo version 4.0 from +gimpprint.texi. + +INFO-DIR-SECTION Libraries +START-INFO-DIR-ENTRY +* GIMP-Print: (gimpprint). print plugin for the GIMP, and printing library +END-INFO-DIR-ENTRY + + This file documents the gimpprint library and associated programs +used for high quality printing. + + Copyright (C) 2001 Michael Sweet (<mike@easysw.com>) and Robert +Krawitz (<rlk@alum.mit.edu>) + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: gimpprint.info, Node: Options functions, Next: Paper functions, Prev: Dither functions, Up: Functions + +Options functions +================= + + - Data type: void * stp_option_t + This is an opaque data type, whose structure is not visible to the + user. + + - Function: void stp_set_option(stp_vars_t V, const char *NAME, const + char *DATA, int BYTES) + + - Function: void stp_clear_option (stp_vars_t V, const char *NAME) + + - Function: void stp_clear_all_options (stp_vars_t V) + + - Function: size_t stp_option_count (const stp_vars_t V) + + - Function: const stp_option_t stp_get_option_by_index (const + stp_vars_t V, size_t IDX) + + - Function: const stp_option_t stp_get_option_by_name (const + stp_vars_t V, const char *NAME) + + - Function: const char * stp_option_data (const stp_option_t OPTION) + *Note*: not null delimited! + + - Function: const char * stp_option_name (const stp_option_t OPTION) + + - Function: size_t stp_option_length (const stp_option_t OPTION) + + +File: gimpprint.info, Node: Paper functions, Next: Printer functions, Prev: Options functions, Up: Functions + +Paper functions +=============== + + - Data type: void * stp_papersize_t + This is an opaque data type, whose structure is not visible to the + user. + + - Data type: stp_papersize_unit_t + typedef enum papersize_unit + { + PAPERSIZE_ENGLISH, + PAPERSIZE_METRIC + } stp_papersize_unit_t; + + - Function: int stp_known_papersizes (void) + + - Function: const stp_papersize_t stp_get_papersize_by_name (const + char *NAME) + + - Function: const stp_papersize_t stp_get_papersize_by_size (int L, + int W) + + - Function: const stp_papersize_t stp_get_papersize_by_index (int + INDEX) + + - Function: const char * stp_papersize_get_name (const stp_papersize_t + PT) + + - Function: unsigned stp_papersize_get_width (const stp_papersize_t PT) + + - Function: unsigned stp_papersize_get_height (const stp_papersize_t + PT) + + - Function: unsigned stp_papersize_get_top (const stp_papersize_t PT) + + - Function: unsigned stp_papersize_get_left (const stp_papersize_t PT) + + - Function: unsigned stp_papersize_get_bottom (const stp_papersize_t + PT) + + - Function: unsigned stp_papersize_get_right (const stp_papersize_t PT) + + - Function: stp_papersize_unit_t stp_papersize_get_unit (const + stp_papersize_t PT) + + +File: gimpprint.info, Node: Printer functions, Next: Settings functions, Prev: Paper functions, Up: Functions + +Printer functions +================= + + - Data type: void * stp_printer_t + This is an opaque data type, whose structure is not visible to the + user. + + - Function: int stp_known_printers (void) + + - Function: const stp_printer_t stp_get_printer_by_index (int IDX) + + - Function: const char * stp_printer_get_long_name (const + stp_printer_t P) + + - Function: const stp_printer_t stp_get_printer_by_long_name (const + char *LONG_NAME) + + - Function: const stp_printer_t stp_get_printer_by_driver (const char + *DRIVER) + + - Function: int stp_get_printer_index_by_driver (const char *DRIVER) + + - Function: const char * stp_printer_get_driver (const stp_printer_t P) + + - Function: int stp_printer_get_model (const stp_printer_t P) + + - Function: const stp_printfuncs_t * stp_printer_get_printfuncs (const + stp_printer_t P) + + - Data type: stp_printfuncs_t + typedef struct + { + char **(*parameters)(const stp_printer_t printer, + const char *ppd_file, + const char *name, int *count); + void (*media_size)(const stp_printer_t printer, + const stp_vars_t v, int *width, + int *height); + void (*imageable_area)(const stp_printer_t printer, + const stp_vars_t v, + int *left, int *right, + int *bottom, int *top); + void (*limit)(const stp_printer_t printer, + const stp_vars_t v, + int *width, int *height); + void (*print)(const stp_printer_t printer, + stp_image_t *image, const stp_vars_t v); + const char *(*default_parameters)(const stp_printer_t printer, + const char *ppd_file, + const char *name); + void (*describe_resolution)(const stp_printer_t printer, + const char *resolution, + int *x, int *y); + int (*verify)(const stp_printer_t p, const stp_vars_t v); + } stp_printfuncs_t; + + - Data type: stp_image_t + typedef struct stp_image + { + void (*init)(struct stp_image *image); + void (*reset)(struct stp_image *image); + void (*transpose)(struct stp_image *image); + void (*hflip)(struct stp_image *image); + void (*vflip)(struct stp_image *image); + void (*crop)(struct stp_image *image, + int left, int top, int right, + int bottom); + void (*rotate_ccw)(struct stp_image *image); + void (*rotate_cw)(struct stp_image *image); + void (*rotate_180)(struct stp_image *image); + int (*bpp)(struct stp_image *image); + int (*width)(struct stp_image *image); + int (*height)(struct stp_image *image); + void (*get_row)(struct stp_image *image, + unsigned char *data, int row); + const char *(*get_appname)(struct stp_image *image); + void (*progress_init)(struct stp_image *image); + void (*note_progress)(struct stp_image *image, + double current, double total); + void (*progress_conclude)(struct stp_image *image); + void *rep; + } stp_image_t; + This is an abstract data type for interfacing with the program + which created the image. + + - Function: const stp_vars_t stp_printer_get_printvars (const + stp_printer_t P) + + +File: gimpprint.info, Node: Settings functions, Next: Version functions, Prev: Printer functions, Up: Functions + +Settings functions +================== + + - Function: stp_convert_t stp_choose_colorfunc (int OUTPUT_TYPE, int + IMAGE_BPP, const unsigned char *CMAP, int *OUT_BPP, const + stp_vars_t V) + + - Function: void stp_compute_page_parameters (int PAGE_RIGHT, int + PAGE_LEFT, int PAGE_TOP, int PAGE_BOTTOM, double SCALING, int + IMAGE_WIDTH, int IMAGE_HEIGHT, stp_image_t *IMAGE, int + *ORIENTATION, int *page_width, int *PAGE_HEIGHT, int + *OUT_WIDTH, int *OUT_HEIGHT, int *LEFT, int *TOP) + + - Function: const stp_vars_t stp_default_settings (void) + + - Function: const stp_vars_t stp_maximum_settings (void) + + - Function: const stp_vars_t stp_minimum_settings (void) + + +File: gimpprint.info, Node: Version functions, Prev: Settings functions, Up: Functions + +Version functions +================= + + - Function: const char * stp_check_version (unsigned int + REQUIRED_MAJOR, + unsigned int REQUIRED_MINOR, unsigned int REQUIRED_MICRO) + + This function checks whether the version of libgimpprint that the + program is linked with is equal to the version number passed to + it. If the version is the same, the function returns `NULL'. If + any of the version numbers do not match (i.e. the library version + is too old or too new), a string containing a desription of the + difference is returned. The first error found is returned. The + function checks in the order major, minor, micro. + +Version macros +-------------- + + - Macro: GIMPPRINT_CHECK_VERSION (major,minor,micro) + This macro returns zero if the version of the libgimpprint headers + are greater or equal to the version given as an argument. It + returns nonzero if the version of the libgimpprint headers are + less than the argument. + + - Macro: GIMPPRINT_MAJOR_VERSION + + - Macro: GIMPPRINT_MINOR_VERSION + + - Macro: GIMPPRINT_MICRO_VERSION + + - Macro: GIMPPRINT_CURRENT_INTERFACE + + - Macro: GIMPPRINT_BINARY_AGE + + - Macro: GIMPPRINT_INTERFACE_AGE + + These macros are integers holding the version numbers. They should be +used for compile-time checking only. To check version numbers at +run-time, use the equivalent variables. Note that at present (4.1.x +development branch) the library interface version numbers are not used. + +Version variables +----------------- + + - Variable: const unsigned int gimpprint_major_version + + - Variable: const unsigned int gimpprint_minor_version + + - Variable: const unsigned int gimpprint_micro_version + + - Variable: const unsigned int gimpprint_current_interface + + - Variable: const unsigned int gimpprint_binary_age + + - Variable: const unsigned int gimpprint_interface_age + + These variables hold the library version numbers. Because the +version of the library may change on a system using shared libraries, +these should be used instead of the equivalent macros when checking the +library version at run-time. Note that library interface version +numbers are not used in the development branch, but are in the stable +branch. + + +File: gimpprint.info, Node: Programs, Next: Problems, Prev: Functions, Up: Top + +Programs +******** + + This chapter of the manual describes the use of some of the programs +which use the GIMP-Print library (libgimpprint). Note that there is now +a user manual in DocBook/SGML format, currently provided in HTML, +PostScript and PDF formats which is distributed with GIMP-Print. This +manual currently covers the use of the GIMP Print plugin and CUPS +drivers. + +* Menu: + +* The GIMP plugin:: The print plugin for the GIMP +* Ghostscript:: Printer driver +* CUPS:: Printer driver + + +File: gimpprint.info, Node: The GIMP plugin, Next: Ghostscript, Prev: Programs, Up: Programs + +The GIMP Print plugin +===================== + + The GIMP Print plugin is the printing facility for the GNU Image +Manipulation Program(1). This section examines the features offered by +the Print plugin. + + The main window is divided into five panes: + +Preview +------- + + The Preview pane contains a positioning widget that allows +interactively positioning the output on the page. It contains an outer +border, representing the sheet of paper; an inner border, representing +the printable area of the printer; an arrow, pointing to the top of the +page (the end that's fed into the printer); and a black rectangle, +representing the position of the image on the page. The image can be +moved around on the paper. When the first (left) button is used, the +image is moved in screen pixels; when any other button is used, the +image is moved in points(2). The arrow resizes depending upon the +media size chosen; the shaft of the arrow is always equal to one inch +on the output. + +[Figure not available in Info format] + +Printer Settings +---------------- + + The Printer Settings pane contains a dropdown menu for selecting a +printer to print to. There is a special `printer' named `File' that +allows you to choose a file to print to, rather than a printer queue. +The Setup box to the right allows specification of a printer type, a +PPD file(3), and the command to be used to print. Each distinct +printer in the Printer list can have different settings applied to it. +Below that is a combo box allowing choice of media size. The choices +are constrained to those that the printer supports. Below that are +dropdown menus for choosing media type (what kind of paper), media +source (what input tray), ink type, and resolution. All of these +settings are printer-specific. + +[Figure not available in Info format] + +Position +-------- + + The Position pane contains various widgets to place the image on the +paper. These widgets work in conjunction with the Preview pane. At the +top of the pane is a button to center the image on the paper (not on the +printable area), and on either side buttons to center vertically and +horizontally. Below these are four boxes that allow entry of the left, +top, right, and bottom of the image. These positions are relative to +the top left of the paper(4). There are two additional boxes that +allow specification of the right margin and bottom margin if you +prefer; these are relative to the bottom right corner of the paper. +Any of these may have values entered into them; the preview image will +be moved appropriately. + + *Note*: These entries do not resize the image. + + Finally, there is a pick box for orientation (landscape or portrait). +There is an `Auto' mode that picks the orientation that yields the +orientation that best matches that of the image to be printed. + +Scaling +------- + + The Scaling pane contains a slider that allows scaling of the image. +The image can be scaled in either percent of the printable area (*not* +the page in this case) or pixels per inch (PPI) via a radio button +below the slider. PPI allows matching image resolution to printer +resolution. The image may be scaled using either method to between 5 +and 100% of the imageable area. It is not possible to crop with the +Print plugin. In Percent mode, the image is scaled so that neither +axis will be longer than the percent of the printable area specified. +For example, if you print an image at 20%, it will be possible to tile +the image 5 times on one axis and at least 5 times on the other. To +the right of the radio button is a button called Set Image Scale. This +sets the scaling to PPI, and sets the resolution as closely as possible +to the resolution stored in the image. To the right of the Set Image +Scale button are two boxes that allow entry of width and height of the +image. These set the scaling mode to PPI. Specifying one +automatically sets the other, and the image is repositioned as needed +to prevent it from falling off the edge of the page. + + To its right is a button group that allows choosing English (inch) +units or metric (centimeter) units. + +Image Settings +-------------- + + The Image Settings pane allows choice of Line Art, Solid Colors, or +Photograph image type. Line art or Solid Colors should be used for +graphics containing mostly solid areas of color. They're very similar +to each other. Photograph mode dithers more slowly, but produces more +accurate colors. To the right of these three radio buttons is a button +called Adjust Color. This pops up a new window that controls various +output quality settings. That will be described separately. Finally, +there is a choice of Black and White, Color and Monochrome output. +Monochrome output can be used to print absolute black and white very +quickly. + +Adjust Output +............. + + The Adjust Output button button pops up a non-modal dialog that +allows adjustment of various parameters related to the print quality. +These are independent of the controls within the GIMP itself and only +affect the print. + +[Figure not available in Info format] + + At the top of the window is a thumbnail of the image that changes to +reflect the color settings of the image. This enables you to get an +idea of how the image will print out as you adjust settings. + + Below that there are eight sliders: + +_Brightness_ + (0-2.0, default 1.0) Adjust the brightness of the image. + +_Contrast_ + (0-4.0, default 1.0) Adjust the output contrast. + +_Cyan, Magenta, Yellow_ + (0-4.0, default 1.0) Adjust the cyan, magenta, and yellow in the + output. These should not normally need to be adjusted very much; + even very small adjustments can go quite a long way to restoring + color balance. + +_Saturation_ + (0-9.0, default 1.0) Adjust the color brilliance (saturation) of + the output. Saturation of 0 means pure gray scale, with no color. + Saturation of 9.0 will make just about anything but pure grays + brilliantly colored. + +_Density_ + (0.1-2.0, default 1.0) Adjust the density (amount of ink) in the + print. The density is automatically corrected for the particular + printer, resolution, and in some cases paper choices. If solid + black in the input is not solid in the print, the density needs to + be increased; if there is excessive ink bleed-through and muddy + dark colors, the density should be decreased. + + *Note*: the density will not increase beyond a certain amount no + matter what the slider is set to. + +_Gamma_ + (0.1-4.0, default 1.0) Adjust the output gamma. The gamma value is + automatically corrected for the choice of printer; this is used if + you believe the automatic setting is incorrect. + +Dither Algorithm +................ + + There is also a selection box for the dither algorithm to be used in +the pop-up dialog. There are currently seven choices: + +_Adaptive Hybrid_ + Adaptive Hybrid usually yields the best output quality; it chooses + a modified Floyd-Steinberg error diffusion algorithm or ordered + dithering depending upon the image characteristics. + +_Ordered_ + Ordered uses a pure ordered dither. It generally yields excellent + quality for simple black and white or four color printers without + variable drop size or drop modulation; it is not recommended if + high quality is desired on six color printers. It is considerably + faster than Adaptive Hybrid. + +_Fast_ + Fast also uses a pure ordered dither, but uses a very simple black + model and makes no attempt to handle multi-level (6-color, + variable drop size, or drop modulation) at all cleanly. It is + substantially faster than Ordered dither. The quality tends to be + quite poor except on simple four color printers. On three color + printers, quality is probably competitive with anything else. + +_Very Fast_ + Very Fast is similar to Fast, except that it uses a very simple + dither matrix that can be looked up much more quickly than the + matrix used in the Fast dither. For simple pure black and white + images dominated by horizontal and vertical lines, this may + actually yield the best results; for other types of image, the + quality will be poor. + +_Adaptive Random_ + Adaptive Random is similar to Adaptive Hybrid, except that the + modifications to the Floyd-Steinberg algorithm are slightly + different. This is slower than Adaptive Hybrid on most systems. + For some images the quality may be better than Adaptive Hybrid, + but generally Adaptive Hybrid should yield slightly superior + images. + +_Hybrid Floyd-Steinberg_ + Hybrid Floyd-Steinberg uses the modified Floyd-Steinberg algorithm + of Adaptive Hybrid on the entire image. Generally, the results + are poor in pale regions. + +_Random Floyd-Steinberg_ + Random Floyd-Steinberg uses the modified Floyd-Steinberg algorithm + of Adaptive Random on the entire image. Generally, the results + are poor in pale regions. + +Action Buttons +-------------- + + The last pane contains four action buttons: + +_Print and Save Settings_ + Immediately print the image (or, if the File printer is chosen, + display a file selection window to pick the output file), and save + all current settings for all printers. + +_Save Settings_ + Immediately save the settings, and continue working in the Print + plugin. + +_Print_ + Immediately print the image (or, if the `File' printer is chosen, + display a file selection window to pick the output file), but do + not save settings. + +_Cancel_ + Immediately quit without saving settings or printing. + + ---------- Footnotes ---------- + + (1) `http://www.gimp.org' + + (2) The output resolution of the plugin. + + (3) For Postscript printers. + + (4) Again, that's relative to the paper corner, not the printable +area, which is usually smaller. + + +File: gimpprint.info, Node: Ghostscript, Next: CUPS, Prev: The GIMP plugin, Up: Programs + +Ghostscript driver +================== + + +File: gimpprint.info, Node: CUPS, Prev: Ghostscript, Up: Programs + +CUPS driver +=========== + + +File: gimpprint.info, Node: Problems, Next: Appendices, Prev: Programs, Up: Top + +Reporting Bugs +************** + + If you find a bug in GIMP-Print or have any suggestions for +modification or improvement, please send electronic mail to the +GIMP-Print bug reporting address (1). Include the version number, +which you can find by running `gimpprint-config --version'. Also +include in your message the output that the program produced and the +output you expected, if applicable, otherwise the best description of +the problem that you can provide. + + If you have other questions, comments or suggestions about +GIMP-Print, contact the developers via electronic mail to the +GIMP-Print mailing list (2). They will try to help you out, although +they may not have time to fix your problems. + + ---------- Footnotes ---------- + + (1) <gimp-print-devel@lists.sourceforge.net> + + (2) <gimp-print-devel@lists.sourceforge.net> + + +File: gimpprint.info, Node: Appendices, Next: Data Type and Variable Index, Prev: Problems, Up: Top + +Appendices +********** + +* Menu: + +* Dithering:: Dither algorithms. +* Weaving:: Weaving algorithms. +* ESC/P2:: Epson ESC/P2 printer control language. +* New Printer:: Adding a new printer to libgimpprint. + + +File: gimpprint.info, Node: Dithering, Next: Weaving, Prev: Appendices, Up: Appendices + +Dithering +********* + + The dithering code in `print-dither.c' attempts to reproduce various +shades of gray (or all colors) from only a few different inks (black, +cyan, magenta, yellow, and sometimes light cyan and light magenta). +The dots can't vary in darkness or size (except for certain special +printers), and so we need to lay down a certain fraction of dots to +represent each distinct level. + + This sounds straightforward; in practice, it isn't. Completely +random distribution of dots (simple probabilistic dithering) would +create grainy clumps and light spots. The smoothest pattern results +from an equidistant spacing of dots. Approximating this requires +sophisticated algorithms. We have two dithering algorithms, an ordered +dither algorithm that uses a grid (matrix) to decide whether to print, +and a modified Floyd-Steinberg error diffusion algorithm that uses a +grid in a slightly different way. + + We currently have three dithering functions: + + 1. `dither_fastblack' produces pure black or white from a pre-dithered + input. This is used for two purposes: for printing pure black and + white very quickly (e. g. text), and for printing pre-screened + monochrome output that was rasterized externally. + + 2. `dither_black' produces black from grayscale input. The new + dither_black can produce either a single or multiple levels of + black, for printers supporting variable dot size. + + 3. `dither_cmyk' produces 3, 4, 5, 6, or 7 color output (CMY, CMYK, + CcMmYK, CcMmYy, CcMmYyK, or any variants). The new routine can + handle single or multiple levels of each color. + + There is a choice of dithering algorithms. Four of them are based +on a basic error diffusion, with a few tweaks of my own. The other one +is `ordered'. However, they all share the basic operation in common. +First, the algorithm picks what kind of dot (if there are multiple dot +sizes and/or tones that may be picked) is the candidate to be printed. +This decision is made based on the darkness at the point being dithered. +Then, it decides whether the dot will be printed at all. What this is +based on depends upon which algorithm family we use. This is all +described in more detail below. + + Ordered dithering works by comparing the value at a given point with +the value of a tiled matrix. If the value at the point is greater than +the value in the matrix, the dot is printed. The matrix should consist +of a set of evenly spaced points between 0 and the upper limit. The +choice of matrix is very important for print quality. A good dither +matrix will emphasize high frequency components, which distributes dots +evenly with a minimum of clumping. The matrices used here are all +simple matrices that are expanded recursively to create larger matrices +with the same kind of even point distribution. This is described below. + + Note that it is important to use different matrices for the two +sub-operations, because otherwise the choice about whether to print and +the choice of dot size will be correlated. The usual result is that the +print is either too dark or too light, but there can be other problems. + + Ordered dithering works quite well on single dot size, four color +printers. It has not been well tested on four color, variable dot size +printers. It should be avoided on six color printers. + + Error diffusion works by taking the output error at a given pixel and +"diffusing" it into surrounding pixels. Output error is the difference +between the amount of ink output and the input level at each pixel. +For simple printers, with one or four ink colors and only one dot size, +the amount of ink output is either 65536 (i. e. full output) or 0 (no +output). The difference between this and the input level is the error. +Normal error diffusion adds part of this error to the adjoining pixels +in the next column and the next row (the algorithm simply scans each +row in turn, never backing up). The error adds up until it reaches a +threshold (half of the full output level, or 32768), at which point a +dot is output, the output is subtracted from the current value, and the +(now negative) error is diffused similarly. + + Error diffusion works quite well in general, but it tends to generate +artifacts which usually appear as worm-like lines or areas of anomalous +density. I have devised some ways, as described below, of ameliorating +these artifacts. + + There are two sub-classes of error diffusion that we use here, +`random' and `hybrid'. One of the techniques that we use to ameliorate +the artifacts is to use a fuzzy threshold rather than the hard +threshold of half of the output level. Random error diffusion uses a +pseudo-random number to perturb the threshold, while hybrid error +diffusion uses a matrix. Hybrid error diffusion worked very poorly in +3.1.3, and I couldn't figure out why until I found a bug. It now works +very well. + + There is one additional variant (on both sub-classes), called +`adaptive hybrid' and `adaptive random'. The adaptive variant takes +advantage of the fact that the patterns that ordered dithering create +are less visible at very low densities, while the artifacts created by +error diffusion are more objectionable at low densities. At low +densities, therefore, it uses ordered dithering; at higher densities it +uses error diffusion. + + Handling multiple output levels makes life a bit more complicated. +In principle, it shouldn't be much harder: simply figure out what the +ratio between the available output levels is and have multiple +thresholds. In practice, getting these right involves a lot of trial +and error. The other thing that's important is to maximize the number +of dots that have some ink. This will reduce the amount of speckling. +More on this later. + + The next question: how do we handle black when printing in color? +Black ink is much darker than colored inks. It's possible to produce +black by adding some mixture of cyan, magenta, and yellow--in +principle. In practice, the black really isn't very black, and +different inks and different papers will produce different color casts. +However, by using CMY to produce gray, we can output a lot more dots! +This makes for a much smoother image. What's more, one cyan, one +magenta, and one yellow dot produce less darkness than one black dot, +so we're outputting that many more dots. Better yet, with 6 or 7 color +printers, we have to output even more light ink dots. So Epson Stylus +Photo printers can produce really smooth grays--if we do everything +right. The right idea is to use CMY at lower black levels, and +gradually mix in black as the overall amount of ink increases, so the +black dots don't really become visible within the ink mass. + + Variable dot sizes are handled by dividing the range between 0 and +65536 into segments. Each segment can either represent a range in +which all of one kind of ink (color and/or dot size) is used, with +varying amounts of ink, or a transition region between inks, in which +equal numbers of dots are printed but the amount of each ink will be +adjusted throughout the range. Each range is represented by four +numbers: + + 1. bottom of the range + + 2. top of the range + + 3. value of the lighter ink + + 4. value of the darker ink + + In addition, the bit patterns and which type of ink are also +represented, but they don't affect the actual algorithm. + + As mentioned above, the basic algorithm is the same whether we use +ordered dither or error diffusion. We perform the following steps on +each color of each pixel: + + 1. Compute the value of the particular color we're printing. This + isn't usually the pure CMY value; it's adjusted to improve + saturation and to limit the use of black in light toned regions + (to avoid speckling). + + 2. Find the range containing this value. + + 3. Compute where this value lies within the range. We scale the + endpoints between 0 and 65536 for this purpose. So for example, + if the bottom of the range is 10,000 and the top of the range is + 20,000, and the value is 12,500, we're 1/4 of the way between the + bottom and the top of the range, so our scale point is 16384. + + 4. Compute the "virtual value". The virtual value is the distance + between the value of the lighter and the value of the darker ink. + So if the value of the light ink is 32768 and the dark ink is + 65536, we compute a virtual value scaled appropriately between + these two values, which is 40960 in this case. + + 5. Using either error diffusion or ordered dither, the standard + threshold is 1/2 of the value (20480 in this case). Using ordered + dither, we want to compute a value between 0 and 40960 that we + will compare the input value against to decide whether to print. + Using pure error diffusion, we would compare the accumulated error + against 20480 to decide whether to print. In practice, we use the + same matrix method to decide whether to print. The correct amount + of ink will be printed this way, but we minimize the squiggly + lines characteristic of error diffusion by dithering the threshold + in this fashion. A future enhancement will allow us to control + the amount of dithering applied to the threshold. + + The matrices were generated by Thomas Tonino <<ttonino@bio.vu.nl>> +with an algorithm of his devising. The algorithm is designed to +maximize the spacing between dots at any given density by searching the +matrix for holes and placing a dot in the largest available hole. It +requires careful selection of initial points to achieve good results, +and is very time consuming. For best results, a different matrix must +be used for modes with 2:1 aspect ratio (e.g. 1440x720) than for 1:1 +(e. g. 720x720). It is essential with any of these matrices that every +point be used. Skipping points generates low-frequency noise. + + It's essential to use different matrices for deciding whether to +print and for deciding what color (dark or light) to print. This +should be obvious; the decision about whether to print at all should be +as independent as possible from the decision about what color to print, +because any bias will result in excess light or dark ink being printed, +shifting the tonal balance. We actually use the same matrices, but we +shift them vertically and horizontally. Assuming that the matrices are +not self-correlated, this will yield good results. + + The ranges are computed from a list of ink values (between 0 and 1 +for each possible combination of dot size and ink tone, where the value +represents the darkness of the ink) and the desired maximum density of +the ink. This is done in dither_set_ranges, and needs more +documentation. + + I stated earlier that I've tweaked the basic error diffusion +algorithm. Here's what I've done to improve it: + + 1. We use a variable threshold to decide when to print, as discussed + above. This does two things for us: it reduces the slightly + squiggly diagonal lines that are the mark of error diffusion; and + it allows us to lay down some ink even in very light areas near + the edge of the image. The squiggly lines that error diffusion + algorithms tend to generate are caused by the gradual accumulation + of error. This error is partially added horizontally and + partially vertically. The horizontal accumulation results in a + dot eventually being printed. The vertical accumulation results + in a dot getting laid down in roughly the same horizontal position + in the next row. The diagonal squigglies result from the error + being added to pixels one forward and one below the current pixel; + these lines slope from the top right to the bottom left of the + image. + + Error diffusion also results in pale areas being completely white + near the top left of the image (the origin of the printing + coordinates). This is because enough error has to accumulate for + anything at all to get printed. In very pale areas it takes quite + a long time to build up anything printable at all; this results in + the bare spots. + + Randomizing the threshold somewhat breaks up the diagonals to some + degree by randomizing the exact location that the accumulated + output crosses the threshold. It reduces the false white areas by + allowing some dots to be printed even when the accumulated output + level is very low. It doesn't result in excess ink because the + full output level is still subtracted and diffused. + + Excessive randomization leads to blobs at high densities. + Therefore, as the density increases, the degree of randomization + decreases. + + 2. Alternating scan direction between rows (first row is scanned left + to right, second is scanned right to left, and so on). This also + helps break up white areas, and it also seems to break up + squigglies a bit. Furthermore, it eliminates directional biases + in the horizontal direction. This isn't necessary for ordered + dither, but it doesn't hurt either. + + 3. Diffusing the error into more pixels. Instead of diffusing the + entire error into (X+1, Y) and (X, Y+1), we diffuse it into (X+1, + Y), (X+K, Y+1), (X, Y+1), (X-K, Y+1) where K depends upon the + output level (it never exceeds about 10 dots, and is greater at + higher output levels). This really reduces squigglies and + graininess. The amount of this spread can be controlled; for line + art, it should be less than for photographs (of course, line art + doesn't usually contain much light color, but the *error* value + can be small in places!) In addition to requiring more + computation, a wide ink spread results in patterning at high dot + densities (note that the dot density can be high even in fairly + pale regions if multiple dot sizes are in use). + + 4. Don't lay down any colored ink if we're laying down black ink. + There's no point; the colored ink won't show. We still pretend + that we did for purposes of error diffusion (otherwise excessive + error will build up, and will take a long time to clear, resulting + in heavy bleeding of ink into surrounding areas, which is very + ugly indeed), but we don't bother wasting the ink. How well this + will do with variable dot size remains to be seen. + + 5. Oversampling. This is how to print 1440x720 with Epson Stylus + printers. Printing full density at 1440x720 will result in excess + ink being laid down. The trick is to print only every other dot. + We still compute the error as though we printed every dot. It + turns out that randomizing which dots are printed results in very + speckled output. This can be taken too far; oversampling at + 1440x1440 or 1440x2880 virtual resolution results in other + problems. However, at present 1440x1440 (which is more accurately + called "1440x720 enhanced", as the Epson printers cannot print + 1440 rows per inch) does quite well, although it's slow. + + What about multiple output levels? For 6 and 7 color printers, +simply using different threshold levels has a problem: the pale inks +have trouble being seen when a lot of darker ink is being printed. So +rather than just using the output level of the particular color to +decide which ink to print, we look at the total density (sum of all +output levels). If the density's high enough, we prefer to use the +dark ink. Speckling is less visible when there's a lot of ink, anyway. +I haven't yet figured out what to do for multiple levels of one color. + + You'll note that I haven't quoted a single source on color or +printing theory. I simply did all of this empirically. + + There are various other tricks to reduce speckling. One that I've +seen is to reduce the amount of ink printed in regions where one color +(particularly cyan, which is perceived as the darkest) is very pale. +This does reduce speckling all right, but it also results in strange +tonal curves and weird (to my eye) colors. + + Before any dither routine is used, `init_dither()' must be called. +This takes three arguments: the input width (number of pixels in the +input), the output width (number of pixels in the output), and a +`vars_t' structure containing the parameters for the print job. + + `init_dither()' returns a pointer to an opaque object representing +the dither. This object is passed as the first argument to all of the +dither-related routines. + + After a page is fully dithered, `free_dither()' must be called to +free the dither object and perform any cleanup. In the future, this may +do more (such as flush output). This arrangement permits using these +routines with programs that create multiple output pages, such as +GhostScript. + + The dithering routines themselves have a number of control knobs that +control internal aspects of the dithering process. These knobs are +accessible via a number of functions that can be called after +`init_dither()'. + + * `dither_set_density()' takes a double between 0 and 1 representing + the desired ink density for printing solid colors. This is used + in a number of places in the dithering routine to make decisions. + + * `dither_set_black_density()' takes a double between 0 and 1 + representing the desired ink density for printing black ink in + color printing. This is used to balance black against color ink. + By default, this is equal to the density set by + `dither_set_density()'. By setting it higher, more black ink will + be printed. For example, if the base density is .4 and the black + density is .8, twice as much black ink will be printed as would + otherwise be called for. + + This is not used when printing in monochrome. When printing + monochrome, the base density (`dither_set_density') should be + adjusted appropriately. + + * `dither_set_ink_budget()' takes an unsigned number representing the + most ink that may be deposited at a given point. This number is + arbitrary; the limit is computed by summing the size of each ink + dot, which is supplied as a parameter in `dither_set_X_ranges'. + By default, there is no limit. + + * `dither_set_black_lower()' takes a double that should be between 0 + and 1 that represents the lowest density level at which black ink + will start to mix in with colored ink to generate grays. The + lower this is, the less density is required to use black ink. + Setting this too low will result in speckling from black dots, + particularly on 6 and 7 color printers. Setting this too high + will make it hard to get satisfactory black or may result in sharp + transition between blended colors and black. Default: 0.0468. + + It is important to note that since the density scale is never + linear (and since this value is adjusted via other things + happening during the dithering process) that this does not mean + that 95% gray will use any black ink. At this setting, there will + be no black ink used until about 50% gray. + + This only applies to color mode. + + This value should be set lower for printers capable of variable dot + size, since more dots can be laid down close to each other. + + * `dither_set_black_upper()' takes a double that should be between 0 + and 1 that represents the highest density level at which colored + inks will be mixed to create gray. Setting this too low will + result in speckly dark grays because there is not enough ink to + fill all the holes, or sharp transition between blended colors and + black if it is too close to the value of dither_set_black_upper(). + Setting this too high will result in poor black and dark tone + quality. Default: 0.5. This results in 10% and darker grays + being printed with essentially all black. + + This only applies to color mode. + + * `dither_set_black_levels()' takes three doubles that represent the + amount of cyan, magenta, and yellow respectively that are blended + to create gray. The defaults are 1.0 for each, which is probably + too low for most printers. These values are adjusted to create a + good gray balance. Setting these too low will result in pale + light and midtone grays, with a sharp transition to darker tones + as black mixes in. Setting them too high will result in overly + dark grays and use of too much ink, possibly creating + bleed-through. + + This only applies to color mode. + + * `dither_set_randomizers()' takes four integer values representing + the degree of randomness used for cyan, magenta, yellow, and black. + This is used to allow some printing to take place in pale areas. + Zero is the most random; greater than 8 or so gives very little + randomness at all. Defaults are 0 for cyan, magenta, and yellow, + and 4 for black. Setting the value for black too low will result + in black speckling in pale areas. Setting values too high will + result in pale areas getting no ink at all. + + This currently only applies to single dot size in color and black. + It should be extended to operate in variable dot size mode, + although actually applying it correctly will be tricky. + + * `dither_set_ink_darkness()' takes three doubles representing the + contribution to perceived darkness of cyan, magenta, and yellow. + This is used to help decide when to switch between light and dark + inks in 6 and 7 color printers (with light cyan, light magenta, + and possibly light yellow). Setting these too low will result in + too much light ink being laid down, creating flat spots in the + darkness curves and bleed-through. Setting them too high will + result in dark ink being used in pale areas, creating speckle. + The defaults are .4 for cyan, .3 for magenta, and .2 for yellow. + Dark cyan will show against yellow much more than dark magenta + will show against cyan, since the cyan appears much darker than + the yellow. + + * `dither_set_light_inks()' takes three doubles between 0 and 1 + representing the ratio in darkness between the light and dark + versions of the inks. Setting these too low will result in too + much dark ink being used in pale areas, creating speckling, while + setting them too high will result in very smooth texture but too + much use of light ink, resulting in flat spots in the density + curves and ink bleed-through. There are no defaults. Any light + ink specified as zero indicates that there is no light ink for + that color. + + This only applies to 6 and 7 color printers in single dot size + color mode, and only to those inks which have light versions + (usually cyan and magenta). + + * `dither_set_ink_spread()' takes a small integer representing the + amount of ink spread in the dither. Larger numbers mean less + spread. Larger values are appropriate for line art and solid + tones; they will yield sharper transitions but more dither + artifacts. Smaller values are more appropriate for photos. They + will reduce resolution and sharpness but reduce dither artifacts + up to a point. A value of 16 or higher implies minimum ink spread + at any resolution no matter what the overdensity. A value of 14 + is typical for photos on single dot size, 6 color printers. For 4 + color printers, subtract 1 (more spread; the dots are farther + apart). For variable dot size printers, add 1 (more small dots + are printed; less spread is desirable). + + * `dither_set_adaptive_divisor()' takes a float representing the + transition point between error diffusion and ordered dither if + adaptive dithering is used. The float is a fraction of the + printing density. For example, if you wish the transition to be + at 1/4 of the maximum density (which works well on simple 4-color + printers), you would pass .25 here. With six colors and/or with + multiple dot sizes, the values should be set lower. + + * `dither_set_transition()' takes a float representing the exponent + of the transition curve between light and dark inks/dot sizes. A + value less than 1 (typical when using error diffusion) mixes in + less dark ink/small dots at lower ends of the range, to reduce + speckling. When using ordered dithering, this must be set to 1. + + * `dither_set_X_ranges_simple' (X=`c', `m', `y', or `k') describes + the ink choices available for each color. This is useful in + typical cases where a four color printer with variable dot sizes + is in use. It is passed an array of doubles between (0, 1] + representing the relative darkness of each dot size. The dot + sizes are assigned bit patterns (and ink quantities, see + `dither_set_ink_budget()' above) from 1 to the number of levels. + This also requires a density, which is the desired density for this + color. This density need not equal the density specified in + `dither_set_density()'. Setting it lower will tend to print more + dark ink (because the curves are calculated for this color + assuming a lower density than is actually supplied). + + * `dither_set_X_ranges' (X=`c', `m', `y', or `k') describes in a + more general way the ink choices available for each color. For + each possible ink choice, a bit pattern, dot size, value (i. e. + relative darkness), and whether the ink is the dark or light + variant ink is specified. + + --Robert Krawitz <<rlk@alum.mit.edu>> May 8, 2000 + + +File: gimpprint.info, Node: Weaving, Next: ESC/P2, Prev: Dithering, Up: Appendices + +Weaving for inkjet printers +*************************** + +by Charles Briscoe-Smith and Robert Krawitz. + +* Menu: + +* Weaving introduction:: Just what is weaving? +* Weaving algorithms:: How to weave. + |