1 |
|
|
/* |
2 |
|
|
Teem: Tools to process and visualize scientific data and images . |
3 |
|
|
Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago |
4 |
|
|
Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann |
5 |
|
|
Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah |
6 |
|
|
|
7 |
|
|
This library is free software; you can redistribute it and/or |
8 |
|
|
modify it under the terms of the GNU Lesser General Public License |
9 |
|
|
(LGPL) as published by the Free Software Foundation; either |
10 |
|
|
version 2.1 of the License, or (at your option) any later version. |
11 |
|
|
The terms of redistributing and/or modifying this software also |
12 |
|
|
include exceptions to the LGPL that facilitate static linking. |
13 |
|
|
|
14 |
|
|
This library is distributed in the hope that it will be useful, |
15 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 |
|
|
Lesser General Public License for more details. |
18 |
|
|
|
19 |
|
|
You should have received a copy of the GNU Lesser General Public License |
20 |
|
|
along with this library; if not, write to Free Software Foundation, Inc., |
21 |
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
#include "nrrd.h" |
25 |
|
|
#include "privateNrrd.h" |
26 |
|
|
|
27 |
|
|
static int |
28 |
|
|
_nrrdFormatEPS_available(void) { |
29 |
|
|
|
30 |
|
|
/* but only for writing ... */ |
31 |
|
4 |
return AIR_TRUE; |
32 |
|
|
} |
33 |
|
|
|
34 |
|
|
static int |
35 |
|
|
_nrrdFormatEPS_nameLooksLike(const char *filename) { |
36 |
|
|
|
37 |
|
|
return airEndsWith(filename, NRRD_EXT_EPS); |
38 |
|
|
} |
39 |
|
|
|
40 |
|
|
static int |
41 |
|
|
_nrrdFormatEPS_fitsInto(const Nrrd *nrrd, const NrrdEncoding *encoding, |
42 |
|
|
int useBiff) { |
43 |
|
|
static const char me[]="_nrrdFormatEPS_fitsInto"; |
44 |
|
|
int ret; |
45 |
|
|
|
46 |
|
|
AIR_UNUSED(encoding); |
47 |
|
|
/* encoding information is ignored- its always going to be hex */ |
48 |
|
|
if (!nrrd) { |
49 |
|
|
biffMaybeAddf(useBiff, NRRD, "%s: got NULL nrrd (%p)", |
50 |
|
|
me, AIR_CVOIDP(nrrd)); |
51 |
|
|
return AIR_FALSE; |
52 |
|
|
} |
53 |
|
|
if (nrrdTypeUChar != nrrd->type) { |
54 |
|
|
biffMaybeAddf(useBiff, NRRD, "%s: type must be %s (not %s)", me, |
55 |
|
|
airEnumStr(nrrdType, nrrdTypeUChar), |
56 |
|
|
airEnumStr(nrrdType, nrrd->type)); |
57 |
|
|
return AIR_FALSE; |
58 |
|
|
} |
59 |
|
|
if (2 == nrrd->dim) { |
60 |
|
|
/* its a gray-scale image */ |
61 |
|
|
ret = 2; |
62 |
|
|
} else if (3 == nrrd->dim) { |
63 |
|
|
if (1 == nrrd->axis[0].size) { |
64 |
|
|
/* its a faux-3D image, really grayscale */ |
65 |
|
|
ret = 2; |
66 |
|
|
} else if (3 == nrrd->axis[0].size) { |
67 |
|
|
/* its a real RGB color image */ |
68 |
|
|
ret = 3; |
69 |
|
|
} else if (4 == nrrd->axis[0].size) { |
70 |
|
|
/* its a real CMYK (our best guess) color image */ |
71 |
|
|
ret = 3; |
72 |
|
|
} else { |
73 |
|
|
/* else its no good */ |
74 |
|
|
char stmp[AIR_STRLEN_SMALL]; |
75 |
|
|
biffMaybeAddf(useBiff, NRRD, |
76 |
|
|
"%s: dim is 3, but 1st axis size is %s, not 1, 3, or 4", |
77 |
|
|
me, airSprintSize_t(stmp, nrrd->axis[0].size)); |
78 |
|
|
return AIR_FALSE; |
79 |
|
|
} |
80 |
|
|
} else { |
81 |
|
|
biffMaybeAddf(useBiff, NRRD, "%s: dimension is %d, not 2 or 3", |
82 |
|
|
me, nrrd->dim); |
83 |
|
|
return AIR_FALSE; |
84 |
|
|
} |
85 |
|
|
return ret; |
86 |
|
|
} |
87 |
|
|
|
88 |
|
|
static int |
89 |
|
|
_nrrdFormatEPS_contentStartsLike(NrrdIoState *nio) { |
90 |
|
|
|
91 |
|
|
AIR_UNUSED(nio); |
92 |
|
|
/* this is a write-only format */ |
93 |
|
|
return AIR_FALSE; |
94 |
|
|
} |
95 |
|
|
|
96 |
|
|
static int |
97 |
|
|
_nrrdFormatEPS_read(FILE *file, Nrrd *nrrd, NrrdIoState *nio) { |
98 |
|
|
static const char me[]="_nrrdFormatEPS_read"; |
99 |
|
|
|
100 |
|
|
AIR_UNUSED(file); |
101 |
|
|
AIR_UNUSED(nrrd); |
102 |
|
|
AIR_UNUSED(nio); |
103 |
|
|
biffAddf(NRRD, "%s: sorry, this is a write-only format", me); |
104 |
|
|
return 1; |
105 |
|
|
} |
106 |
|
|
|
107 |
|
|
static int |
108 |
|
|
_nrrdFormatEPS_write(FILE *file, const Nrrd *_nrrd, NrrdIoState *nio) { |
109 |
|
|
static const char me[]="_nrrdFormatEPS_write"; |
110 |
|
|
int color, cmyk, sx, sy; |
111 |
|
|
Nrrd *nrrd; |
112 |
|
|
double aspect, minX, minY, maxX, maxY, scale; |
113 |
|
|
airArray *mop; |
114 |
|
|
|
115 |
|
|
mop = airMopNew(); |
116 |
|
|
airMopAdd(mop, nrrd = nrrdNew(), (airMopper)nrrdNuke, airMopAlways); |
117 |
|
|
if (nrrdCopy(nrrd, _nrrd)) { |
118 |
|
|
biffAddf(NRRD, "%s: couldn't make private copy", me); |
119 |
|
|
airMopError(mop); return 1; |
120 |
|
|
} |
121 |
|
|
if (3 == nrrd->dim && 1 == nrrd->axis[0].size) { |
122 |
|
|
if (nrrdAxesDelete(nrrd, nrrd, 0)) { |
123 |
|
|
biffAddf(NRRD, "%s:", me); |
124 |
|
|
airMopError(mop); return 1; |
125 |
|
|
} |
126 |
|
|
} |
127 |
|
|
color = (3 == nrrd->dim) && (3 == nrrd->axis[0].size |
128 |
|
|
|| 4 == nrrd->axis[0].size); |
129 |
|
|
cmyk = color && 4 == nrrd->axis[0].size; |
130 |
|
|
if (color) { |
131 |
|
|
sx = AIR_CAST(int, nrrd->axis[1].size); |
132 |
|
|
sy = AIR_CAST(int, nrrd->axis[2].size); |
133 |
|
|
} else { |
134 |
|
|
sx = AIR_CAST(int, nrrd->axis[0].size); |
135 |
|
|
sy = AIR_CAST(int, nrrd->axis[1].size); |
136 |
|
|
} |
137 |
|
|
aspect = AIR_CAST(double, sx)/sy; |
138 |
|
|
if (aspect > 7.5/10) { |
139 |
|
|
/* image has a wider aspect ratio than safely printable page area */ |
140 |
|
|
minX = 0.5; |
141 |
|
|
maxX = 8.0; |
142 |
|
|
minY = 5.50 - 7.5*sy/sx/2; |
143 |
|
|
maxY = 5.50 + 7.5*sy/sx/2; |
144 |
|
|
scale = 7.5/sx; |
145 |
|
|
} else { |
146 |
|
|
/* image is taller ... */ |
147 |
|
|
minX = 4.25 - 10.0*sx/sy/2; |
148 |
|
|
maxX = 4.25 + 10.0*sx/sy/2; |
149 |
|
|
minY = 0.5; |
150 |
|
|
maxY = 10.5; |
151 |
|
|
scale = 10.0/sy; |
152 |
|
|
} |
153 |
|
|
minX *= 72; minY *= 72; |
154 |
|
|
maxX *= 72; maxY *= 72; |
155 |
|
|
scale *= 72; |
156 |
|
|
|
157 |
|
|
fprintf(file, "%%!PS-Adobe-3.0 EPSF-3.0\n"); |
158 |
|
|
fprintf(file, "%%%%Creator: Nrrd Utilities From the " |
159 |
|
|
"Great Nation of Deseret\n"); |
160 |
|
|
fprintf(file, "%%%%Title: %s\n", |
161 |
|
|
nrrd->content ? nrrd->content : "A lovely little image"); |
162 |
|
|
fprintf(file, "%%%%Pages: 1\n"); |
163 |
|
|
fprintf(file, "%%%%BoundingBox: %d %d %d %d\n", |
164 |
|
|
(int)floor(minX), (int)floor(minY), |
165 |
|
|
(int)ceil(maxX), (int)ceil(maxY)); |
166 |
|
|
fprintf(file, "%%%%HiResBoundingBox: %g %g %g %g\n", |
167 |
|
|
minX, minY, maxX, maxY); |
168 |
|
|
fprintf(file, "%%%%EndComments\n"); |
169 |
|
|
fprintf(file, "%%%%BeginProlog\n"); |
170 |
|
|
fprintf(file, "%% linestr creates an empty string to hold " |
171 |
|
|
"one scanline\n"); |
172 |
|
|
fprintf(file, "/linestr %d string def\n", sx*(color |
173 |
|
|
? (cmyk |
174 |
|
|
? 4 |
175 |
|
|
: 3) |
176 |
|
|
: 1)); |
177 |
|
|
fprintf(file, "%%%%EndProlog\n"); |
178 |
|
|
fprintf(file, "%%%%Page: 1 1\n"); |
179 |
|
|
fprintf(file, "gsave\n"); |
180 |
|
|
fprintf(file, "%g %g moveto\n", minX, minY); |
181 |
|
|
fprintf(file, "%g %g lineto\n", maxX, minY); |
182 |
|
|
fprintf(file, "%g %g lineto\n", maxX, maxY); |
183 |
|
|
fprintf(file, "%g %g lineto\n", minX, maxY); |
184 |
|
|
fprintf(file, "closepath\n"); |
185 |
|
|
fprintf(file, "clip\n"); |
186 |
|
|
fprintf(file, "gsave newpath\n"); |
187 |
|
|
fprintf(file, "%g %g translate\n", minX, minY); |
188 |
|
|
fprintf(file, "%g %g scale\n", sx*scale, sy*scale); |
189 |
|
|
fprintf(file, "%d %d 8\n", sx, sy); |
190 |
|
|
fprintf(file, "[%d 0 0 -%d 0 %d]\n", sx, sy, sy); |
191 |
|
|
if (color) { |
192 |
|
|
fprintf(file, "{currentfile linestr readhexstring pop} " |
193 |
|
|
"false %d colorimage\n", cmyk ? 4 : 3); |
194 |
|
|
} else { |
195 |
|
|
fprintf(file, "{currentfile linestr readhexstring pop} image\n"); |
196 |
|
|
} |
197 |
|
|
nrrdEncodingHex->write(file, nrrd->data, nrrdElementNumber(nrrd), |
198 |
|
|
nrrd, nio); |
199 |
|
|
fprintf(file, "\n"); |
200 |
|
|
fprintf(file, "grestore\n"); |
201 |
|
|
fprintf(file, "grestore\n"); |
202 |
|
|
|
203 |
|
|
airMopError(mop); |
204 |
|
|
return 0; |
205 |
|
|
} |
206 |
|
|
|
207 |
|
|
const NrrdFormat |
208 |
|
|
_nrrdFormatEPS = { |
209 |
|
|
"EPS", |
210 |
|
|
AIR_FALSE, /* isImage */ |
211 |
|
|
AIR_FALSE, /* readable */ |
212 |
|
|
AIR_FALSE, /* usesDIO */ |
213 |
|
|
_nrrdFormatEPS_available, |
214 |
|
|
_nrrdFormatEPS_nameLooksLike, |
215 |
|
|
_nrrdFormatEPS_fitsInto, |
216 |
|
|
_nrrdFormatEPS_contentStartsLike, |
217 |
|
|
_nrrdFormatEPS_read, |
218 |
|
|
_nrrdFormatEPS_write |
219 |
|
|
}; |
220 |
|
|
|
221 |
|
|
const NrrdFormat *const |
222 |
|
|
nrrdFormatEPS = &_nrrdFormatEPS; |