From b5bfdb4197083ceaa64470f327a49456946855a3 Mon Sep 17 00:00:00 2001 From: ValdikSS Date: Tue, 23 Jun 2026 13:17:08 +0300 Subject: [PATCH 1/2] Ghostscript filters (gsto...): remove default gamma from spot halftone By default, Ghostscript applies 0.8 exponent as a gamma curve, which makes levels a bit washed out. Remove this gamma curve by default, as it's done for genordered. --- cupsfilters/ghostscript.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cupsfilters/ghostscript.c b/cupsfilters/ghostscript.c index 3bd07dfec..0adbeff60 100644 --- a/cupsfilters/ghostscript.c +++ b/cupsfilters/ghostscript.c @@ -1920,7 +1920,7 @@ cfFilterGhostscript(int inputfd, // I - File descriptor input "cfFilterGhostscript: Ghostscript using Spot halftone (frequency=%d angle=%d dotshape=%d).\n", ht_frequency, ht_angle, shape); snprintf(tmpstr, sizeof(tmpstr), - "<< /HalftoneType 1 /Frequency %d /Angle %d /SpotFunction %s >> /Default exch /Halftone defineresource sethalftone", + "<< /HalftoneType 1 /Frequency %d /Angle %d /SpotFunction %s >> /Default exch /Halftone defineresource sethalftone { } settransfer 0.003 setsmoothness", ht_frequency, ht_angle, ht_spot_functions[shape]); cupsArrayAdd(gs_args, strdup(tmpstr)); } From dc13bb1f0bbb6e05969413d16be5ee8154a577db Mon Sep 17 00:00:00 2001 From: ValdikSS Date: Tue, 23 Jun 2026 13:44:02 +0300 Subject: [PATCH 2/2] Ghostscript filters (gsto...): add halftone gamma value halftone-type=spot[-frequency][-angle][-dotshape][-gamma] halftone-type=genordered[-frequency][-angle][-dotshape][-gamma] Gamma is a fraction of exponent value, 1-99, where 99 covers almost all levels and 1 produces very light faint image. gamma 80 = pixel ^ 0.80 --- cupsfilters/ghostscript.c | 45 ++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/cupsfilters/ghostscript.c b/cupsfilters/ghostscript.c index 0adbeff60..9e8fa8fa4 100644 --- a/cupsfilters/ghostscript.c +++ b/cupsfilters/ghostscript.c @@ -867,7 +867,7 @@ cfFilterGhostscript(int inputfd, // I - File descriptor input cf_cm_calibration_t cm_calibrate; int pxlcolor = 0; // 1 if printer is color printer otherwise 0. cups_halftone_type_t halftonetype = HALFTONE_DEFAULT; - int ht_frequency = 133, ht_angle = 45, ht_dotshape = 0; + int ht_frequency = 133, ht_angle = 45, ht_dotshape = 0, ht_gamma = 0; ipp_attribute_t *ipp_attr; cf_logfunc_t log = data->logfunc; void *ld = data->logdata; @@ -1701,7 +1701,13 @@ cfFilterGhostscript(int inputfd, // I - File descriptor input { p++; v = strtol(p, &endp, 10); - if (endp != p) ht_dotshape = (int)v; + if (endp != p) { ht_dotshape = (int)v; p = endp; } + if (*p == '-') + { + p++; + v = strtol(p, &endp, 10); + if (endp != p) ht_gamma = (int)v; + } } } } @@ -1726,7 +1732,13 @@ cfFilterGhostscript(int inputfd, // I - File descriptor input { p++; v = strtol(p, &endp, 10); - if (endp != p) ht_dotshape = (int)v; + if (endp != p) { ht_dotshape = (int)v; p = endp; } + if (*p == '-') + { + p++; + v = strtol(p, &endp, 10); + if (endp != p) ht_gamma = (int)v; + } } } } @@ -1896,13 +1908,18 @@ cfFilterGhostscript(int inputfd, // I - File descriptor input // 0=CIRCLE, 1=REDBOOK, 2=INVERTED, 3=RHOMBOID, 4=LINE_X, 5=LINE_Y, // 6=DIAMOND1, 7=DIAMOND2, 8=ROUNDSPOT */ // - if (halftonetype == HALFTONE_GENORDERED) { + if (halftonetype == HALFTONE_GENORDERED) + { + char ht_transfer[16] = {0}; + if (ht_gamma >= 1 && ht_gamma <= 99) + snprintf(ht_transfer, sizeof(ht_transfer), "0.%02d exp", ht_gamma); if (log) log(ld, CF_LOGLEVEL_DEBUG, - "cfFilterGhostscript: Ghostscript using .genordered halftone (frequency=%d angle=%d dotshape=%d).", - ht_frequency, ht_angle, ht_dotshape); + "cfFilterGhostscript: Ghostscript using .genordered halftone (frequency=%d angle=%d dotshape=%d gamma=%s).", + ht_frequency, ht_angle, ht_dotshape, + ht_transfer[0] ? ht_transfer : "default"); snprintf(tmpstr, sizeof(tmpstr), - "<< /Frequency %d /Angle %d /DotShape %d >> .genordered /Default exch /Halftone defineresource sethalftone { } settransfer 0.003 setsmoothness", - ht_frequency, ht_angle, ht_dotshape); + "<< /Frequency %d /Angle %d /DotShape %d >> .genordered /Default exch /Halftone defineresource sethalftone { %s } settransfer 0.003 setsmoothness", + ht_frequency, ht_angle, ht_dotshape, ht_transfer); cupsArrayAdd(gs_args, strdup(tmpstr)); } @@ -1914,14 +1931,18 @@ cfFilterGhostscript(int inputfd, // I - File descriptor input if (halftonetype == HALFTONE_SPOT) { int shape = ht_dotshape; + char ht_transfer[16] = {0}; if (shape < 0) shape = 0; if (shape >= HT_SPOT_FUNCTIONS_COUNT) shape = HT_SPOT_FUNCTIONS_COUNT - 1; + if (ht_gamma >= 1 && ht_gamma <= 99) + snprintf(ht_transfer, sizeof(ht_transfer), "0.%02d exp", ht_gamma); if (log) log(ld, CF_LOGLEVEL_DEBUG, - "cfFilterGhostscript: Ghostscript using Spot halftone (frequency=%d angle=%d dotshape=%d).\n", - ht_frequency, ht_angle, shape); + "cfFilterGhostscript: Ghostscript using Spot halftone (frequency=%d angle=%d dotshape=%d gamma=%s).\n", + ht_frequency, ht_angle, shape, + ht_transfer[0] ? ht_transfer : "default"); snprintf(tmpstr, sizeof(tmpstr), - "<< /HalftoneType 1 /Frequency %d /Angle %d /SpotFunction %s >> /Default exch /Halftone defineresource sethalftone { } settransfer 0.003 setsmoothness", - ht_frequency, ht_angle, ht_spot_functions[shape]); + "<< /HalftoneType 1 /Frequency %d /Angle %d /SpotFunction %s >> /Default exch /Halftone defineresource sethalftone { %s } settransfer 0.003 setsmoothness", + ht_frequency, ht_angle, ht_spot_functions[shape], ht_transfer); cupsArrayAdd(gs_args, strdup(tmpstr)); }