Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions doc/rst/source/gmt.conf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1091,8 +1091,13 @@ PostScript Parameters
with standard fonts.

**PS_COLOR_MODEL**
Determines whether PostScript output should use **RGB**, **HSV**, **CMYK**,
or **GRAY** when specifying color [default is **rgb**]. Note if **HSV**
Determines whether PostScript output should use **RGB**, **RGBnoQUANT**,
**HSV**, **CMYK**, or **GRAY** when specifying color [default is **rgb**].
**RGBnoQUANT** uses
normal RGB colors but forces direct RGB raster output instead of indexed
images. This may increase file size and is intended for compatibility with
third-party PostScript/PDF editors that have problems with indexed images.
Note if **HSV**
is selected it does not apply to images which in that case uses **RGB**.
When selecting **GRAY**, all colors will be converted to gray scale using
YIQ (television) conversion.
Expand Down
1 change: 1 addition & 0 deletions src/gmt_defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ struct GMT_DEFAULTS {
double ps_transparency; /* Later transparency [0] */
double ps_penwidth; /* Current pen width */
unsigned int ps_color_mode; /* Postscript encoding of color [PSL_RGB | PSL_CMYK | PSL_HSV | PSL_GRAY] */
bool ps_color_no_quantization; /* Skip RGB image quantization and indexed-color output [false] */
unsigned int ps_copies; /* How man copies of each plot [>=1] [GMT4 COMPATIBILITY ONLY] */
int ps_media; /* Default paper media [25(Letter)]; negative if custom size */
unsigned int ps_orientation; /* Orientation of page [PSL_LANDSCAPE (0)] or PSL_PORTRAIT (1) */
Expand Down
25 changes: 20 additions & 5 deletions src/gmt_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -6972,6 +6972,7 @@ EXTERN_MSC void gmtinit_conf_classic (struct GMT_CTRL *GMT) {
gmtinit_load_encoding (GMT);
/* PS_COLOR_MODEL */
GMT->current.setting.ps_color_mode = PSL_RGB;
GMT->current.setting.ps_color_no_quantization = false;
/* PS_IMAGE_COMPRESS */
if (GMT->PSL) { /* Only when using PSL in this session */
#ifdef HAVE_ZLIB
Expand Down Expand Up @@ -11750,14 +11751,26 @@ unsigned int gmtlib_setparameter (struct GMT_CTRL *GMT, const char *keyword, cha
gmt_M_compat_translate ("PS_COLOR_MODEL");
break;
case GMTCASE_PS_COLOR_MODEL:
if (!strcmp (lower_value, "rgb"))
if (!strcmp (lower_value, "rgb")) {
GMT->current.setting.ps_color_mode = PSL_RGB;
else if (!strcmp (lower_value, "cmyk"))
GMT->current.setting.ps_color_no_quantization = false;
}
else if (!strcmp (lower_value, "rgbnoquant")) {
GMT->current.setting.ps_color_mode = PSL_RGB;
GMT->current.setting.ps_color_no_quantization = true;
}
else if (!strcmp (lower_value, "cmyk")) {
GMT->current.setting.ps_color_mode = PSL_CMYK;
else if (!strcmp (lower_value, "hsv"))
GMT->current.setting.ps_color_no_quantization = false;
}
else if (!strcmp (lower_value, "hsv")) {
GMT->current.setting.ps_color_mode = PSL_HSV;
else if (!strcmp (lower_value, "gray") || !strcmp (lower_value, "grey"))
GMT->current.setting.ps_color_no_quantization = false;
}
else if (!strcmp (lower_value, "gray") || !strcmp (lower_value, "grey")) {
GMT->current.setting.ps_color_mode = PSL_GRAY;
GMT->current.setting.ps_color_no_quantization = false;
}
else
error = true;
break;
Expand Down Expand Up @@ -13261,7 +13274,9 @@ char *gmtlib_getparameter (struct GMT_CTRL *GMT, const char *keyword) {
else { error = gmtinit_badvalreport (GMT, keyword); break; } /* Not recognized so give error message */
/* Intentionally fall through */
case GMTCASE_PS_COLOR_MODEL:
if (GMT->current.setting.ps_color_mode == PSL_RGB)
if (GMT->current.setting.ps_color_no_quantization)
strcpy (value, "rgbnoquant");
else if (GMT->current.setting.ps_color_mode == PSL_RGB)
strcpy (value, "rgb");
else if (GMT->current.setting.ps_color_mode == PSL_CMYK)
strcpy (value, "cmyk");
Expand Down
4 changes: 2 additions & 2 deletions src/gmt_keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ PROJ_SCALE_FACTOR # Scale factor for UTM maps
# PS Group: PostScript settings
#-------------------------------------------------------
PS_CHAR_ENCODING # Character encoding vector to use in PS plots
PS_COLOR_MODEL # Color model in use (RGB, HSV, CMYK, GRAY)
PS_COLOR_MODEL # Color model in use (RGB, RGBnoQUANT, HSV, CMYK, GRAY)
PS_DPI # The dots-pr-inch setting [obsolete - not in gmt.conf]
PS_IMAGE_COMPRESS # Compression algorithm for images
PS_LINE_CAP # Line cap setting
Expand All @@ -177,4 +177,4 @@ TIME_REPORT # Controls time or elapsed run-time stamp in messages
TIME_UNIT # Unit of time measurement
TIME_SYSTEM # Shortcut to setting TIME_EPOCH/UNIT [does not go in gmt.conf]
TIME_WEEK_START # Day a new week starts on
TIME_Y2K_OFFSET_YEAR # For 2-digit years to separate 1900 and 2000 centuries
TIME_Y2K_OFFSET_YEAR # For 2-digit years to separate 1900 and 2000 centuries
1 change: 1 addition & 0 deletions src/gmt_plot.c
Original file line number Diff line number Diff line change
Expand Up @@ -9319,6 +9319,7 @@ struct PSL_CTRL *gmt_plotinit (struct GMT_CTRL *GMT, struct GMT_OPTION *options)
else
snprintf (GMT->current.ps.title, GMT_LEN256, "GMT v%s Document from %s", GMT_VERSION, GMT->init.module_name);

PSL->internal.no_quantization = GMT->current.setting.ps_color_no_quantization;
PSL_beginplot (PSL, fp, GMT->current.setting.ps_orientation|write_to_mem|switch_charset, O_active, GMT->current.setting.ps_color_mode,
GMT->current.ps.origin, GMT->current.setting.map_origin, media_size, GMT->current.ps.title, fno);

Expand Down
4 changes: 3 additions & 1 deletion src/postscriptlight.c
Original file line number Diff line number Diff line change
Expand Up @@ -3888,7 +3888,9 @@ int PSL_plotcolorimage (struct PSL_CTRL *PSL, double x, double y, double xsize,
/* Colormask or interpolate */
it = nx < 0 ? 1 : (nbits < 0 ? 2 : 0);

if (PSL->internal.color_mode != PSL_GRAY && (image = psl_makecolormap (PSL, buffer, nx, ny, nbits))) {
if (!PSL->internal.no_quantization &&
PSL->internal.color_mode != PSL_GRAY &&
(image = psl_makecolormap (PSL, buffer, nx, ny, nbits))) {
/* Creation of colormap was successful */
nbits = psl_bitreduce (PSL, image->buffer, nx, ny, image->colormap->ncolors);

Expand Down
2 changes: 2 additions & 0 deletions src/postscriptlight.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ extern "C" {
/* Declaration modifiers for DLL support (MSC et al) */
#include "declspec.h"

#include <stdbool.h>
#include <stdio.h>

#define PSL_MaxOpStack_Size 300000 /* As of GhostSCript 9.50; see declaration in gs_init.ps */
Expand Down Expand Up @@ -401,6 +402,7 @@ struct PSL_CTRL {
int deflate_level; /* Compression level for DEFLATE (1-9, default 0) */
int call_level; /* Level in a series of module calls from GMT */
int color_mode; /* 0 = rgb, 1 = cmyk, 2 = hsv (only 1-2 for images) */
bool no_quantization; /* Skip RGB image quantization and indexed-color output [false] */
int line_cap; /* 0, 1, or 2 for butt, round, or square [butt] */
int line_join; /* 0, 1, or 2 for miter, arc, or bevel [miter] */
int miter_limit; /* Acute angle threshold 0-180; 0 means PS default [0] */
Expand Down
30 changes: 30 additions & 0 deletions test/postscriptlight/rgbnoquant.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
#
# Purpose: Verify RGBnoQUANT bypasses PSL indexed-color image optimization
# GMT modules: gmt
#
printf 'P6\n4 4\n255\n' > colors.ppm
printf '\377\000\000\000\377\000\000\000\377\377\377\000' >> colors.ppm
printf '\000\377\000\000\000\377\377\377\000\377\000\000' >> colors.ppm
printf '\000\000\377\377\377\000\377\000\000\000\377\000' >> colors.ppm
printf '\377\377\000\377\000\000\000\377\000\000\000\377' >> colors.ppm

# Default RGB keeps the existing indexed-color and bit-reduction path.
gmt set PS_COLOR_MODEL RGB
[ "$(gmt get PS_COLOR_MODEL)" = "rgb" ] || echo "RGB setting did not round-trip" >> fail
gmt psimage colors.ppm -R0/4/0/4 -JX4c > indexed.ps
grep -Fq "/Indexed /DeviceRGB" indexed.ps || echo "RGB image was not indexed" >> fail
grep -Fq "/Decode [0 3]" indexed.ps || echo "RGB image was not bit-reduced" >> fail

# Case-insensitive RGBnoQUANT must use the existing direct DeviceRGB path.
gmt set PS_COLOR_MODEL RgBnOqUaNt
[ "$(gmt get PS_COLOR_MODEL)" = "rgbnoquant" ] || echo "RGBnoQUANT setting did not round-trip" >> fail
gmt psimage colors.ppm -R0/4/0/4 -JX4c > direct.ps
grep -Fq "/Indexed /DeviceRGB" direct.ps && echo "RGBnoQUANT image was indexed" >> fail
grep -Fq "/DeviceRGB setcolorspace" direct.ps || echo "RGBnoQUANT image was not direct DeviceRGB" >> fail
grep -Fq "/Decode [0 1 0 1 0 1]" direct.ps || echo "RGBnoQUANT image was not 24 bit" >> fail

# Switching back to RGB must reset the no-quantization flag.
gmt set PS_COLOR_MODEL rgb
gmt psimage colors.ppm -R0/4/0/4 -JX4c > restored.ps
grep -Fq "/Indexed /DeviceRGB" restored.ps || echo "RGB did not restore indexed output" >> fail
Loading