|
CUPS rastertoql filter
1.0.4
Filter for the Brother QL family of label printers
|
Data Structures | |
| struct | line_command |
| struct | qlrgb |
| struct | qlhsv |
| struct | halftone_converter |
| struct | ql_trim |
| struct | qldriver |
| struct | dk_roll_types |
| struct | ql_simple_command |
Macros | |
| #define | COLOUR_VAL_DARK 0x00 |
| #define | COLOUR_VAL_BRIGHT 0xff |
| #define | PRINT_DOT_VAL 0x00 |
| #define | DEFAULT_QL_LINE_SIZE 90 |
| #define | PRE_CUT_LABEL_MARGIN_SKIP_LOW_RES 35 |
| #define | PRE_CUT_LABEL_MARGIN_SKIP_HIGH_RES 70 |
Enumerations | |
| enum | printer_type { BROTHER_QL_UNKNOWN = 0, BROTHER_QL_500 = 500, BROTHER_QL_550 = 550, BROTHER_QL_560 = 560, BROTHER_QL_570 = 570, BROTHER_QL_580 = 580, BROTHER_QL_600 = 600, BROTHER_QL_650 = 650, BROTHER_QL_700 = 700, BROTHER_QL_710 = 710, BROTHER_QL_720 = 720, BROTHER_QL_800 = 800, BROTHER_QL_810 = 810, BROTHER_QL_820 = 820, BROTHER_QL_1050 = 1050, BROTHER_QL_1060 = 1060 } |
| enum | half_tone { HT_ERROR_DIFFUSION = 1, HT_ORDERED = 2, HT_NONE = 3 } |
| enum | dk_caps { DK_CAP_UNKNOWN = 0, DK_CAP_CONTINUOUS = 1, DK_CAP_DIE_CUT = 2, DK_CAP_RED = 4 } |
Functions | |
| void | sliding_halftone_get (struct halftone_converter *cnv) |
| void | sliding_halftone_put (struct halftone_converter *cnv) |
| void | halftone_line_no_dither (struct halftone_converter *cnv) |
| void | halftone_line_ordered (struct halftone_converter *cnv) |
| void | halftone_line_with_error_diffusion (struct halftone_converter *cnv) |
| void | move_in_next_line (struct halftone_converter *cnv, const unsigned char raw[cnv->pixel_count]) |
| void | move_in_empty_line (struct halftone_converter *cnv, signed short val) |
| int | cups_ql_driver_init (struct qldriver *ql) |
| int | ql_dk_information_get (struct dk_roll_types *medium, const char *name) |
| int | cups_ql_job_print (struct qldriver *ql) |
| int | cups_ql_colour_page_print (struct qldriver *ql, int first_time) |
| int | cups_ql_monochome_page_print (struct qldriver *ql, int first_time) |
| int | cups_ql_raster_header_read (struct qldriver *ql) |
| int | cups_ql_next_line_read (struct qldriver *ql, size_t sz, unsigned char buf[sz]) |
| int | ql_printer_data_send (struct qldriver *ql, const void *data, size_t count, int flush) |
| void | transform_to_monochrome (size_t input_cnt, const signed short input[input_cnt], unsigned char *data) |
| int | ql_reset (struct qldriver *ql) |
| int | ql_auto_powerdown (struct qldriver *ql, unsigned short time_out) |
| int | ql_auto_powerup (struct qldriver *ql, unsigned short mode) |
| int | ql_input_raster_crop (struct qldriver *ql) |
| int | ql_raster_limits_get (struct qldriver *ql) |
| int | ql_page_header_generate (struct qldriver *ql, int first_time) |
| int | ql_job_footer_generate (struct qldriver *ql) |
| int | ql_job_header_generate (struct qldriver *ql) |
| #define COLOUR_VAL_BRIGHT 0xff |
Value of white. The maximal value of a byte (regarding the CUPS raster)
| #define COLOUR_VAL_DARK 0x00 |
Value of black. The minimal value of a byte (regarding the CUPS raster)
| #define DEFAULT_QL_LINE_SIZE 90 |
The generic count of bytes of one line of these QL printers
| #define PRE_CUT_LABEL_MARGIN_SKIP_HIGH_RES 70 |
Amount of raster lines to skip at the top and bottom of a pre-cut label. This is a printer device requirement. It more or less defines a margin of 3 mm.
70 lines are valid for 600 DPI
| #define PRE_CUT_LABEL_MARGIN_SKIP_LOW_RES 35 |
Amount of raster lines to skip at the top and bottom of a pre-cut label. This is a printer device requirement. It more or less defines a margin of 3 mm.
35 lines are valid for 300 DPI
| #define PRINT_DOT_VAL 0x00 |
The value of a to be printed dot (regarding the internal processing)
| enum dk_caps |
| enum half_tone |
| enum printer_type |
Keep the numbers here in sync with the PPD "cupsModelNumber" entry
| int cups_ql_colour_page_print | ( | struct qldriver * | ql, |
| int | first_time | ||
| ) |
Convert the current page into the printer's wire data format
| [in] | ql | Full job description |
| [in] | first_time | '1' if called the first time of this job, '0' else |
| 0 | On success |
| -EINVAL | Unsupported raster input format |
| -ECANCELED | Termination request from outerspace |
The routine loops through all or the remaining lines of the current page and converts them into the printer's colour wire format
| int cups_ql_driver_init | ( | struct qldriver * | ql | ) |
Init required information about the printer device
| [in] | ql | Full job description |
| 0 | On success (currently always) |
| int cups_ql_job_print | ( | struct qldriver * | ql | ) |
CUPS specific document print routine
| [in] | ql | Full job description |
| 0 | On success |
| -EINVAL | Unsupported raster input format |
This function prepares the print. E.g. configure the printer according to the given CUPS raster format.
We need to check the raster header in order to have an idea, what has to be printed (monochrome versus bi-colour). We can check the medium size versus the raster size here to be able to print something.
The routine loops through all pages inside the CUPS raster file and calls the corresponding encoding routine to do the job.
-ECANCELED, because the routine itself knows how to terminate the print at the printer's side as well| int cups_ql_monochome_page_print | ( | struct qldriver * | ql, |
| int | first_time | ||
| ) |
Convert the current page into the printer's wire data format
| [in] | ql | Full job description |
| [in] | first_time | '1' if called the first time in this job, '0' else |
| 0 | On success |
| -EINVAL | Unsupported raster input format |
| -ECANCELED | Termination request from outerspace |
The routine loops through all or the remaining lines of the current page and converts them into the printer's monchrome wire format
| int cups_ql_next_line_read | ( | struct qldriver * | ql, |
| size_t | sz, | ||
| unsigned char | buf[sz] | ||
| ) |
Read in the next line from the CUPS raster
| [in,out] | ql | Full job description |
| [in] | sz | Size of bytes buf points to |
| [out] | buf | Where to store the raster data |
| 0 | On success |
| -ENODATA | Mature end of CUPS raster input data |
| int cups_ql_raster_header_read | ( | struct qldriver * | ql | ) |
Read in the next header from the CUPS raster file
| [in,out] | ql | Full job description |
| number | Header bytes read |
| 0 | on EOF, negative value on failure, 'errno' is valid in this case |
| void halftone_line_no_dither | ( | struct halftone_converter * | cnv | ) |
Quantize the top line without any half tone algorithm
| [in,out] | cnv | The converter structure to use |
http://www.visgraf.impa.br/Courses/ip00/proj/Dithering1/average_dithering.html
| void halftone_line_ordered | ( | struct halftone_converter * | cnv | ) |
Quantize the top line according to an "ordered dithering matrix"
| [in,out] | cnv | The converter structure to use |
This is a simple algorithm with a 2x2 "ordered dithering matrix":
| 1/10 3/10 | <-- cnv->sliding_lines[0] | 4/10 2/10 | <-- cnv->sliding_lines[1]
http://www.visgraf.impa.br/Courses/ip00/proj/Dithering1/ordered_dithering.html
| void halftone_line_with_error_diffusion | ( | struct halftone_converter * | cnv | ) |
Quantize the top line according to the "Floyd-Steinberg error diffusion" and distribute the error around
| [in,out] | cnv | The converter structure to use |
From: http://www.visgraf.impa.br/Courses/ip00/proj/Dithering1/floyd_steinberg_dithering.html
| N * 7/16 | <-- cnv->sliding_lines[0] | 3/16 5/16 1/16 | <-- cnv->sliding_lines[1]
N previous pixel, * current pixel to process (e.g. X/Y position)
| void move_in_empty_line | ( | struct halftone_converter * | cnv, |
| signed short | val | ||
| ) |
Move in an empty line into the process
| [in,out] | cnv | The converter structure to use |
| [in] | val | 'Empty' value (0…255) |
'Empty' means val must have a value which should not print anything. For example COLOUR_VAL_BRIGHT.
| void move_in_next_line | ( | struct halftone_converter * | cnv, |
| const unsigned char | raw[cnv->pixel_count] | ||
| ) |
Move in the next line with raw raster data into the process
| [in,out] | cnv | The converter structure to destroy |
| [in] | raw | Buffer with raw pixel data (grey scale) in bytes |
Throw away the content of the current top line, move all lines below one line up and fill the bottom line with new content from the given raw line.
Currently there are only two lines in the calculation buffer, so "moving" means "swapping" instead.
The byte based pixel data is copied into the sliding half tone structure and gets converted to signed short to be able run the half tone algorithm afterwards.
| int ql_auto_powerdown | ( | struct qldriver * | ql, |
| unsigned short | time_out | ||
| ) |
Set the printer's auto power down behaviour if it is idle
| [in] | ql | Full job description |
| [in] | time_out | Time out when idle to enter power down mode |
time_out can be:
If the printer enters the power down mode, it disconnects itself from the USB and can be re-enabled manually only with its local power button. This is a really bad idea for remote printers.
| int ql_auto_powerup | ( | struct qldriver * | ql, |
| unsigned short | mode | ||
| ) |
Set the printer's power up behaviour when connecting to external power
| [in] | ql | Full job description |
| [in] | mode | Power On mode |
mode can be:
| int ql_dk_information_get | ( | struct dk_roll_types * | medium, |
| const char * | name | ||
| ) |
Retrieve settings/information about a specific DK roll/cassette
| [out] | medium | The settings for the DK roll named by name |
| [in] | name | The DK roll name the settings should be retrieved for |
| 0 | On success, *medium is valid |
| -EINVAL | Roll with the given name not found |
DK rolls can inherit settings from other rolls. This routine walks through the table and uses the dk_roll_types::like member to re-use their settings.
| int ql_input_raster_crop | ( | struct qldriver * | ql | ) |
Crop the input raster to meet the printer's expectations/requirements
| [in] | ql | Full job description |
The printer device has some - hmm, lets it call - interesting requirements about the print data it accepts. Continuous labels are easy, but pre-cut labels aren't. In order to ensure the printer always cuts inbetween two pre-cut labels, we need to tweak the amount of lines to be print.
Read How the Filter deals with margins about details.
| int ql_job_footer_generate | ( | struct qldriver * | ql | ) |
Send the footer commands after a print job
| [in] | ql | Full job description |
Called once per print job at the end. But only:
| int ql_job_header_generate | ( | struct qldriver * | ql | ) |
Send the heading commands to setup the printer prior a print job
| [in] | ql | Full job description |
Called once per print job at the beginning
| int ql_page_header_generate | ( | struct qldriver * | ql, |
| int | first_time | ||
| ) |
| [in] | ql | Full job description |
| [in] | first_time | Flag if called the first time in a print job |
| 0 | On success |
| -ENODEV | Device seems gone (e.g. channel to the next stage is gone) |
Called once per page at the beginning
Deal with QL_FAST_PRINT/QL_QUALITY_PRINT for monochrome use case
Do the QL_QUALITY_PRINT and QL_HIGH_RESOLUTION bits depend on each other?
Deal with auto cut setting and when to cut (and if the printer has a cutter). To make it simple: only "cut at end" and "cut each" should be supported
| int ql_printer_data_send | ( | struct qldriver * | ql, |
| const void * | data, | ||
| size_t | count, | ||
| int | flush | ||
| ) |
Send data to the printer's stream
| [in,out] | ql | Full job description |
| [in] | data | Pointer to the to be sent data |
| [in] | count | Count of bytes data points to |
| [in] | flush | '1' if the stream should be flushed |
| 0 | On success |
| Negative | ERRNO from fwrite() call |
| int ql_raster_limits_get | ( | struct qldriver * | ql | ) |
| int ql_reset | ( | struct qldriver * | ql | ) |
Initialize/reset the printer
| [in] | ql | Full job description |
| 0 | On success |
| Negative | Error code from the ql_printer_data_send() call |
This command can also be used every time to terminate a current print
| void sliding_halftone_get | ( | struct halftone_converter * | cnv | ) |
Prepare the sliding line buffers
| [in,out] | cnv | The converter structure to initialiaize |
In order to run some kind of half-tone processing we need signed values per pixel which must be larger than the incoming pixels data. Incoming pixels are of type 'unsigned char' with their grey values. Due to this conversion we do not need to honor any kind of saturation while calculating the dithered output.
| void sliding_halftone_put | ( | struct halftone_converter * | cnv | ) |
Clean up image processing via sliding line buffers
| [in,out] | cnv | The converter structure to destroy |
| void transform_to_monochrome | ( | size_t | input_cnt, |
| const signed short | input[input_cnt], | ||
| unsigned char * | data | ||
| ) |
Convert an array of signed shorts into a monochrome pattern (one signed short into one bit)
| [in] | input_cnt | Count of pixel in input |
| [in] | input | Where to get the quantized input data |
| [out] | data | Where to store the converted output data |
1.8.17