1 // This is core/vil/vil_new.cxx
2 //:
3 // \file
4 // \author Andrew W. Fitzgibbon, Oxford RRG
5 // \date 16 Feb 00
6
7 #include <cstring>
8 #include "vil_new.h"
9
10 #ifdef _MSC_VER
11 # include "vcl_msvc_warnings.h"
12 #endif
13 #include <cassert>
14 #include "vil/vil_save.h"
15 #include "vil/vil_file_format.h"
16 #include "vil/vil_stream_fstream.h"
17 #include "vil/vil_image_resource.h"
18 #include "vil/vil_memory_image.h"
19 #include "vil/vil_blocked_image_facade.h"
20 #include "vil/vil_cached_image_resource.h"
21 #include "vil/vil_pyramid_image_resource.h"
22 #include <vil/file_formats/vil_pyramid_image_list.h>
23 // The first two functions really should be upgraded to create an image in
24 // a temporary file on disk if the sizes are large. - TODO
25
26 //: Make a new image of given format.
27 // If the format is not scalar, the number of planes must be 1. When you create
28 // a multi-component image in this way, the vil_image_resource API will treat
29 // it as a scalar pixel image with multiple planes. (This doesn't affect the
30 // underlying data storage.)
31 // \relatesalso vil_image_resource
32 vil_image_resource_sptr
vil_new_image_resource(unsigned ni,unsigned nj,unsigned nplanes,vil_pixel_format format)33 vil_new_image_resource(unsigned ni, unsigned nj, unsigned nplanes, vil_pixel_format format)
34 {
35 assert(nplanes == 1 || vil_pixel_format_num_components(format) == 1);
36
37 return new vil_memory_image(ni, nj, nplanes, format);
38 }
39
40
41 //: Make a new image of given format with interleaved planes.
42 // The format must be scalar.
43 // \relatesalso vil_image_resource
44 vil_image_resource_sptr
vil_new_image_resource_interleaved(unsigned ni,unsigned nj,unsigned nplanes,vil_pixel_format format)45 vil_new_image_resource_interleaved(unsigned ni, unsigned nj, unsigned nplanes, vil_pixel_format format)
46 {
47 assert(vil_pixel_format_num_components(format) == 1);
48
49 return new vil_memory_image(ni, nj, 1, format, nplanes);
50 }
51
52
53 //: Make a new image resource that is a wrapper on an existing view's data.
54 // \note The output will be a shallow copy of the input, so changing the pixel values
55 // of one may change the pixel value of the other. Thanks to the magic of smart pointers,
56 // the output will remain valid even if you destroy the input. When you wrap
57 // a multi-component image in this way, the vil_image_resource API will treat
58 // it as a scalar pixel image with multiple planes. (This doesn't affect the
59 // underlying data storage.)
60 // \relatesalso vil_image_resource
61 vil_image_resource_sptr
vil_new_image_resource_of_view(vil_image_view_base const & view)62 vil_new_image_resource_of_view(vil_image_view_base const & view)
63 {
64 return new vil_memory_image(view);
65 }
66
67 //: Make a new image, similar format to the prototype.
68 // \relatesalso vil_image_resource
69 vil_image_resource_sptr
vil_new_image_resource(unsigned ni,unsigned nj,vil_image_resource_sptr const & prototype)70 vil_new_image_resource(unsigned ni, unsigned nj, vil_image_resource_sptr const & prototype)
71 {
72 return vil_new_image_resource(ni, nj, prototype->nplanes(), prototype->pixel_format());
73 }
74
75 //: Make a new image.
76 // \relatesalso vil_image_resource
77 vil_image_resource_sptr
vil_new_image_resource(vil_stream * os,unsigned ni,unsigned nj,unsigned nplanes,vil_pixel_format format,char const * file_format)78 vil_new_image_resource(vil_stream * os,
79 unsigned ni,
80 unsigned nj,
81 unsigned nplanes,
82 vil_pixel_format format,
83 char const * file_format)
84 {
85 if (!file_format) // avoid segfault in strcmp()
86 file_format = "pnm";
87
88 vil_image_resource_sptr outimage = nullptr;
89 std::list<vil_file_format *> & l = vil_file_format::all();
90 for (auto fmt : l)
91 {
92 if (std::strcmp(fmt->tag(), file_format) == 0)
93 {
94 outimage = fmt->make_output_image(os, ni, nj, nplanes, format);
95 if (!outimage)
96 std::cerr << "vil_new: Cannot new to type [" << file_format << "]\n";
97 return outimage;
98 }
99 }
100
101 std::cerr << "vil_new: Unknown file type [" << file_format << "]\n";
102 return nullptr;
103 }
104
105 //: Make a new vil_image_resource, writing to file "filename", size ni x nj, copying pixel format etc from "prototype".
106 // \relatesalso vil_image_resource
107 vil_image_resource_sptr
vil_new_image_resource(char const * filename,unsigned ni,unsigned nj,vil_image_resource_sptr const & prototype,char const * file_format)108 vil_new_image_resource(char const * filename,
109 unsigned ni,
110 unsigned nj,
111 vil_image_resource_sptr const & prototype,
112 char const * file_format)
113 {
114 #ifdef VIL_USE_FSTREAM64
115 vil_stream_fstream64 * os = new vil_stream_fstream64(filename, "w");
116 #else // VIL_USE_FSTREAM64
117 auto * os = new vil_stream_fstream(filename, "w");
118 #endif // VIL_USE_FSTREAM64
119 return vil_new_image_resource(
120 os, ni, nj, prototype->nplanes(), prototype->pixel_format(), file_format ? file_format : prototype->file_format());
121 }
122
123 //: Make a new image.
124 // \relatesalso vil_image_resource
125 vil_image_resource_sptr
vil_new_image_resource(char const * filename,unsigned ni,unsigned nj,unsigned nplanes,vil_pixel_format format,char const * file_format)126 vil_new_image_resource(char const * filename,
127 unsigned ni,
128 unsigned nj,
129 unsigned nplanes,
130 vil_pixel_format format,
131 char const * file_format)
132 {
133 #ifdef VIL_USE_FSTREAM64
134 vil_stream_fstream64 * os = new vil_stream_fstream64(filename, "w");
135 #else // VIL_USE_FSTREAM64
136 auto * os = new vil_stream_fstream(filename, "w");
137 #endif // VIL_USE_FSTREAM64
138
139 if (!file_format || !*file_format)
140 file_format = vil_save_guess_file_format(filename);
141 return vil_new_image_resource(os, ni, nj, nplanes, format, file_format);
142 }
143
144
145 //: Make a new vil_image_resource, writing to stream "os", size ni x nj, copying pixel format etc from "prototype".
146 // \relatesalso vil_image_resource
147 vil_image_resource_sptr
vil_new_image_resource(vil_stream * os,unsigned ni,unsigned nj,vil_image_resource_sptr const & prototype,char const * file_format)148 vil_new_image_resource(vil_stream * os,
149 unsigned ni,
150 unsigned nj,
151 vil_image_resource_sptr const & prototype,
152 char const * file_format)
153 {
154 return vil_new_image_resource(
155 os, prototype->nplanes(), ni, nj, prototype->pixel_format(), file_format ? file_format : prototype->file_format());
156 }
157
158 vil_blocked_image_resource_sptr
vil_new_blocked_image_resource(vil_stream * os,unsigned ni,unsigned nj,unsigned nplanes,vil_pixel_format format,unsigned size_block_i,unsigned size_block_j,char const * file_format)159 vil_new_blocked_image_resource(vil_stream * os,
160 unsigned ni,
161 unsigned nj,
162 unsigned nplanes,
163 vil_pixel_format format,
164 unsigned size_block_i,
165 unsigned size_block_j,
166 char const * file_format)
167 {
168 if (!file_format) // avoid segfault in strcmp()
169 file_format = "pnm";
170
171 vil_blocked_image_resource_sptr outimage = nullptr;
172 std::list<vil_file_format *> & l = vil_file_format::all();
173 for (auto fmt : l)
174 {
175 if (std::strcmp(fmt->tag(), file_format) == 0)
176 {
177 outimage = fmt->make_blocked_output_image(os, ni, nj, nplanes, size_block_i, size_block_j, format);
178 if (!outimage)
179 std::cerr << "vil_new: Cannot new a blocked resource to type [" << file_format << "]\n";
180 return outimage;
181 }
182 }
183
184 std::cerr << "vil_new: Unknown file type [" << file_format << "]\n";
185 return nullptr;
186 }
187
188 vil_blocked_image_resource_sptr
vil_new_blocked_image_resource(char const * filename,unsigned ni,unsigned nj,unsigned nplanes,vil_pixel_format format,unsigned size_block_i,unsigned size_block_j,char const * file_format)189 vil_new_blocked_image_resource(char const * filename,
190 unsigned ni,
191 unsigned nj,
192 unsigned nplanes,
193 vil_pixel_format format,
194 unsigned size_block_i,
195 unsigned size_block_j,
196 char const * file_format)
197 {
198 #ifdef VIL_USE_FSTREAM64
199 vil_stream_fstream64 * os = new vil_stream_fstream64(filename, "w");
200 #else // VIL_USE_FSTREAM64
201 auto * os = new vil_stream_fstream(filename, "w");
202 #endif // VIL_USE_FSTREAM64
203 return vil_new_blocked_image_resource(os, ni, nj, nplanes, format, size_block_i, size_block_j, file_format);
204 }
205
206 vil_blocked_image_resource_sptr
vil_new_blocked_image_facade(const vil_image_resource_sptr & src,unsigned size_block_i,unsigned size_block_j)207 vil_new_blocked_image_facade(const vil_image_resource_sptr & src, unsigned size_block_i, unsigned size_block_j)
208 {
209 return new vil_blocked_image_facade(src, size_block_i, size_block_j);
210 }
211
212
213 vil_blocked_image_resource_sptr
vil_new_cached_image_resource(const vil_blocked_image_resource_sptr & bir,const unsigned cache_size)214 vil_new_cached_image_resource(const vil_blocked_image_resource_sptr & bir, const unsigned cache_size)
215 {
216 return new vil_cached_image_resource(bir, cache_size);
217 }
218
219 vil_pyramid_image_resource_sptr
vil_new_pyramid_image_resource(char const * file_or_directory,char const * file_format)220 vil_new_pyramid_image_resource(char const * file_or_directory, char const * file_format)
221 {
222 if (!file_format) // avoid segfault in strcmp()
223 file_format = "tiff";
224 vil_pyramid_image_resource_sptr outimage = nullptr;
225 std::list<vil_file_format *> & l = vil_file_format::all();
226 for (auto fmt : l)
227 {
228 if (std::strcmp(fmt->tag(), file_format) == 0)
229 {
230 outimage = fmt->make_pyramid_output_image(file_or_directory);
231 if (!outimage)
232 std::cerr << "vil_new: Cannot new a pyramid resource to type [" << file_format << "]\n";
233 return outimage;
234 }
235 }
236 std::cerr << "vil_new: Unknown file type [" << file_format << "]\n";
237 return nullptr;
238 }
239
240 vil_pyramid_image_resource_sptr
vil_new_pyramid_image_from_base(char const * filename,vil_image_resource_sptr const & base_image,unsigned nlevels,char const * file_format,char const * temp_dir)241 vil_new_pyramid_image_from_base(char const * filename,
242 vil_image_resource_sptr const & base_image,
243 unsigned nlevels,
244 char const * file_format,
245 char const * temp_dir)
246 {
247 if (!file_format) // avoid segfault in strcmp()
248 file_format = "tiff";
249 vil_pyramid_image_resource_sptr outimage = nullptr;
250 std::list<vil_file_format *> & l = vil_file_format::all();
251 for (auto fmt : l)
252 {
253 if (std::strcmp(fmt->tag(), file_format) == 0)
254 {
255 outimage = fmt->make_pyramid_image_from_base(filename, base_image, nlevels, temp_dir);
256 if (!outimage)
257 std::cerr << "vil_new: Cannot new a pyramid resource to type [" << file_format << "]\n";
258 return outimage;
259 }
260 }
261 std::cerr << "vil_new: Unknown file type [" << file_format << "]\n";
262 return nullptr;
263 }
264
265 // for now there is only one directory based pyramid format
266 vil_pyramid_image_resource_sptr
vil_new_pyramid_image_list_from_base(char const * directory,vil_image_resource_sptr const & base_image,unsigned nlevels,bool copy_base,char const * level_file_format,char const * filename)267 vil_new_pyramid_image_list_from_base(char const * directory,
268 vil_image_resource_sptr const & base_image,
269 unsigned nlevels,
270 bool copy_base,
271 char const * level_file_format,
272 char const * filename)
273 {
274 vil_pyramid_image_list_format vpilf;
275 return vpilf.make_pyramid_image_from_base(directory, base_image, nlevels, copy_base, level_file_format, filename);
276 }
277
278 //: Create a shallow copy of an image and wrap it in a vil_image_view_base_sptr
279 // \note vil_image_view_base_sptr almost certainly doesn't behave as
280 // you would expect, and this function should really only be used by experts.
281 vil_image_view_base_sptr
vil_new_image_view_base_sptr(const vil_image_view_base & src)282 vil_new_image_view_base_sptr(const vil_image_view_base & src)
283 {
284 vil_image_view_base_sptr dest;
285 switch (vil_pixel_format_component_format(src.pixel_format()))
286 {
287 #ifndef DOXYGEN_SHOULD_SKIP_THIS
288 # define macro(F, T) \
289 case F: { \
290 dest = new vil_image_view<T>(src); \
291 break; \
292 }
293 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte) macro(VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte)
294 # if VXL_HAS_INT_64
295 macro(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64) macro(VIL_PIXEL_FORMAT_INT_64, vxl_int_64)
296 # endif
297 macro(VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32) macro(VIL_PIXEL_FORMAT_INT_32, vxl_int_32)
298 macro(VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16) macro(VIL_PIXEL_FORMAT_INT_16, vxl_int_16)
299 macro(VIL_PIXEL_FORMAT_FLOAT, float) macro(VIL_PIXEL_FORMAT_DOUBLE, double)
300 macro(VIL_PIXEL_FORMAT_BOOL, bool)
301 # undef macro
302 #endif // DOXYGEN_SHOULD_SKIP_THIS
303 default: /* do nothing */;
304 }
305 return dest;
306 }
307
308 #if defined(_WIN32) && VXL_USE_WIN_WCHAR_T
309 # include <windows.h>
310
311 //: Make a new image.
312 // \relatesalso vil_image_resource
313 vil_image_resource_sptr
vil_new_image_resource(vil_stream * os,unsigned ni,unsigned nj,unsigned nplanes,vil_pixel_format format,wchar_t const * file_format)314 vil_new_image_resource(vil_stream * os,
315 unsigned ni,
316 unsigned nj,
317 unsigned nplanes,
318 vil_pixel_format format,
319 wchar_t const * file_format)
320 {
321 if (!file_format) // avoid segfault in strcmp()
322 file_format = L"pnm";
323
324 constexpr unsigned int size = 200;
325 char fmt_buffer[size]; // should be enough
326 BOOL useless;
327 // ret indicates the number of characters successfully converted
328 const int ret = WideCharToMultiByte(CP_ACP, 0, file_format, int(wcslen(file_format)), fmt_buffer, size, 0, &useless);
329 fmt_buffer[ret] = '\0';
330 if (!ret)
331 return 0;
332
333 return vil_new_image_resource(os, ni, nj, nplanes, format, fmt_buffer);
334 }
335
336 //: Make a new vil_image_resource, writing to file "filename", size ni x nj, copying pixel format etc from "prototype".
337 // \relatesalso vil_image_resource
338 vil_image_resource_sptr
vil_new_image_resource(wchar_t const * filename,unsigned ni,unsigned nj,vil_image_resource_sptr const & prototype,wchar_t const * file_format)339 vil_new_image_resource(wchar_t const * filename,
340 unsigned ni,
341 unsigned nj,
342 vil_image_resource_sptr const & prototype,
343 wchar_t const * file_format)
344 {
345 # ifdef VIL_USE_FSTREAM64
346 vil_stream_fstream64 * os = new vil_stream_fstream64(filename, "w");
347 # else // VIL_USE_FSTREAM64
348 vil_stream_fstream * os = new vil_stream_fstream(filename, "w");
349 # endif // VIL_USE_FSTREAM64
350
351 constexpr unsigned int size = 200; // should be enough
352 wchar_t tag_buffer[size];
353 if (!file_format)
354 {
355 char const * tag = prototype->file_format();
356 const int ret = MultiByteToWideChar(CP_ACP, 0, tag, std::strlen(tag), tag_buffer, size);
357 assert(ret);
358 file_format = tag_buffer; // use the file format of the given resource
359 }
360
361 return vil_new_image_resource(os, ni, nj, prototype->nplanes(), prototype->pixel_format(), file_format);
362 }
363
364 //: Make a new image.
365 // \relatesalso vil_image_resource
366 vil_image_resource_sptr
vil_new_image_resource(wchar_t const * filename,unsigned ni,unsigned nj,unsigned nplanes,vil_pixel_format format,wchar_t const * file_format)367 vil_new_image_resource(wchar_t const * filename,
368 unsigned ni,
369 unsigned nj,
370 unsigned nplanes,
371 vil_pixel_format format,
372 wchar_t const * file_format)
373 {
374 # ifdef VIL_USE_FSTREAM64
375 vil_stream_fstream64 * os = new vil_stream_fstream64(filename, "w");
376 # else // VIL_USE_FSTREAM64
377 vil_stream_fstream * os = new vil_stream_fstream(filename, "w");
378 # endif // VIL_USE_FSTREAM64
379
380 if (!file_format || !*file_format)
381 file_format = vil_save_guess_file_format(filename);
382 return vil_new_image_resource(os, ni, nj, nplanes, format, file_format);
383 }
384
385 #endif // defined(_WIN32) && VXL_USE_WIN_WCHAR_T
386