Skip to content

Commit bd188ff

Browse files
authored
Merge pull request #2003 from GenericMappingTools/ghostfuns-improvs
Improve the code of some functions in ghost_funs by using a same shared function.
2 parents 82fde2d + ae1b0b9 commit bd188ff

4 files changed

Lines changed: 109 additions & 48 deletions

File tree

src/ghost/ghost_funs.jl

Lines changed: 8 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -190,28 +190,10 @@ function ps2image(ps_data::Union{String, AbstractVector{UInt8}}; dpi::Int=300, g
190190
nch = gray ? 1 : 3
191191
_gs_state_reset!()
192192
cb_ref = _gs_make_callback_ref()
193-
inst_ref = Ref{Ptr{Cvoid}}(C_NULL)
194-
rc = gsapi_new_instance(inst_ref, C_NULL)
195-
rc < 0 && error("gsapi_new_instance failed: $rc")
196-
inst = inst_ref[]
197-
try
198-
gsapi_set_arg_encoding(inst, GS_ARG_ENCODING_UTF8)
199-
rc = gsapi_set_display_callback(inst, cb_ref)
200-
rc < 0 && error("gsapi_set_display_callback failed: $rc")
201-
args = ["gs", "-dNOPAUSE", "-dNOPROMPT", "-dQUIET", "-dSCANCONVERTERTYPE=2",
202-
"-dUseFastColor=true", "-dGraphicsAlphaBits=4", "-dTextAlphaBits=4",
203-
"-sDEVICE=display", "-dDisplayFormat=$(fmt_int)", "-r$(dpi)"]
204-
#args_c = [Base.cconvert(Cstring, s) for s in args]
205-
#argv = [Base.unsafe_convert(Cstring, s) for s in args_c]
206-
GC.@preserve args begin
207-
rc = gsapi_init_with_args(inst, Cint(length(args)), args)
208-
end
209-
rc < 0 && error("gsapi_init_with_args failed: $rc")
210-
_gs_run_ps_str(inst, ps_data, () -> "")
211-
finally
212-
gsapi_exit(inst)
213-
gsapi_delete_instance(inst)
214-
end
193+
args = ["gs", "-dNOPAUSE", "-dNOPROMPT", "-dQUIET", "-dSCANCONVERTERTYPE=2",
194+
"-dUseFastColor=true", "-dGraphicsAlphaBits=4", "-dTextAlphaBits=4",
195+
"-sDEVICE=display", "-dDisplayFormat=$(fmt_int)", "-r$(dpi)"]
196+
_gs_session(args, inst -> _gs_run_ps_str(inst, ps_data, () -> ""); display_cb=cb_ref)
215197
_GS_STATE.ready || error("Ghostscript produced no output — check PostScript validity.")
216198
W = _GS_STATE.width; H = _GS_STATE.height; R = _GS_STATE.raster
217199
img = if R == W * nch
@@ -605,28 +587,10 @@ psview(ps_data::GMTps; dpi::Int=300) = psview(ps_data.postscript; dpi=dpi)
605587
function psview(ps_data::Union{String, AbstractVector{UInt8}}; dpi::Int=300)
606588
_gs_state_reset!()
607589
cb_ref = _gs_make_callback_ref()
608-
inst_ref = Ref{Ptr{Cvoid}}(C_NULL)
609-
rc = gsapi_new_instance(inst_ref, C_NULL)
610-
rc < 0 && error("gsapi_new_instance failed: $rc")
611-
inst = inst_ref[]
612-
try
613-
gsapi_set_arg_encoding(inst, GS_ARG_ENCODING_UTF8)
614-
rc = gsapi_set_display_callback(inst, cb_ref)
615-
rc < 0 && error("gsapi_set_display_callback failed: $rc")
616-
args = ["gs", "-dNOPAUSE", "-dNOPROMPT", "-dQUIET", "-dSCANCONVERTERTYPE=2",
617-
"-dUseFastColor=true", "-dGraphicsAlphaBits=4", "-dTextAlphaBits=4",
618-
"-sDEVICE=display", "-dDisplayFormat=$(_GS_FMT_RGB24)", "-r$(dpi)"]
619-
#args_c = [Base.cconvert(Cstring, s) for s in args]
620-
#argv = [Base.unsafe_convert(Cstring, s) for s in args_c]
621-
GC.@preserve args begin
622-
rc = gsapi_init_with_args(inst, Cint(length(args)), args)
623-
end
624-
rc < 0 && error("gsapi_init_with_args failed: $rc")
625-
_gs_run_ps_str(inst, ps_data, () -> "")
626-
finally
627-
gsapi_exit(inst)
628-
gsapi_delete_instance(inst)
629-
end
590+
args = ["gs", "-dNOPAUSE", "-dNOPROMPT", "-dQUIET", "-dSCANCONVERTERTYPE=2",
591+
"-dUseFastColor=true", "-dGraphicsAlphaBits=4", "-dTextAlphaBits=4",
592+
"-sDEVICE=display", "-dDisplayFormat=$(_GS_FMT_RGB24)", "-r$(dpi)"]
593+
_gs_session(args, inst -> _gs_run_ps_str(inst, ps_data, () -> ""); display_cb=cb_ref)
630594
_GS_STATE.ready || error("Ghostscript produced no output.")
631595
_GS_BGR[] = _gs_make_bgr_dib(_GS_STATE.width, _GS_STATE.height, _GS_STATE.raster, _GS_STATE.data)
632596

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ using InteractiveUtils
1717
API = GMT.GMT_Create_Session("GMT", 2, GMT.GMT_SESSION_NOEXIT + GMT.GMT_SESSION_EXTERNAL);
1818
GMT.GMT_Get_Ctrl(API);
1919

20+
include("test_ghost.jl")
2021
try
2122
GMT.tic()
2223
include("test_dgt.jl")

test/test_ghost.jl

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
println(" GHOST FUNS (ps2image, ps2raster, psbbox)")
2+
3+
# Minimal valid PostScript: 100x80 point box with bounding box hint.
4+
const _TEST_PS = """%!PS-Adobe-3.0
5+
%%BoundingBox: 10 20 110 100
6+
%%HiResBoundingBox: 10.0 20.0 110.0 100.0
7+
%%EndComments
8+
newpath
9+
10 20 moveto
10+
110 20 lineto
11+
110 100 lineto
12+
10 100 lineto
13+
closepath
14+
0.5 setgray fill
15+
showpage
16+
"""
17+
18+
const _TEST_PS_FILE = joinpath(tempdir(), "gmt_ghost_test.ps")
19+
write(_TEST_PS_FILE, _TEST_PS)
20+
21+
# ── psbbox ───────────────────────────────────────────────────────────────────
22+
@testset "psbbox" begin
23+
# GS bbox device returns ink bounds — slightly outside the geometric rect.
24+
try
25+
bb = GMT.psbbox(_TEST_PS)
26+
@test bb isa NamedTuple
27+
@test isapprox(bb.llx, 10.0; atol=0.1)
28+
@test isapprox(bb.lly, 20.0; atol=0.1)
29+
@test isapprox(bb.urx, 110.0; atol=0.1)
30+
@test isapprox(bb.ury, 100.0; atol=0.1)
31+
32+
bb_file = GMT.psbbox(_TEST_PS_FILE)
33+
@test isapprox(bb_file.llx, 10.0; atol=0.1) && isapprox(bb_file.urx, 110.0; atol=0.1)
34+
@test isapprox(bb_file.lly, 20.0; atol=0.1) && isapprox(bb_file.ury, 100.0; atol=0.1)
35+
36+
bb_bytes = GMT.psbbox(Vector{UInt8}(codeunits(_TEST_PS)))
37+
@test isapprox(bb_bytes.urx, 110.0; atol=0.1) && isapprox(bb_bytes.ury, 100.0; atol=0.1)
38+
catch e
39+
println("psbbox test failed: $e")
40+
end
41+
end
42+
43+
# ── ps2raster ────────────────────────────────────────────────────────────────
44+
@testset "ps2raster" begin
45+
for (fmt, ext) in (("png", ".png"), ("jpg", ".jpg"), ("tif", ".tif"))
46+
out = GMT.ps2raster(_TEST_PS_FILE; fmt=fmt, dpi=72)
47+
@test isfile(out)
48+
@test endswith(out, ext)
49+
@test filesize(out) > 0
50+
rm(out; force=true)
51+
end
52+
53+
out_gray = GMT.ps2raster(_TEST_PS_FILE; fmt="png", dpi=72, gray=true)
54+
@test isfile(out_gray)
55+
rm(out_gray; force=true)
56+
57+
out_named = joinpath(tempdir(), "gmt_ghost_named.png")
58+
rm(out_named; force=true)
59+
r = GMT.ps2raster(_TEST_PS_FILE; outfile=out_named, dpi=72)
60+
@test r == out_named
61+
@test isfile(out_named)
62+
rm(out_named; force=true)
63+
64+
@test_throws ErrorException GMT.ps2raster(_TEST_PS_FILE; fmt="bmp")
65+
@test_throws ErrorException GMT.ps2raster("no_such_file_xyz.ps")
66+
end
67+
68+
# ── ps2image ─────────────────────────────────────────────────────────────────
69+
@testset "ps2image" begin
70+
img = GMT.ps2image(_TEST_PS; dpi=72)
71+
@test img isa Array{UInt8,3}
72+
@test size(img, 3) == 3
73+
@test size(img, 1) > 0 && size(img, 2) > 0
74+
75+
img_gray = GMT.ps2image(_TEST_PS; dpi=72, gray=true)
76+
@test img_gray isa Array{UInt8,2}
77+
@test size(img_gray, 1) == size(img, 1)
78+
@test size(img_gray, 2) == size(img, 2)
79+
80+
img_bytes = GMT.ps2image(Vector{UInt8}(codeunits(_TEST_PS)); dpi=72)
81+
@test size(img_bytes) == size(img)
82+
83+
img_hi = GMT.ps2image(_TEST_PS; dpi=144)
84+
@test size(img_hi, 1) > size(img, 1)
85+
@test size(img_hi, 2) > size(img, 2)
86+
end
87+
88+
rm(_TEST_PS_FILE; force=true)

test/test_misc.jl

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,15 +286,23 @@
286286

287287
# Seismicity
288288
println(" Seismicity")
289-
seismicity(last="1w", circle=(-90,10,500), data=1)
290-
seismicity(last="1w", R=:d, show=false);
291-
seismicity(last="1w", R=:d, size=5, show=false);
289+
try
290+
seismicity(last="1w", circle=(-90,10,500), data=1)
291+
seismicity(last="1w", R=:d, show=false);
292+
seismicity(last="1w", R=:d, size=5, show=false);
292293
GMT.seislegend(Vd=2);
294+
catch e
295+
println(e)
296+
end
293297

294298
# Weather
295299
println(" Weather")
296300
weather(year=2023, debug=1);
297-
weather(city="Quarteira", var="rain");
301+
try
302+
weather(city="Quarteira", var="rain");
303+
catch e
304+
println(e)
305+
end
298306

299307
dataset = "reanalysis-era5-single-levels"
300308
request = """{

0 commit comments

Comments
 (0)