|
CUPS rastertoql filter
1.0.4
Filter for the Brother QL family of label printers
|
A collection of half tone algorithems. More...
Macros | |
| #define | RIGHTWARD 0 |
| #define | DOWNLEFTWARD 1 |
| #define | DOWNWARD 2 |
| #define | DOWNRIGHTWARD 3 |
Functions | |
| void | sliding_halftone_get (struct halftone_converter *cnv) |
| void | sliding_halftone_put (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) |
| static signed int | quantize_grey_pixel (const struct halftone_converter *cnv, signed int v) |
| static signed short | diffuse (signed int pix_in, signed int q_err, signed int factor) |
| static signed int | random_number_create (void) |
| static void | error_diffusion_randomness_calc (signed int error, signed int random[4]) |
| static void | error_diffusion_right_to_left (struct halftone_converter *cnv) |
| static void | error_diffusion_left_to_right (struct halftone_converter *cnv) |
| void | halftone_line_with_error_diffusion (struct halftone_converter *cnv) |
| void | halftone_line_ordered (struct halftone_converter *cnv) |
| void | halftone_line_no_dither (struct halftone_converter *cnv) |
A collection of half tone algorithems.
This is a collection of functions to run half-tone algorithms on the raster data prior it is printed.
Each algorithm needs two lines of input data with the raster data. They are always processed at once and - important - gets both changed by the algorithms. Raw raster data is expected in shades of grey and in the format of a signed short per pixel. move_in_next_line() does this required conversation (unsigned char to signed short).
After the algorithm has processed the lines, the first line can be printed. Based on the signed short pixel value result, the printer driver needs to chose a corresponding print pattern ("to dot, or not to dot?").
After that, the second line from the previous call needs to be the first line in the next call, while the second line then contains fresh data from the next raw raster line. You can think of the algorithm slides from the top to the bottom of the raster. move_in_next_line() does this required line swap.
So: to start at the top of the image, you need both lines filled with data, run the half tone algorithm, then print the top line from the sliding half tone structure. Then you are in the flow until you hit the bottom line of your image. In order to process and print it, you need to fill an empty line (via move_in_empty_line()), run the half tone algorithm and again print the top line from the sliding half tone structure. Then you're done.
| #define DOWNLEFTWARD 1 |
Value for the downleftward pixel. Just to avoid anonymous numbers
| #define DOWNRIGHTWARD 3 |
Value for the downrightward pixel. Just to avoid anonymous numbers
| #define DOWNWARD 2 |
Value for the downward pixel. Just to avoid anonymous numbers
| #define RIGHTWARD 0 |
Value for the rightward pixel. Just to avoid anonymous numbers
|
static |
Calculate a pixel value according to "Floyd-Steinberg error diffusion" formula
| [in] | pix_in | the plain pixel to quantize |
| [in] | q_err | the quantization error |
| [in] | factor | one of the factors of the algorithm |
Calculation done here is: result = pix_in + ((q_err * factor) / 16)
|
static |
Apply error diffusion from left to right
| [in,out] | cnv | The converter structure to use |
------------------> processing direction | 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)
|
static |
Calculate some randomness for the error diffusion to avoid visible pattern
| [in] | error | The current quantization error |
| [out] | random | Random offset for the four surrounding pixel |
The larger the quantization error is, the larger the random offsets will be.
|
static |
Apply error diffusion from right to left
| [in,out] | cnv | The converter structure to use |
<------------------ processing direction | 7/16 * N | <-- cnv->sliding_lines[0] | 1/16 5/16 3/16 | <-- cnv->sliding_lines[1]
N previous pixel, * current pixel to process (e.g. X/Y position)
| 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.
|
static |
Return the printer's possible value for a given pixel's grey value, e.g. quantize it
| [in] | cnv | The converter structure to use |
| [in] | v | The grey value from CUPS raster or any dither algorithm |
| Upper | halftone_converter::dotval[1] if v is above halftone_converter::threshold |
| Lower | halftone_converter::dotval[0] if v is below halftone_converter::threshold |
From the Ghostscript/CUPS raster perspective:
so, with an decreasing value we get a more black pixel
|
static |
Create some random number
stdlib.h defines RAND_MAX to 2147483647 (same as INT_MAX). By substracting (RAND_MAX / 2) the result should always swing around zero with +/- (RAND_MAX / 2).
| 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 |
1.8.17