|
scofield@7925
|
1 |
/*
|
|
scofield@7925
|
2 |
|
|
jwe@8920
|
3 |
Copyright (C) 2002, 2009 Andy Adler
|
|
jwe@7932
|
4 |
Copyright (C) 2008 Thomas L. Scofield
|
|
scofield@7925
|
5 |
|
|
scofield@7925
|
6 |
This file is part of Octave.
|
|
scofield@7925
|
7 |
|
|
scofield@7925
|
8 |
Octave is free software; you can redistribute it and/or modify it
|
|
scofield@7925
|
9 |
under the terms of the GNU General Public License as published by the
|
|
scofield@7925
|
10 |
Free Software Foundation; either version 3 of the License, or (at your
|
|
scofield@7925
|
11 |
option) any later version.
|
|
scofield@7925
|
12 |
|
|
scofield@7925
|
13 |
Octave is distributed in the hope that it will be useful, but WITHOUT
|
|
scofield@7925
|
14 |
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
scofield@7925
|
15 |
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
scofield@7925
|
16 |
for more details.
|
|
scofield@7925
|
17 |
|
|
scofield@7925
|
18 |
You should have received a copy of the GNU General Public License
|
|
scofield@7925
|
19 |
along with Octave; see the file COPYING. If not, see
|
|
scofield@7925
|
20 |
<http://www.gnu.org/licenses/>.
|
|
scofield@7925
|
21 |
|
|
scofield@7925
|
22 |
*/
|
|
scofield@7925
|
23 |
|
|
jwe@7926
|
24 |
#ifdef HAVE_CONFIG_H
|
|
jwe@7926
|
25 |
#include <config.h>
|
|
jwe@7926
|
26 |
#endif
|
|
scofield@7925
|
27 |
|
|
scofield@8054
|
28 |
#include <cmath>
|
|
scofield@8054
|
29 |
|
|
jwe@7926
|
30 |
#include "defun-dld.h"
|
|
jwe@7926
|
31 |
#include "error.h"
|
|
scofield@8054
|
32 |
#include "ov-struct.h"
|
|
jwe@7926
|
33 |
|
|
dbateman@7937
|
34 |
#ifdef HAVE_MAGICK
|
|
dbateman@7937
|
35 |
|
|
scofield@7925
|
36 |
#include <GraphicsMagick/Magick++.h>
|
|
scofield@7925
|
37 |
|
|
scofield@7925
|
38 |
unsigned int
|
|
jwe@7926
|
39 |
scale_quantum_to_depth (const Magick::Quantum& quantum, unsigned int depth)
|
|
scofield@7925
|
40 |
{
|
|
jwe@7926
|
41 |
return (static_cast<unsigned int> (static_cast<double> (quantum)
|
|
scofield@8053
|
42 |
/ MaxRGB * ((1 << depth) - 1)));
|
|
scofield@7925
|
43 |
}
|
|
scofield@7925
|
44 |
|
|
scofield@7925
|
45 |
octave_value_list
|
|
jwe@7926
|
46 |
read_indexed_images (std::vector<Magick::Image>& imvec,
|
|
scofield@8053
|
47 |
const Array<int>& frameidx, bool wantalpha)
|
|
scofield@7925
|
48 |
{
|
|
scofield@7925
|
49 |
octave_value_list output;
|
|
jwe@7926
|
50 |
|
|
scofield@7925
|
51 |
int rows = imvec[0].baseRows ();
|
|
scofield@7925
|
52 |
int columns = imvec[0].baseColumns ();
|
|
scofield@7925
|
53 |
int nframes = frameidx.length ();
|
|
jwe@7926
|
54 |
|
|
scofield@8054
|
55 |
dim_vector idim = dim_vector ();
|
|
scofield@8054
|
56 |
idim.resize (4);
|
|
scofield@8054
|
57 |
idim(0) = rows;
|
|
scofield@8054
|
58 |
idim(1) = columns;
|
|
scofield@8054
|
59 |
idim(2) = 1;
|
|
scofield@8054
|
60 |
idim(3) = nframes;
|
|
scofield@8054
|
61 |
|
|
scofield@8054
|
62 |
Array<int> idx (dim_vector (4));
|
|
scofield@8054
|
63 |
|
|
jwe@7926
|
64 |
Magick::ImageType type = imvec[0].type ();
|
|
jwe@7926
|
65 |
|
|
scofield@7925
|
66 |
unsigned int mapsize = imvec[0].colorMapSize ();
|
|
scofield@8054
|
67 |
unsigned int i = mapsize;
|
|
scofield@7925
|
68 |
unsigned int depth = 0;
|
|
jwe@7926
|
69 |
while (i >>= 1)
|
|
jwe@7926
|
70 |
depth++;
|
|
scofield@7925
|
71 |
i = 0;
|
|
scofield@7925
|
72 |
depth--;
|
|
jwe@7926
|
73 |
while (depth >>= 1)
|
|
jwe@7926
|
74 |
i++;
|
|
scofield@7925
|
75 |
depth = 1 << i;
|
|
scofield@7925
|
76 |
|
|
scofield@7925
|
77 |
switch (depth)
|
|
scofield@7925
|
78 |
{
|
|
scofield@7925
|
79 |
case 1:
|
|
scofield@7925
|
80 |
case 2:
|
|
scofield@7925
|
81 |
case 4:
|
|
scofield@7925
|
82 |
case 8:
|
|
scofield@7925
|
83 |
{
|
|
scofield@8054
|
84 |
uint8NDArray im = uint8NDArray (idim);
|
|
jwe@7926
|
85 |
|
|
scofield@8054
|
86 |
idx(2) = 0;
|
|
scofield@8053
|
87 |
for (int frame = 0; frame < nframes; frame++)
|
|
scofield@8053
|
88 |
{
|
|
scofield@8053
|
89 |
imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
|
|
jwe@7933
|
90 |
|
|
scofield@8053
|
91 |
const Magick::IndexPacket *pix
|
|
scofield@8053
|
92 |
= imvec[frameidx(frame)].getConstIndexes ();
|
|
jwe@7933
|
93 |
|
|
scofield@8053
|
94 |
i = 0;
|
|
scofield@8054
|
95 |
idx(3) = frame;
|
|
jwe@7933
|
96 |
|
|
scofield@8053
|
97 |
for (int y = 0; y < rows; y++)
|
|
scofield@8054
|
98 |
{
|
|
scofield@8054
|
99 |
idx(0) = y;
|
|
scofield@8054
|
100 |
for (int x = 0; x < columns; x++)
|
|
scofield@8054
|
101 |
{
|
|
scofield@8054
|
102 |
idx(1) = x;
|
|
scofield@8054
|
103 |
im(idx) = static_cast<octave_uint8> (pix[i++]);
|
|
scofield@8054
|
104 |
}
|
|
scofield@8054
|
105 |
}
|
|
scofield@8053
|
106 |
}
|
|
scofield@8053
|
107 |
im.chop_trailing_singletons ();
|
|
scofield@8053
|
108 |
output(0) = octave_value (im);
|
|
scofield@7925
|
109 |
}
|
|
scofield@7925
|
110 |
break;
|
|
jwe@7926
|
111 |
|
|
scofield@7925
|
112 |
case 16:
|
|
scofield@7925
|
113 |
{
|
|
scofield@8054
|
114 |
uint16NDArray im = uint16NDArray (idim);
|
|
jwe@7933
|
115 |
|
|
scofield@8054
|
116 |
idx(2) = 0;
|
|
scofield@8053
|
117 |
for (int frame = 0; frame < nframes; frame++)
|
|
scofield@8053
|
118 |
{
|
|
scofield@8053
|
119 |
imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
|
|
jwe@7933
|
120 |
|
|
scofield@8053
|
121 |
const Magick::IndexPacket *pix
|
|
scofield@8053
|
122 |
= imvec[frameidx(frame)].getConstIndexes ();
|
|
jwe@7933
|
123 |
|
|
scofield@8053
|
124 |
i = 0;
|
|
scofield@8054
|
125 |
idx(3) = frame;
|
|
jwe@7933
|
126 |
|
|
scofield@8053
|
127 |
for (int y = 0; y < rows; y++)
|
|
scofield@8054
|
128 |
{
|
|
scofield@8054
|
129 |
idx(0) = y;
|
|
scofield@8054
|
130 |
for (int x = 0; x < columns; x++)
|
|
scofield@8054
|
131 |
{
|
|
scofield@8054
|
132 |
idx(1) = x;
|
|
scofield@8054
|
133 |
im(idx) = static_cast<octave_uint16> (pix[i++]);
|
|
scofield@8054
|
134 |
}
|
|
scofield@8054
|
135 |
}
|
|
scofield@8053
|
136 |
}
|
|
scofield@7925
|
137 |
im.chop_trailing_singletons ();
|
|
scofield@7925
|
138 |
output(0) = octave_value (im);
|
|
scofield@7925
|
139 |
}
|
|
scofield@7925
|
140 |
break;
|
|
jwe@7926
|
141 |
|
|
scofield@7925
|
142 |
default:
|
|
jwe@7926
|
143 |
error ("__magic_read__: index depths bigger than 16-bit not supported");
|
|
scofield@7925
|
144 |
return octave_value_list ();
|
|
scofield@7925
|
145 |
}
|
|
scofield@7925
|
146 |
|
|
jwe@7926
|
147 |
Matrix map = Matrix (mapsize, 3);
|
|
scofield@7925
|
148 |
Matrix alpha;
|
|
jwe@7926
|
149 |
|
|
scofield@7925
|
150 |
switch (type)
|
|
scofield@7925
|
151 |
{
|
|
jwe@7926
|
152 |
case Magick::PaletteMatteType:
|
|
jwe@7926
|
153 |
#if 0
|
|
jwe@7926
|
154 |
warning ("palettematte");
|
|
jwe@7926
|
155 |
Matrix map (mapsize, 3);
|
|
jwe@7926
|
156 |
Matrix alpha (mapsize, 1);
|
|
jwe@7926
|
157 |
for (i = 0; i < mapsize; i++)
|
|
scofield@7925
|
158 |
{
|
|
scofield@8053
|
159 |
warning ("%d", i);
|
|
scofield@8053
|
160 |
Magick::ColorRGB c = imvec[0].colorMap (i);
|
|
scofield@8053
|
161 |
map(i,0) = c.red ();
|
|
scofield@8053
|
162 |
map(i,1) = c.green ();
|
|
scofield@8053
|
163 |
map(i,2) = c.blue ();
|
|
scofield@8053
|
164 |
alpha(i,1) = c.alpha ();
|
|
scofield@7925
|
165 |
}
|
|
jwe@7926
|
166 |
break;
|
|
jwe@7926
|
167 |
#endif
|
|
jwe@7926
|
168 |
|
|
jwe@7926
|
169 |
case Magick::PaletteType:
|
|
jwe@7926
|
170 |
alpha = Matrix (0, 0);
|
|
jwe@7926
|
171 |
for (i = 0; i < mapsize; i++)
|
|
scofield@7925
|
172 |
{
|
|
scofield@8053
|
173 |
Magick::ColorRGB c = imvec[0].colorMap (i);
|
|
scofield@8053
|
174 |
map(i,0) = c.red ();
|
|
scofield@8053
|
175 |
map(i,1) = c.green ();
|
|
scofield@8053
|
176 |
map(i,2) = c.blue ();
|
|
scofield@7925
|
177 |
}
|
|
jwe@7926
|
178 |
break;
|
|
jwe@7926
|
179 |
|
|
scofield@7925
|
180 |
default:
|
|
jwe@7926
|
181 |
error ("__magick_read__: unsupported indexed image type");
|
|
scofield@7925
|
182 |
return octave_value_list ();
|
|
scofield@7925
|
183 |
}
|
|
scofield@7925
|
184 |
|
|
scofield@7925
|
185 |
if (wantalpha)
|
|
jwe@7926
|
186 |
output(2) = alpha;
|
|
jwe@7926
|
187 |
|
|
jwe@7926
|
188 |
output(1) = map;
|
|
jwe@7926
|
189 |
|
|
scofield@7925
|
190 |
return output;
|
|
scofield@7925
|
191 |
}
|
|
scofield@7925
|
192 |
|
|
scofield@7925
|
193 |
template <class T>
|
|
jwe@7926
|
194 |
octave_value_list
|
|
jwe@7926
|
195 |
read_images (const std::vector<Magick::Image>& imvec,
|
|
scofield@8053
|
196 |
const Array<int>& frameidx, unsigned int depth)
|
|
scofield@7925
|
197 |
{
|
|
jwe@7926
|
198 |
octave_value_list retval (3, Matrix ());
|
|
jwe@7926
|
199 |
|
|
jwe@7926
|
200 |
T im;
|
|
jwe@7926
|
201 |
|
|
scofield@7925
|
202 |
int rows = imvec[0].baseRows ();
|
|
scofield@7925
|
203 |
int columns = imvec[0].baseColumns ();
|
|
scofield@7925
|
204 |
int nframes = frameidx.length ();
|
|
jwe@7926
|
205 |
|
|
scofield@7925
|
206 |
dim_vector idim = dim_vector ();
|
|
scofield@7925
|
207 |
idim.resize (4);
|
|
scofield@7925
|
208 |
idim(0) = rows;
|
|
scofield@7925
|
209 |
idim(1) = columns;
|
|
scofield@7925
|
210 |
idim(2) = 1;
|
|
scofield@7925
|
211 |
idim(3) = nframes;
|
|
jwe@7926
|
212 |
|
|
scofield@7925
|
213 |
Array<int> idx (dim_vector (4));
|
|
jwe@7926
|
214 |
|
|
jwe@7926
|
215 |
Magick::ImageType type = imvec[0].type ();
|
|
jwe@7926
|
216 |
|
|
scofield@7925
|
217 |
switch (type)
|
|
scofield@7925
|
218 |
{
|
|
jwe@7926
|
219 |
case Magick::BilevelType:
|
|
jwe@7926
|
220 |
case Magick::GrayscaleType:
|
|
scofield@8054
|
221 |
im = T (idim);
|
|
jwe@7926
|
222 |
for (int frame = 0; frame < nframes; frame++)
|
|
scofield@7925
|
223 |
{
|
|
scofield@8053
|
224 |
const Magick::PixelPacket *pix
|
|
scofield@8053
|
225 |
= imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
|
|
jwe@7926
|
226 |
|
|
scofield@8053
|
227 |
int i = 0;
|
|
scofield@8054
|
228 |
idx(2) = 0;
|
|
scofield@8054
|
229 |
idx(3) = frame;
|
|
jwe@7926
|
230 |
|
|
scofield@8053
|
231 |
for (int y = 0; y < rows; y++)
|
|
scofield@8054
|
232 |
{
|
|
scofield@8054
|
233 |
idx(0) = y;
|
|
scofield@8054
|
234 |
for (int x = 0; x < columns; x++)
|
|
scofield@8054
|
235 |
{
|
|
scofield@8054
|
236 |
idx(1) = x;
|
|
scofield@8054
|
237 |
im(idx) = scale_quantum_to_depth (pix[i++].red, depth);
|
|
scofield@8054
|
238 |
}
|
|
scofield@8054
|
239 |
}
|
|
scofield@7925
|
240 |
}
|
|
scofield@7925
|
241 |
break;
|
|
jwe@7926
|
242 |
|
|
jwe@7926
|
243 |
case Magick::GrayscaleMatteType:
|
|
scofield@7925
|
244 |
idim(2) = 2;
|
|
jwe@7926
|
245 |
im = T (idim);
|
|
jwe@7926
|
246 |
for (int frame = 0; frame < nframes; frame++)
|
|
scofield@7925
|
247 |
{
|
|
scofield@8053
|
248 |
const Magick::PixelPacket *pix
|
|
scofield@8053
|
249 |
= imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
|
|
jwe@7926
|
250 |
|
|
scofield@8053
|
251 |
int i = 0;
|
|
scofield@8053
|
252 |
idx(3) = frame;
|
|
jwe@7926
|
253 |
|
|
scofield@8053
|
254 |
for (int y = 0; y < rows; y++)
|
|
scofield@8053
|
255 |
{
|
|
scofield@8053
|
256 |
idx(0) = y;
|
|
scofield@8053
|
257 |
for (int x = 0; x < columns; x++)
|
|
scofield@8053
|
258 |
{
|
|
scofield@8053
|
259 |
idx(1) = x;
|
|
scofield@8053
|
260 |
idx(2) = 0;
|
|
scofield@8053
|
261 |
im(idx) = scale_quantum_to_depth (pix[i].red, depth);
|
|
scofield@8053
|
262 |
idx(2) = 1;
|
|
scofield@8053
|
263 |
im(idx) = scale_quantum_to_depth (pix[i].opacity, depth);
|
|
scofield@8053
|
264 |
i++;
|
|
scofield@8053
|
265 |
}
|
|
scofield@8053
|
266 |
}
|
|
jwe@7926
|
267 |
}
|
|
scofield@7925
|
268 |
break;
|
|
jwe@7926
|
269 |
|
|
jwe@7926
|
270 |
case Magick::PaletteType:
|
|
jwe@7926
|
271 |
case Magick::TrueColorType:
|
|
scofield@7925
|
272 |
idim(2) = 3;
|
|
jwe@7926
|
273 |
im = T (idim);
|
|
jwe@7932
|
274 |
for (int frame = 0; frame < nframes; frame++)
|
|
scofield@7925
|
275 |
{
|
|
scofield@8053
|
276 |
const Magick::PixelPacket *pix
|
|
scofield@8053
|
277 |
= imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
|
|
jwe@7926
|
278 |
|
|
scofield@8053
|
279 |
int i = 0;
|
|
scofield@8053
|
280 |
idx(3) = frame;
|
|
jwe@7926
|
281 |
|
|
scofield@8053
|
282 |
for (int y = 0; y < rows; y++)
|
|
scofield@8053
|
283 |
{
|
|
scofield@8053
|
284 |
idx(0) = y;
|
|
scofield@8053
|
285 |
for (int x = 0; x < columns; x++)
|
|
scofield@8053
|
286 |
{
|
|
scofield@8053
|
287 |
idx(1) = x;
|
|
scofield@8053
|
288 |
idx(2) = 0;
|
|
scofield@8053
|
289 |
im(idx) = scale_quantum_to_depth (pix[i].red, depth);
|
|
scofield@8053
|
290 |
idx(2) = 1;
|
|
scofield@8053
|
291 |
im(idx) = scale_quantum_to_depth (pix[i].green, depth);
|
|
scofield@8053
|
292 |
idx(2) = 2;
|
|
scofield@8053
|
293 |
im(idx) = scale_quantum_to_depth (pix[i].blue, depth);
|
|
scofield@8053
|
294 |
i++;
|
|
scofield@8053
|
295 |
}
|
|
scofield@8053
|
296 |
}
|
|
jwe@7926
|
297 |
}
|
|
scofield@7925
|
298 |
break;
|
|
jwe@7926
|
299 |
|
|
jwe@7926
|
300 |
case Magick::PaletteMatteType:
|
|
jwe@7926
|
301 |
case Magick::TrueColorMatteType:
|
|
jwe@7926
|
302 |
case Magick::ColorSeparationType:
|
|
scofield@7925
|
303 |
idim(2) = 4;
|
|
jwe@7926
|
304 |
im = T (idim);
|
|
jwe@7932
|
305 |
for (int frame = 0; frame < nframes; frame++)
|
|
scofield@7925
|
306 |
{
|
|
scofield@8053
|
307 |
const Magick::PixelPacket *pix
|
|
scofield@8053
|
308 |
= imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
|
|
jwe@7926
|
309 |
|
|
scofield@8053
|
310 |
int i = 0;
|
|
scofield@8053
|
311 |
idx(3) = frame;
|
|
jwe@7926
|
312 |
|
|
scofield@8053
|
313 |
for (int y = 0; y < rows; y++)
|
|
scofield@8053
|
314 |
{
|
|
scofield@8053
|
315 |
idx(0) = y;
|
|
scofield@8053
|
316 |
for (int x = 0; x < columns; x++)
|
|
scofield@8053
|
317 |
{
|
|
scofield@8053
|
318 |
idx(1) = x;
|
|
scofield@8053
|
319 |
idx(2) = 0;
|
|
scofield@8053
|
320 |
im(idx) = scale_quantum_to_depth (pix[i].red, depth);
|
|
scofield@8053
|
321 |
idx(2) = 1;
|
|
scofield@8053
|
322 |
im(idx) = scale_quantum_to_depth (pix[i].green, depth);
|
|
scofield@8053
|
323 |
idx(2) = 2;
|
|
scofield@8053
|
324 |
im(idx) = scale_quantum_to_depth (pix[i].blue, depth);
|
|
scofield@8053
|
325 |
idx(2) = 3;
|
|
scofield@8053
|
326 |
im(idx) = scale_quantum_to_depth (pix[i].opacity, depth);
|
|
scofield@8053
|
327 |
i++;
|
|
scofield@8053
|
328 |
}
|
|
scofield@8053
|
329 |
}
|
|
jwe@7926
|
330 |
}
|
|
scofield@7925
|
331 |
break;
|
|
jwe@7926
|
332 |
|
|
scofield@7925
|
333 |
default:
|
|
jwe@7926
|
334 |
error ("__magick_read__: undefined ImageMagick image type");
|
|
jwe@7926
|
335 |
return retval;
|
|
scofield@7925
|
336 |
}
|
|
scofield@7925
|
337 |
|
|
scofield@7925
|
338 |
im.chop_trailing_singletons ();
|
|
jwe@7926
|
339 |
|
|
jwe@7926
|
340 |
retval(0) = im;
|
|
jwe@7926
|
341 |
|
|
jwe@7926
|
342 |
return retval;
|
|
scofield@7925
|
343 |
}
|
|
jwe@7974
|
344 |
|
|
jwe@7974
|
345 |
#endif
|
|
scofield@7925
|
346 |
|
|
jwe@9384
|
347 |
DEFUN_DLD (magick_read, args, nargout,
|
|
jwe@7926
|
348 |
"-*- texinfo -*-\n\
|
|
jwe@7926
|
349 |
@deftypefn {Function File} {@var{m} =} __magick_read__(@var{fname}, @var{index})\n\
|
|
jwe@7926
|
350 |
@deftypefnx{Function File} {[@var{m}, @var{colormap}] =} __magick_read__(@var{fname}, @var{index})\n\
|
|
jwe@7926
|
351 |
@deftypefnx{Function File} {[@var{m}, @var{colormap}, @var{alpha}] =} __magick_read__(@var{fname}, @var{index})\n\
|
|
rdrider0-list@9064
|
352 |
Read images with ImageMagick++. In general you should not be using this function.\n\
|
|
scofield@7925
|
353 |
Instead you should use @code{imread}.\n\
|
|
scofield@7925
|
354 |
@seealso{imread}\n\
|
|
jwe@7926
|
355 |
@end deftypefn")
|
|
scofield@7925
|
356 |
{
|
|
scofield@7925
|
357 |
octave_value_list output;
|
|
jwe@7926
|
358 |
|
|
dbateman@7937
|
359 |
#ifdef HAVE_MAGICK
|
|
jwe@7974
|
360 |
|
|
jwe@7931
|
361 |
if (args.length () > 2 || args.length () < 1 || ! args(0).is_string ()
|
|
jwe@7926
|
362 |
|| nargout > 3)
|
|
scofield@7925
|
363 |
{
|
|
scofield@7925
|
364 |
print_usage ();
|
|
jwe@7926
|
365 |
return output;
|
|
scofield@7925
|
366 |
}
|
|
jwe@7926
|
367 |
|
|
scofield@7925
|
368 |
Array<int> frameidx;
|
|
jwe@7926
|
369 |
|
|
jwe@7931
|
370 |
if (args.length () == 2 && args(1).is_real_type ())
|
|
scofield@7925
|
371 |
frameidx = args(1).int_vector_value();
|
|
scofield@7925
|
372 |
else
|
|
scofield@7925
|
373 |
{
|
|
jwe@7926
|
374 |
frameidx = Array<int> (1);
|
|
jwe@7926
|
375 |
frameidx(0) = 1;
|
|
scofield@7925
|
376 |
}
|
|
scofield@7925
|
377 |
|
|
jwe@7926
|
378 |
std::vector<Magick::Image> imvec;
|
|
jwe@7926
|
379 |
|
|
scofield@7925
|
380 |
try
|
|
scofield@7925
|
381 |
{
|
|
jwe@7926
|
382 |
// Read a file into vector of image objects
|
|
jwe@7926
|
383 |
Magick::readImages (&imvec, args(0).string_value ());
|
|
scofield@7925
|
384 |
}
|
|
jwe@7926
|
385 |
catch (Magick::Warning& w)
|
|
scofield@7925
|
386 |
{
|
|
jwe@7926
|
387 |
warning ("Magick++ warning: %s", w.what ());
|
|
jwe@7926
|
388 |
}
|
|
jwe@7926
|
389 |
catch (Magick::ErrorCoder& e)
|
|
jwe@7926
|
390 |
{
|
|
jwe@7926
|
391 |
warning ("Magick++ coder error: %s", e.what ());
|
|
jwe@7926
|
392 |
}
|
|
jwe@7926
|
393 |
catch (Magick::Exception& e)
|
|
jwe@7926
|
394 |
{
|
|
jwe@7926
|
395 |
error ("Magick++ exception: %s", e.what ());
|
|
jwe@7926
|
396 |
return output;
|
|
scofield@7925
|
397 |
}
|
|
scofield@7925
|
398 |
|
|
jwe@7926
|
399 |
for (int i = 0; i < frameidx.length(); i++)
|
|
scofield@7925
|
400 |
{
|
|
jwe@7926
|
401 |
frameidx(i) = frameidx(i) - 1;
|
|
jwe@7926
|
402 |
|
|
jwe@7926
|
403 |
int nframes = imvec.size ();
|
|
jwe@7926
|
404 |
|
|
jwe@7926
|
405 |
if (frameidx(i) >= nframes || frameidx(i) < 0)
|
|
scofield@8053
|
406 |
{
|
|
scofield@8053
|
407 |
error ("__magick_read__: invalid index vector");
|
|
scofield@8053
|
408 |
return output;
|
|
scofield@8053
|
409 |
}
|
|
scofield@7925
|
410 |
}
|
|
jwe@7926
|
411 |
|
|
jwe@7926
|
412 |
Magick::ClassType klass = imvec[0].classType ();
|
|
jwe@7926
|
413 |
|
|
jwe@7926
|
414 |
if (klass == Magick::PseudoClass && nargout > 1)
|
|
jwe@7926
|
415 |
output = read_indexed_images (imvec, frameidx, (nargout == 3));
|
|
scofield@7925
|
416 |
else
|
|
scofield@7925
|
417 |
{
|
|
jwe@7926
|
418 |
unsigned int depth = imvec[0].modulusDepth ();
|
|
jwe@7926
|
419 |
int i = 0;
|
|
jwe@7926
|
420 |
while (depth >>= 1)
|
|
scofield@8053
|
421 |
i++;
|
|
jwe@7926
|
422 |
depth = 1 << i;
|
|
jwe@7926
|
423 |
|
|
jwe@7926
|
424 |
switch (depth)
|
|
scofield@8053
|
425 |
{
|
|
scofield@8053
|
426 |
case 1:
|
|
scofield@8053
|
427 |
output = read_images<boolNDArray> (imvec, frameidx, depth);
|
|
scofield@8053
|
428 |
break;
|
|
jwe@7926
|
429 |
|
|
scofield@8053
|
430 |
case 2:
|
|
scofield@8053
|
431 |
case 4:
|
|
scofield@8053
|
432 |
case 8:
|
|
scofield@8053
|
433 |
output = read_images<uint8NDArray> (imvec, frameidx, depth) ;
|
|
scofield@8053
|
434 |
break;
|
|
jwe@7926
|
435 |
|
|
scofield@8053
|
436 |
case 16:
|
|
scofield@8053
|
437 |
output = read_images<uint16NDArray> (imvec, frameidx, depth);
|
|
scofield@8053
|
438 |
break;
|
|
jwe@7926
|
439 |
|
|
scofield@8053
|
440 |
case 32:
|
|
scofield@8053
|
441 |
case 64:
|
|
scofield@7925
|
442 |
default:
|
|
scofield@8053
|
443 |
error ("__magick_read__: image depths bigger than 16-bit not supported");
|
|
scofield@8053
|
444 |
}
|
|
scofield@7925
|
445 |
}
|
|
dbateman@7937
|
446 |
#else
|
|
dbateman@7937
|
447 |
|
|
dbateman@7937
|
448 |
error ("__magick_read__: not available in this version of Octave");
|
|
dbateman@7937
|
449 |
|
|
dbateman@7937
|
450 |
#endif
|
|
scofield@7925
|
451 |
|
|
scofield@7925
|
452 |
return output;
|
|
scofield@7925
|
453 |
}
|
|
jwe@7926
|
454 |
|
|
jwe@7974
|
455 |
#ifdef HAVE_MAGICK
|
|
jwe@7974
|
456 |
|
|
scofield@8054
|
457 |
static void
|
|
scofield@8054
|
458 |
jpg_settings (std::vector<Magick::Image>& imvec,
|
|
scofield@8054
|
459 |
const Octave_map& options,
|
|
scofield@8054
|
460 |
bool)
|
|
jwe@7974
|
461 |
{
|
|
scofield@8054
|
462 |
int nframes = static_cast<int>(imvec.size ());
|
|
scofield@8054
|
463 |
bool something_set = 0;
|
|
jwe@7974
|
464 |
|
|
scofield@8054
|
465 |
// Quality setting
|
|
scofield@8054
|
466 |
octave_value result;
|
|
scofield@8054
|
467 |
Octave_map::const_iterator p;
|
|
scofield@8054
|
468 |
bool found_it = 0;
|
|
scofield@8054
|
469 |
for (p = options.begin (); p != options.end (); p++)
|
|
scofield@8054
|
470 |
if (options.key (p) == "Quality")
|
|
scofield@8054
|
471 |
{
|
|
scofield@8054
|
472 |
found_it = 1;
|
|
scofield@8054
|
473 |
result = options.contents (p).elem (0);
|
|
scofield@8054
|
474 |
break;
|
|
scofield@8054
|
475 |
}
|
|
scofield@8054
|
476 |
if (found_it && (! result.is_empty ()))
|
|
scofield@8054
|
477 |
{
|
|
scofield@8054
|
478 |
something_set = 1;
|
|
scofield@8054
|
479 |
if (result.is_real_type ())
|
|
scofield@8054
|
480 |
{
|
|
scofield@8054
|
481 |
int qlev = static_cast<int>(result.int_value ());
|
|
scofield@8054
|
482 |
if (qlev < 0 || qlev > 100)
|
|
scofield@8054
|
483 |
warning ("warning: Quality setting invalid--use default of 75");
|
|
scofield@8054
|
484 |
else
|
|
scofield@8054
|
485 |
for (int fnum = 0; fnum < nframes; fnum++)
|
|
scofield@8054
|
486 |
imvec[fnum].quality (static_cast<unsigned int>(qlev));
|
|
scofield@8054
|
487 |
}
|
|
scofield@8054
|
488 |
else
|
|
scofield@8054
|
489 |
warning ("warning: Quality setting invalid--use default of 75");
|
|
scofield@8054
|
490 |
}
|
|
jwe@7974
|
491 |
|
|
scofield@8054
|
492 |
// Other settings go here
|
|
scofield@8054
|
493 |
|
|
scofield@8054
|
494 |
if (! something_set)
|
|
scofield@8054
|
495 |
warning ("__magick_write__ warning: All write parameters ignored.");
|
|
scofield@8054
|
496 |
}
|
|
scofield@8054
|
497 |
|
|
scofield@8054
|
498 |
static void
|
|
scofield@8054
|
499 |
encode_bool_image (std::vector<Magick::Image>& imvec, const octave_value& img)
|
|
scofield@8054
|
500 |
{
|
|
scofield@8054
|
501 |
unsigned int nframes = 1;
|
|
scofield@8054
|
502 |
boolNDArray m = img.bool_array_value ();
|
|
scofield@8054
|
503 |
|
|
scofield@8054
|
504 |
dim_vector dsizes = m.dims ();
|
|
scofield@8054
|
505 |
if (dsizes.length () == 4)
|
|
scofield@8054
|
506 |
nframes = dsizes(3);
|
|
scofield@8054
|
507 |
|
|
scofield@8054
|
508 |
Array<octave_idx_type> idx (dsizes.length ());
|
|
scofield@8054
|
509 |
|
|
scofield@8054
|
510 |
octave_idx_type rows = m.rows ();
|
|
scofield@8054
|
511 |
octave_idx_type columns = m.columns ();
|
|
scofield@8054
|
512 |
|
|
scofield@8054
|
513 |
for (unsigned int ii = 0; ii < nframes; ii++)
|
|
scofield@8054
|
514 |
{
|
|
scofield@8054
|
515 |
Magick::Image im(Magick::Geometry (columns, rows), "black");
|
|
scofield@8054
|
516 |
im.classType (Magick::DirectClass);
|
|
scofield@8054
|
517 |
im.depth (1);
|
|
scofield@8054
|
518 |
|
|
scofield@8054
|
519 |
for (int y=0; y < columns; y++)
|
|
scofield@8054
|
520 |
{
|
|
scofield@8054
|
521 |
idx(1) = y;
|
|
scofield@8054
|
522 |
for (int x=0; x < rows; x++)
|
|
scofield@8054
|
523 |
{
|
|
scofield@8054
|
524 |
if (nframes > 1)
|
|
scofield@8054
|
525 |
{
|
|
scofield@8054
|
526 |
idx(2) = 0;
|
|
scofield@8054
|
527 |
idx(3) = ii;
|
|
scofield@8054
|
528 |
}
|
|
scofield@8054
|
529 |
idx(0) = x;
|
|
scofield@8054
|
530 |
if (m(idx))
|
|
scofield@8054
|
531 |
im.pixelColor (y, x, "white");
|
|
scofield@8054
|
532 |
}
|
|
scofield@8054
|
533 |
}
|
|
scofield@8054
|
534 |
imvec.push_back (im);
|
|
scofield@8054
|
535 |
}
|
|
scofield@8054
|
536 |
}
|
|
scofield@8054
|
537 |
|
|
scofield@8054
|
538 |
template <class T>
|
|
scofield@8054
|
539 |
static void
|
|
scofield@8054
|
540 |
encode_uint_image (std::vector<Magick::Image>& imvec,
|
|
scofield@8054
|
541 |
const octave_value& img,
|
|
scofield@8054
|
542 |
bool has_map)
|
|
scofield@8054
|
543 |
{
|
|
hauberg@8520
|
544 |
unsigned int bitdepth = 0;
|
|
scofield@8054
|
545 |
T m;
|
|
scofield@8054
|
546 |
|
|
scofield@8054
|
547 |
if (img.is_uint8_type ())
|
|
scofield@8054
|
548 |
{
|
|
scofield@8054
|
549 |
bitdepth = 8;
|
|
scofield@8054
|
550 |
m = img.uint8_array_value ();
|
|
scofield@8054
|
551 |
}
|
|
scofield@8054
|
552 |
else if (img.is_uint16_type ())
|
|
scofield@8054
|
553 |
{
|
|
scofield@8054
|
554 |
bitdepth = 16;
|
|
scofield@8054
|
555 |
m = img.uint16_array_value ();
|
|
scofield@8054
|
556 |
}
|
|
scofield@8054
|
557 |
else
|
|
scofield@8054
|
558 |
error ("__magick_write__: invalid image class");
|
|
scofield@8054
|
559 |
|
|
scofield@8054
|
560 |
dim_vector dsizes = m.dims ();
|
|
scofield@8054
|
561 |
unsigned int nframes = 1;
|
|
scofield@8054
|
562 |
if (dsizes.length () == 4)
|
|
scofield@8054
|
563 |
nframes = dsizes(3);
|
|
scofield@8054
|
564 |
bool is_color = ((dsizes.length () > 2) && (dsizes(2) > 2));
|
|
scofield@8054
|
565 |
bool has_alpha = (dsizes.length () > 2 && (dsizes(2) == 2 || dsizes(2) == 4));
|
|
scofield@8054
|
566 |
|
|
scofield@8054
|
567 |
Array<octave_idx_type> idx (dsizes.length ());
|
|
scofield@8054
|
568 |
octave_idx_type rows = m.rows ();
|
|
scofield@8054
|
569 |
octave_idx_type columns = m.columns ();
|
|
Michael@8090
|
570 |
|
|
Michael@8090
|
571 |
// FIXME -- maybe simply using bit shifting would be better?
|
|
Michael@8090
|
572 |
unsigned int div_factor = pow (2.0, static_cast<int> (bitdepth)) - 1;
|
|
scofield@8054
|
573 |
|
|
scofield@8054
|
574 |
for (unsigned int ii = 0; ii < nframes; ii++)
|
|
scofield@8054
|
575 |
{
|
|
scofield@8054
|
576 |
Magick::Image im(Magick::Geometry (columns, rows), "black");
|
|
scofield@8054
|
577 |
im.depth (bitdepth);
|
|
scofield@8054
|
578 |
if (has_map)
|
|
scofield@8054
|
579 |
im.classType (Magick::PseudoClass);
|
|
scofield@8054
|
580 |
else
|
|
scofield@8054
|
581 |
im.classType (Magick::DirectClass);
|
|
scofield@8054
|
582 |
|
|
scofield@8054
|
583 |
if (is_color)
|
|
scofield@8054
|
584 |
{
|
|
scofield@8054
|
585 |
if (has_alpha)
|
|
scofield@8054
|
586 |
im.type (Magick::TrueColorMatteType);
|
|
scofield@8054
|
587 |
else
|
|
scofield@8054
|
588 |
im.type (Magick::TrueColorType);
|
|
scofield@8054
|
589 |
|
|
scofield@8054
|
590 |
Magick::ColorRGB c;
|
|
scofield@8054
|
591 |
for (int y=0; y < columns; y++)
|
|
scofield@8054
|
592 |
{
|
|
scofield@8054
|
593 |
idx(1) = y;
|
|
scofield@8054
|
594 |
for (int x=0; x < rows; x++)
|
|
scofield@8054
|
595 |
{
|
|
scofield@8054
|
596 |
idx(0) = x;
|
|
scofield@8054
|
597 |
if (nframes > 1)
|
|
scofield@8054
|
598 |
idx(3) = ii;
|
|
scofield@8054
|
599 |
|
|
scofield@8054
|
600 |
idx(2) = 0;
|
|
scofield@8054
|
601 |
c.red (static_cast<double>(m(idx)) / div_factor);
|
|
scofield@8054
|
602 |
idx(2) = 1;
|
|
scofield@8054
|
603 |
c.green (static_cast<double>(m(idx)) / div_factor);
|
|
scofield@8054
|
604 |
idx(2) = 2;
|
|
scofield@8054
|
605 |
c.blue (static_cast<double>(m(idx)) / div_factor);
|
|
scofield@8054
|
606 |
|
|
scofield@8054
|
607 |
if (has_alpha)
|
|
scofield@8054
|
608 |
{
|
|
scofield@8054
|
609 |
idx(2) = 3;
|
|
scofield@8054
|
610 |
c.alpha (static_cast<double>(m(idx)) / div_factor);
|
|
scofield@8054
|
611 |
}
|
|
scofield@8054
|
612 |
im.pixelColor (y, x, c);
|
|
scofield@8054
|
613 |
}
|
|
scofield@8054
|
614 |
}
|
|
scofield@8054
|
615 |
}
|
|
scofield@8054
|
616 |
else
|
|
scofield@8054
|
617 |
{
|
|
scofield@8054
|
618 |
if (has_alpha)
|
|
scofield@8054
|
619 |
im.type (Magick::GrayscaleMatteType);
|
|
scofield@8054
|
620 |
else
|
|
scofield@8054
|
621 |
im.type (Magick::GrayscaleType);
|
|
scofield@8054
|
622 |
|
|
scofield@8054
|
623 |
Magick::ColorGray c;
|
|
scofield@8054
|
624 |
|
|
scofield@8054
|
625 |
for (int y=0; y < columns; y++)
|
|
scofield@8054
|
626 |
{
|
|
scofield@8054
|
627 |
idx(1) = y;
|
|
scofield@8054
|
628 |
for (int x=0; x < rows; x++)
|
|
scofield@8054
|
629 |
{
|
|
scofield@8054
|
630 |
idx(0) = x;
|
|
scofield@8054
|
631 |
if (nframes > 1)
|
|
scofield@8054
|
632 |
{
|
|
scofield@8054
|
633 |
idx(2) = 0;
|
|
scofield@8054
|
634 |
idx(3) = ii;
|
|
scofield@8054
|
635 |
}
|
|
scofield@8054
|
636 |
if (has_alpha)
|
|
scofield@8054
|
637 |
{
|
|
scofield@8054
|
638 |
idx(2) = 1;
|
|
scofield@8054
|
639 |
c.alpha (static_cast<double>(m(idx)) / div_factor);
|
|
scofield@8054
|
640 |
idx(2) = 0;
|
|
scofield@8054
|
641 |
}
|
|
scofield@8054
|
642 |
|
|
scofield@8054
|
643 |
c.shade (static_cast<double>(m(idx)) / div_factor);
|
|
scofield@8054
|
644 |
im.pixelColor (y, x, c);
|
|
scofield@8054
|
645 |
}
|
|
scofield@8054
|
646 |
}
|
|
scofield@8054
|
647 |
}
|
|
scofield@8054
|
648 |
imvec.push_back (im);
|
|
scofield@8054
|
649 |
}
|
|
scofield@8054
|
650 |
}
|
|
scofield@8054
|
651 |
|
|
scofield@8054
|
652 |
static void
|
|
scofield@8054
|
653 |
encode_map (std::vector<Magick::Image>& imvec, const NDArray& cmap)
|
|
scofield@8054
|
654 |
{
|
|
scofield@8054
|
655 |
unsigned int mapsize = cmap.dim1 ();
|
|
scofield@8054
|
656 |
int nframes = static_cast<int>(imvec.size ());
|
|
scofield@8054
|
657 |
|
|
scofield@8054
|
658 |
for (int fnum = 0; fnum < nframes; fnum++)
|
|
scofield@8054
|
659 |
{
|
|
scofield@8054
|
660 |
imvec[fnum].colorMapSize (mapsize);
|
|
scofield@8054
|
661 |
imvec[fnum].type (Magick::PaletteType);
|
|
scofield@8054
|
662 |
}
|
|
scofield@8054
|
663 |
|
|
scofield@8054
|
664 |
for (unsigned int ii = 0; ii < mapsize; ii++)
|
|
scofield@8054
|
665 |
{
|
|
highegg@9274
|
666 |
Magick::ColorRGB c (cmap(ii,0), cmap(ii,1), cmap(ii,2));
|
|
scofield@8054
|
667 |
|
|
scofield@8054
|
668 |
// FIXME -- is this case needed?
|
|
scofield@8054
|
669 |
if (cmap.dim2 () == 4)
|
|
scofield@8054
|
670 |
c.alpha (cmap(ii,3));
|
|
scofield@8054
|
671 |
|
|
scofield@8054
|
672 |
try
|
|
scofield@8054
|
673 |
{
|
|
scofield@8054
|
674 |
for_each (imvec.begin (), imvec.end (),
|
|
scofield@8054
|
675 |
Magick::colorMapImage (ii, c));
|
|
scofield@8054
|
676 |
}
|
|
scofield@8054
|
677 |
catch (Magick::Warning& w)
|
|
scofield@8054
|
678 |
{
|
|
scofield@8054
|
679 |
warning ("Magick++ warning: %s", w.what ());
|
|
scofield@8054
|
680 |
}
|
|
scofield@8054
|
681 |
catch (Magick::ErrorCoder& e)
|
|
scofield@8054
|
682 |
{
|
|
scofield@8054
|
683 |
warning ("Magick++ coder error: %s", e.what ());
|
|
scofield@8054
|
684 |
}
|
|
scofield@8054
|
685 |
catch (Magick::Exception& e)
|
|
scofield@8054
|
686 |
{
|
|
scofield@8054
|
687 |
error ("Magick++ exception: %s", e.what ());
|
|
scofield@8054
|
688 |
}
|
|
scofield@8054
|
689 |
}
|
|
scofield@8054
|
690 |
}
|
|
scofield@8054
|
691 |
|
|
scofield@8054
|
692 |
static void
|
|
scofield@8054
|
693 |
write_image (const std::string& filename, const std::string& fmt,
|
|
scofield@8054
|
694 |
const octave_value& img,
|
|
scofield@8054
|
695 |
const octave_value& map = octave_value (),
|
|
scofield@8054
|
696 |
const octave_value& params = octave_value ())
|
|
scofield@8054
|
697 |
{
|
|
scofield@8054
|
698 |
std::vector<Magick::Image> imvec;
|
|
scofield@8054
|
699 |
|
|
jwe@9275
|
700 |
bool has_map = map.is_defined ();
|
|
jwe@9275
|
701 |
|
|
jwe@9275
|
702 |
if (has_map)
|
|
jwe@9275
|
703 |
{
|
|
jwe@9275
|
704 |
error ("__magick_write__: direct saving of indexed images not currently supported; use ind2rgb and save converted image");
|
|
jwe@9275
|
705 |
return;
|
|
jwe@9275
|
706 |
}
|
|
jwe@9275
|
707 |
|
|
scofield@8054
|
708 |
if (img.is_bool_type ())
|
|
scofield@8054
|
709 |
encode_bool_image (imvec, img);
|
|
scofield@8054
|
710 |
else if (img.is_uint8_type ())
|
|
jwe@9275
|
711 |
encode_uint_image<uint8NDArray> (imvec, img, has_map);
|
|
scofield@8054
|
712 |
else if (img.is_uint16_type ())
|
|
jwe@9275
|
713 |
encode_uint_image<uint16NDArray> (imvec, img, has_map);
|
|
scofield@8054
|
714 |
else
|
|
scofield@8054
|
715 |
error ("__magick_write__: image type not supported");
|
|
scofield@8054
|
716 |
|
|
jwe@9275
|
717 |
if (! error_state && has_map)
|
|
scofield@8054
|
718 |
{
|
|
scofield@8054
|
719 |
NDArray cmap = map.array_value ();
|
|
scofield@8054
|
720 |
|
|
scofield@8054
|
721 |
if (! error_state)
|
|
scofield@8054
|
722 |
encode_map (imvec, cmap);
|
|
scofield@8054
|
723 |
}
|
|
scofield@8054
|
724 |
|
|
scofield@8054
|
725 |
if (! error_state && params.is_defined ())
|
|
scofield@8054
|
726 |
{
|
|
scofield@8054
|
727 |
Octave_map options = params.map_value ();
|
|
scofield@8054
|
728 |
|
|
scofield@8054
|
729 |
// Insert calls here to handle parameters for various image formats
|
|
scofield@8054
|
730 |
if (fmt == "jpg" || fmt == "jpeg")
|
|
jwe@9275
|
731 |
jpg_settings (imvec, options, has_map);
|
|
scofield@8054
|
732 |
else
|
|
scofield@8054
|
733 |
warning ("warning: your parameter(s) currently not supported");
|
|
scofield@8054
|
734 |
}
|
|
jwe@7974
|
735 |
|
|
jwe@7974
|
736 |
try
|
|
jwe@7974
|
737 |
{
|
|
scofield@8054
|
738 |
Magick::writeImages (imvec.begin (), imvec.end (), filename);
|
|
jwe@7974
|
739 |
}
|
|
jwe@7974
|
740 |
catch (Magick::Warning& w)
|
|
jwe@7974
|
741 |
{
|
|
jwe@7974
|
742 |
warning ("Magick++ warning: %s", w.what ());
|
|
jwe@7974
|
743 |
}
|
|
jwe@7974
|
744 |
catch (Magick::ErrorCoder& e)
|
|
jwe@7974
|
745 |
{
|
|
jwe@7974
|
746 |
warning ("Magick++ coder error: %s", e.what ());
|
|
jwe@7974
|
747 |
}
|
|
jwe@7974
|
748 |
catch (Magick::Exception& e)
|
|
jwe@7974
|
749 |
{
|
|
jwe@7974
|
750 |
error ("Magick++ exception: %s", e.what ());
|
|
jwe@7974
|
751 |
}
|
|
jwe@7974
|
752 |
}
|
|
jwe@7974
|
753 |
|
|
jwe@7974
|
754 |
#endif
|
|
jwe@7974
|
755 |
|
|
jwe@9384
|
756 |
DEFUN_DLD (magick_write, args, ,
|
|
jwe@7974
|
757 |
"-*- texinfo -*-\n\
|
|
jwe@7974
|
758 |
@deftypefn {Function File} {} __magick_write__(@var{fname}, @var{fmt}, @var{img})\n\
|
|
jwe@7974
|
759 |
@deftypefnx {Function File} {} __magick_write__(@var{fname}, @var{fmt}, @var{img}, @var{map})\n\
|
|
rdrider0-list@9064
|
760 |
Write images with ImageMagick++. In general you should not be using this function.\n\
|
|
jwe@7974
|
761 |
Instead you should use @code{imwrite}.\n\
|
|
jwe@7974
|
762 |
@seealso{imread}\n\
|
|
jwe@7974
|
763 |
@end deftypefn")
|
|
jwe@7974
|
764 |
{
|
|
jwe@7974
|
765 |
octave_value_list retval;
|
|
jwe@7974
|
766 |
|
|
jwe@7974
|
767 |
#ifdef HAVE_MAGICK
|
|
jwe@7974
|
768 |
int nargin = args.length ();
|
|
jwe@7974
|
769 |
|
|
jwe@7974
|
770 |
if (nargin > 2)
|
|
jwe@7974
|
771 |
{
|
|
jwe@7974
|
772 |
std::string filename = args(0).string_value ();
|
|
jwe@7974
|
773 |
|
|
jwe@7974
|
774 |
if (! error_state)
|
|
scofield@8053
|
775 |
{
|
|
scofield@8053
|
776 |
std::string fmt = args(1).string_value ();
|
|
jwe@7974
|
777 |
|
|
scofield@8053
|
778 |
if (! error_state)
|
|
scofield@8053
|
779 |
{
|
|
scofield@8054
|
780 |
if (nargin > 4)
|
|
scofield@8054
|
781 |
write_image (filename, fmt, args(2), args(3), args(4));
|
|
scofield@8054
|
782 |
else if (nargin > 3)
|
|
scofield@8054
|
783 |
if (args(3).is_real_type ())
|
|
scofield@8054
|
784 |
write_image (filename, fmt, args(2), args(3));
|
|
scofield@8054
|
785 |
else
|
|
scofield@8054
|
786 |
write_image (filename, fmt, args(2), octave_value(), args(3));
|
|
scofield@8053
|
787 |
else
|
|
scofield@8053
|
788 |
write_image (filename, fmt, args(2));
|
|
scofield@8053
|
789 |
}
|
|
scofield@8053
|
790 |
else
|
|
scofield@8053
|
791 |
error ("__magick_write__: expecting format as second argument");
|
|
scofield@8053
|
792 |
}
|
|
jwe@7974
|
793 |
else
|
|
scofield@8053
|
794 |
error ("__magick_write__: expecting filename as first argument");
|
|
jwe@7974
|
795 |
}
|
|
jwe@7974
|
796 |
else
|
|
jwe@7974
|
797 |
print_usage ();
|
|
jwe@7974
|
798 |
#else
|
|
jwe@7974
|
799 |
|
|
jwe@7974
|
800 |
error ("__magick_write__: not available in this version of Octave");
|
|
jwe@7974
|
801 |
|
|
jwe@7974
|
802 |
#endif
|
|
jwe@7974
|
803 |
|
|
scofield@8054
|
804 |
return retval;
|
|
jwe@7974
|
805 |
}
|
|
jwe@7974
|
806 |
|
|
jwe@8165
|
807 |
#ifdef HAVE_MAGICK
|
|
jwe@8165
|
808 |
|
|
sh@8144
|
809 |
template<class T>
|
|
sh@8144
|
810 |
static octave_value
|
|
sh@8144
|
811 |
magick_to_octave_value (const T magick)
|
|
sh@8144
|
812 |
{
|
|
sh@8144
|
813 |
return octave_value (magick);
|
|
sh@8144
|
814 |
}
|
|
sh@8144
|
815 |
|
|
sh@8144
|
816 |
static octave_value
|
|
sh@8144
|
817 |
magick_to_octave_value (const Magick::EndianType magick)
|
|
sh@8144
|
818 |
{
|
|
sh@8144
|
819 |
switch (magick)
|
|
sh@8144
|
820 |
{
|
|
sh@8144
|
821 |
case Magick::LSBEndian:
|
|
sh@8144
|
822 |
return octave_value ("little-endian");
|
|
sh@8144
|
823 |
|
|
sh@8144
|
824 |
case Magick::MSBEndian:
|
|
sh@8144
|
825 |
return octave_value ("big-endian");
|
|
sh@8144
|
826 |
|
|
sh@8144
|
827 |
default:
|
|
sh@8144
|
828 |
return octave_value ("undefined");
|
|
sh@8144
|
829 |
}
|
|
sh@8144
|
830 |
}
|
|
sh@8144
|
831 |
|
|
sh@8144
|
832 |
static octave_value
|
|
sh@8144
|
833 |
magick_to_octave_value (const Magick::ResolutionType magick)
|
|
sh@8144
|
834 |
{
|
|
sh@8144
|
835 |
switch (magick)
|
|
sh@8144
|
836 |
{
|
|
sh@8144
|
837 |
case Magick::PixelsPerInchResolution:
|
|
sh@8144
|
838 |
return octave_value ("pixels per inch");
|
|
sh@8144
|
839 |
|
|
sh@8144
|
840 |
case Magick::PixelsPerCentimeterResolution:
|
|
sh@8144
|
841 |
return octave_value ("pixels per centimeter");
|
|
sh@8144
|
842 |
|
|
sh@8144
|
843 |
default:
|
|
sh@8144
|
844 |
return octave_value ("undefined");
|
|
sh@8144
|
845 |
}
|
|
sh@8144
|
846 |
}
|
|
sh@8144
|
847 |
|
|
sh@8144
|
848 |
static octave_value
|
|
sh@8144
|
849 |
magick_to_octave_value (const Magick::ImageType magick)
|
|
sh@8144
|
850 |
{
|
|
sh@8144
|
851 |
switch (magick)
|
|
sh@8144
|
852 |
{
|
|
sh@8144
|
853 |
case Magick::BilevelType:
|
|
sh@8144
|
854 |
case Magick::GrayscaleType:
|
|
sh@8144
|
855 |
case Magick::GrayscaleMatteType:
|
|
sh@8144
|
856 |
return octave_value ("grayscale");
|
|
sh@8144
|
857 |
|
|
sh@8144
|
858 |
case Magick::PaletteType:
|
|
sh@8144
|
859 |
case Magick::PaletteMatteType:
|
|
sh@8144
|
860 |
return octave_value ("indexed");
|
|
sh@8144
|
861 |
|
|
sh@8144
|
862 |
case Magick::TrueColorType:
|
|
sh@8144
|
863 |
case Magick::TrueColorMatteType:
|
|
sh@8144
|
864 |
case Magick::ColorSeparationType:
|
|
sh@8144
|
865 |
return octave_value ("truecolor");
|
|
sh@8144
|
866 |
|
|
sh@8144
|
867 |
default:
|
|
sh@8144
|
868 |
return octave_value ("undefined");
|
|
sh@8144
|
869 |
}
|
|
sh@8144
|
870 |
}
|
|
sh@8144
|
871 |
|
|
sh@8144
|
872 |
// We put this in a try-block because GraphicsMagick will throw
|
|
sh@8144
|
873 |
// exceptions if a parameter isn't present in the current image.
|
|
sh@8144
|
874 |
#define GET_PARAM(NAME, OUTNAME) \
|
|
sh@8144
|
875 |
try \
|
|
sh@8144
|
876 |
{ \
|
|
sh@8144
|
877 |
st.assign (OUTNAME, magick_to_octave_value (im.NAME ())); \
|
|
sh@8144
|
878 |
} \
|
|
sh@8144
|
879 |
catch (Magick::Warning& w) \
|
|
sh@8144
|
880 |
{ \
|
|
sh@8144
|
881 |
}
|
|
sh@8144
|
882 |
|
|
jwe@8165
|
883 |
#endif
|
|
jwe@8165
|
884 |
|
|
jwe@9384
|
885 |
DEFUN_DLD (magick_finfo, args, ,
|
|
sh@8144
|
886 |
"-*- texinfo -*-\n\
|
|
sh@8144
|
887 |
@deftypefn {Loadable File} {} __magick_finfo__(@var{fname})\n\
|
|
rdrider0-list@9064
|
888 |
Read image information with GraphicsMagick++. In general you should\n\
|
|
sh@8144
|
889 |
not be using this function. Instead you should use @code{imfinfo}.\n\
|
|
sh@8144
|
890 |
@seealso{imfinfo, imread}\n\
|
|
sh@8144
|
891 |
@end deftypefn")
|
|
sh@8144
|
892 |
{
|
|
sh@8144
|
893 |
octave_value_list output;
|
|
sh@8144
|
894 |
|
|
sh@8144
|
895 |
#ifdef HAVE_MAGICK
|
|
sh@8144
|
896 |
|
|
sh@8144
|
897 |
if (args.length () < 1 || ! args (0).is_string ())
|
|
sh@8144
|
898 |
{
|
|
sh@8144
|
899 |
print_usage ();
|
|
sh@8144
|
900 |
return output;
|
|
sh@8144
|
901 |
}
|
|
sh@8144
|
902 |
|
|
sh@8144
|
903 |
const std::string filename = args (0).string_value ();
|
|
sh@8144
|
904 |
|
|
sh@8144
|
905 |
try
|
|
sh@8144
|
906 |
{
|
|
sh@8144
|
907 |
// Read the file.
|
|
sh@8144
|
908 |
Magick::Image im;
|
|
sh@8144
|
909 |
im.read (filename);
|
|
sh@8144
|
910 |
|
|
sh@8144
|
911 |
// Read properties.
|
|
sh@8144
|
912 |
Octave_map st;
|
|
sh@8144
|
913 |
st.assign ("Filename", filename);
|
|
sh@8144
|
914 |
|
|
sh@8144
|
915 |
// Annoying CamelCase naming is for Matlab compatibility.
|
|
sh@8144
|
916 |
GET_PARAM (fileSize, "FileSize")
|
|
sh@8144
|
917 |
GET_PARAM (rows, "Height")
|
|
sh@8144
|
918 |
GET_PARAM (columns, "Width")
|
|
sh@8144
|
919 |
GET_PARAM (depth, "BitDepth")
|
|
sh@8144
|
920 |
GET_PARAM (magick, "Format")
|
|
sh@8144
|
921 |
GET_PARAM (format, "LongFormat")
|
|
sh@8144
|
922 |
GET_PARAM (xResolution, "XResolution")
|
|
sh@8144
|
923 |
GET_PARAM (yResolution, "YResolution")
|
|
sh@8144
|
924 |
GET_PARAM (totalColors, "TotalColors")
|
|
sh@8144
|
925 |
GET_PARAM (tileName, "TileName")
|
|
sh@8144
|
926 |
GET_PARAM (animationDelay, "AnimationDelay")
|
|
sh@8144
|
927 |
GET_PARAM (animationIterations, "AnimationIterations")
|
|
sh@8144
|
928 |
GET_PARAM (endian, "ByteOrder")
|
|
sh@8144
|
929 |
GET_PARAM (gamma, "Gamma")
|
|
sh@8144
|
930 |
GET_PARAM (matte, "Matte")
|
|
sh@8144
|
931 |
GET_PARAM (modulusDepth, "ModulusDepth")
|
|
sh@8144
|
932 |
GET_PARAM (quality, "Quality")
|
|
sh@8144
|
933 |
GET_PARAM (quantizeColors, "QuantizeColors")
|
|
sh@8144
|
934 |
GET_PARAM (resolutionUnits, "ResolutionUnits")
|
|
sh@8144
|
935 |
GET_PARAM (type, "ColorType")
|
|
sh@8144
|
936 |
GET_PARAM (view, "View")
|
|
sh@8144
|
937 |
|
|
sh@8144
|
938 |
output (0) = st;
|
|
sh@8144
|
939 |
}
|
|
sh@8144
|
940 |
catch (Magick::Warning& w)
|
|
sh@8144
|
941 |
{
|
|
sh@8144
|
942 |
warning ("Magick++ warning: %s", w.what ());
|
|
sh@8144
|
943 |
}
|
|
sh@8144
|
944 |
catch (Magick::ErrorCoder& e)
|
|
sh@8144
|
945 |
{
|
|
sh@8144
|
946 |
warning ("Magick++ coder error: %s", e.what ());
|
|
sh@8144
|
947 |
}
|
|
sh@8144
|
948 |
catch (Magick::Exception& e)
|
|
sh@8144
|
949 |
{
|
|
sh@8144
|
950 |
error ("Magick++ exception: %s", e.what ());
|
|
sh@8144
|
951 |
return output;
|
|
sh@8144
|
952 |
}
|
|
sh@8144
|
953 |
|
|
sh@8144
|
954 |
#else
|
|
sh@8144
|
955 |
|
|
sh@8144
|
956 |
error ("imfinfo: not available in this version of Octave");
|
|
sh@8144
|
957 |
|
|
sh@8144
|
958 |
#endif
|
|
sh@8144
|
959 |
|
|
sh@8144
|
960 |
return output;
|
|
sh@8144
|
961 |
}
|
|
sh@8144
|
962 |
|
|
sh@8144
|
963 |
#undef GET_PARAM
|
|
sh@8144
|
964 |
|
|
sh@8144
|
965 |
|
|
jwe@7926
|
966 |
/*
|
|
jwe@7926
|
967 |
;;; Local Variables: ***
|
|
jwe@7926
|
968 |
;;; mode: C++ ***
|
|
scofield@8054
|
969 |
;;; indent-tabs-mode: nil ***
|
|
jwe@7926
|
970 |
;;; End: ***
|
|
jwe@7926
|
971 |
*/
|