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