Skip to content

Commit 7378c22

Browse files
authored
Ghostscript filters (gsto...): Introduce cupsHalftoneType dithering algorithms (#642)
- Added new dithering (halftone) algorithms in addition to the default Ghostscript one - Controlled either with `halftone-type` job option or `cupsHalftoneType` PPD option - Stochastic algorithm is implemented in `stocht.ps` Ghostscript library, just include it if cupsHalftoneType is set to yes/true/on/stochastic - foo2zjs algorithm is PostScript code taken from foo2zjs-pstops (don't know the name of the algorithm) - Added bi-level threshold support, similar to pdftoraster implementation
1 parent acbe36d commit 7378c22

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

filter/gstoraster.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,14 @@ typedef enum {
6464
OUTPUT_FORMAT_PXL
6565
} OutFormatType;
6666

67+
typedef enum
68+
{
69+
HALFTONE_DEFAULT,
70+
HALFTONE_STOCHASTIC,
71+
HALFTONE_FOO2ZJS,
72+
HALFTONE_BI_LEVEL
73+
} cups_halftone_type_t;
74+
6775
#ifdef CUPS_RASTER_SYNCv1
6876
typedef cups_page_header2_t gs_page_header;
6977
#else
@@ -647,6 +655,8 @@ main (int argc, char **argv, char *envp[])
647655
struct sigaction sa;
648656
cm_calibration_t cm_calibrate;
649657
int pxlcolor = 1;
658+
cups_halftone_type_t halftonetype = HALFTONE_DEFAULT;
659+
char *halftone_tmp = NULL;
650660
#ifdef HAVE_CUPS_1_7
651661
int pwgraster = 0;
652662
ppd_attr_t *attr;
@@ -976,6 +986,35 @@ main (int argc, char **argv, char *envp[])
976986
cupsArrayAdd(gs_args, strdup(tmpstr));
977987
}
978988

989+
if ((t = cupsGetOption("cupsHalftoneType", num_options, options)) != NULL ||
990+
(t = cupsGetOption("halftone-type", num_options, options)) != NULL)
991+
halftone_tmp = t;
992+
else if (ppd && (attr = ppdFindAttr(ppd, "DefaultcupsHalftoneType", NULL)) != NULL)
993+
halftone_tmp = attr->value;
994+
995+
if (halftone_tmp) {
996+
if (!strcasecmp(halftone_tmp, "true") || !strcasecmp(halftone_tmp, "on") ||
997+
!strcasecmp(halftone_tmp, "yes") || !strcasecmp(halftone_tmp, "stochastic"))
998+
halftonetype = HALFTONE_STOCHASTIC;
999+
else if (!strcasecmp(halftone_tmp, "foo2zjs"))
1000+
halftonetype = HALFTONE_FOO2ZJS;
1001+
else if (!strcasecmp(halftone_tmp, "bi-level"))
1002+
halftonetype = HALFTONE_BI_LEVEL;
1003+
}
1004+
1005+
/* For bi-level type, also check print-color-mode, the way it is
1006+
handled by Poppler pwgtoraster/pdftoraster/pclmtoraster utilities. */
1007+
if ((t = cupsGetOption("print-color-mode", num_options, options)) != NULL &&
1008+
!strcasecmp(t, "bi-level"))
1009+
halftonetype = HALFTONE_BI_LEVEL;
1010+
1011+
/* Use Stochastic Halftone dithering found in GhostScript stocht.ps library file.
1012+
It is activated automatically. */
1013+
if (halftonetype == HALFTONE_STOCHASTIC) {
1014+
fprintf(stderr, "DEBUG: Ghostscript using Stochastic Halftone dithering.\n");
1015+
cupsArrayAdd(gs_args, strdup("stocht.ps"));
1016+
}
1017+
9791018
/* Switch to taking PostScript commands on the Ghostscript command line */
9801019
cupsArrayAdd(gs_args, strdup("-c"));
9811020

@@ -1021,6 +1060,56 @@ main (int argc, char **argv, char *envp[])
10211060
} else
10221061
fprintf(stderr, "DEBUG: Ghostscript using Any-Part-of-Pixel method to fill paths.\n");
10231062

1063+
/* Use halftone dithering algorithm found in foo2zjs-pstops file */
1064+
if (halftonetype == HALFTONE_FOO2ZJS) {
1065+
fprintf(stderr, "DEBUG: Ghostscript using foo2zjs Halftone dithering.\n");
1066+
cupsArrayAdd(gs_args, strdup("/SpotDot { 180 mul cos exch 180 mul cos add 2 div } def\
1067+
<<\
1068+
/HalftoneType 5\
1069+
/Cyan <<\
1070+
/HalftoneType 1\
1071+
/AccurateScreens true\
1072+
/Frequency 150\
1073+
/Angle 105\
1074+
/SpotFunction /SpotDot load\
1075+
>>\
1076+
/Magenta <<\
1077+
/HalftoneType 1\
1078+
/AccurateScreens true\
1079+
/Frequency 150\
1080+
/Angle 165\
1081+
/SpotFunction /SpotDot load\
1082+
>>\
1083+
/Yellow <<\
1084+
/HalftoneType 1\
1085+
/AccurateScreens true\
1086+
/Frequency 150\
1087+
/Angle 30\
1088+
/SpotFunction /SpotDot load\
1089+
>>\
1090+
/Black <<\
1091+
/HalftoneType 1\
1092+
/AccurateScreens true\
1093+
/Frequency 150\
1094+
/Angle 45\
1095+
/SpotFunction /SpotDot load\
1096+
>>\
1097+
/Default <<\
1098+
/HalftoneType 1\
1099+
/AccurateScreens true\
1100+
/Frequency 150\
1101+
/Angle 37\
1102+
/SpotFunction /SpotDot load\
1103+
>>\
1104+
>> /Default exch /Halftone defineresource sethalftone"));
1105+
}
1106+
1107+
/* Use simple threshold (bi-level) halftone algorithm */
1108+
if (halftonetype == HALFTONE_BI_LEVEL) {
1109+
fprintf(stderr, "DEBUG: Ghostscript using Bi-Level Halftone dithering.\n");
1110+
cupsArrayAdd(gs_args, strdup("{ .5 gt { 1 } { 0 } ifelse} settransfer"));
1111+
}
1112+
10241113
/* Mark the end of PostScript commands supplied on the Ghostscript command
10251114
line (with the "-c" option), so that we can supply the input file name */
10261115
cupsArrayAdd(gs_args, strdup("-f"));

0 commit comments

Comments
 (0)