MVE - Multi-View Environment mve-devel
Loading...
Searching...
No Matches
image_io.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015, Simon Fuhrmann
3 * TU Darmstadt - Graphics, Capture and Massively Parallel Computing
4 * All rights reserved.
5 *
6 * This software may be modified and distributed under the terms
7 * of the BSD 3-Clause license. See the LICENSE.txt file for details.
8 */
9
10#include <algorithm>
11#include <limits>
12#include <fstream>
13#include <cstdio>
14#include <cstdarg>
15#include <cstring>
16#include <cerrno>
17
18#ifndef MVE_NO_PNG_SUPPORT
19# include <png.h>
20#endif
21
22#ifndef MVE_NO_JPEG_SUPPORT
23/* Include windows.h before jpeglib.h to prevent INT32 typedef collision. */
24# if defined(_WIN32)
25# include <windows.h>
26# endif
27# include <jpeglib.h>
28#endif
29
30#ifndef MVE_NO_TIFF_SUPPORT
31# include <tiff.h>
32# include <tiffio.h>
33#endif
34
35#include "math/algo.h"
36#include "util/exception.h"
37#include "util/strings.h"
38#include "util/system.h"
39#include "mve/image_io.h"
40
41/* Loader limits for reading PPM files. */
42#define PPM_MAX_PIXEL_AMOUNT (16384 * 16384) /* 2^28 */
43
44/* The signature to identify MVEI image files and loader limits. */
45#define MVEI_FILE_SIGNATURE "\211MVE_IMAGE\n"
46#define MVEI_FILE_SIGNATURE_LEN 11
47#define MVEI_MAX_PIXEL_AMOUNT (16384 * 16384) /* 2^28 */
48
51
52/*
53 * ------------------------ Loading and Saving -----------------------
54 */
55
56ByteImage::Ptr
57load_file (std::string const& filename)
58{
59 try
60 {
61#ifndef MVE_NO_PNG_SUPPORT
62 try
63 { return load_png_file(filename); }
64 catch (util::FileException& e) { throw; }
65 catch (util::Exception& e) {}
66#endif
67
68#ifndef MVE_NO_JPEG_SUPPORT
69 try
70 { return load_jpg_file(filename); }
71 catch (util::FileException& e) { throw; }
72 catch (util::Exception& e) {}
73#endif
74
75#ifndef MVE_NO_TIFF_SUPPORT
76 try
77 { return load_tiff_file(filename); }
78 catch (util::FileException& e) { throw; }
79 catch (util::Exception& e) {}
80#endif
81
82 try
83 { return load_ppm_file(filename); }
84 catch (util::FileException& e) { throw; }
85 catch (util::Exception& e) {}
86
87 try
88 {
89 ImageHeaders header = load_mvei_file_headers(filename);
90 if (header.type != IMAGE_TYPE_UINT8)
91 throw util::Exception("Invalid image format");
92 ImageBase::Ptr image = load_mvei_file(filename);
93 return std::dynamic_pointer_cast<ByteImage>(image);
94 }
95 catch (util::FileException& e) { throw; }
96 catch (util::Exception& e) {}
97 }
98 catch (util::FileException& e)
99 {
100 throw util::Exception(filename + ": ", e.what());
101 }
102
103 throw util::Exception(filename, ": Cannot determine image format");
104}
105
106ImageHeaders
107load_file_headers (std::string const& filename)
108{
109 try
110 {
111#ifndef MVE_NO_PNG_SUPPORT
112 try
113 { return load_png_file_headers(filename); }
114 catch (util::FileException&) { throw; }
115 catch (util::Exception&) {}
116#endif
117
118#ifndef MVE_NO_JPEG_SUPPORT
119 try
120 { return load_jpg_file_headers(filename); }
121 catch (util::FileException&) { throw; }
122 catch (util::Exception&) {}
123#endif
124
125#ifndef MVE_NO_TIFF_SUPPORT
126 try
127 { return load_tiff_file_headers(filename); }
128 catch (util::FileException&) { throw; }
129 catch (util::Exception&) {}
130#endif
131
132 try
133 { return load_mvei_file_headers(filename); }
134 catch (util::FileException&) { throw; }
135 catch (util::Exception&) {}
136 }
137 catch (util::FileException& e)
138 {
139 throw util::Exception(filename + ": ", e.what());
140 }
141
142 throw util::Exception(filename, ": Cannot determine image format");
143}
144
145void
146save_file (ByteImage::ConstPtr image, std::string const& filename)
147{
148 using namespace util::string;
149 std::string fext4 = lowercase(right(filename, 4));
150 std::string fext5 = lowercase(right(filename, 5));
151
152#ifndef MVE_NO_JPEG_SUPPORT
153 if (fext4 == ".jpg" || fext5 == ".jpeg")
154 {
155 save_jpg_file(image, filename, 85);
156 return;
157 }
158#endif
159
160#ifndef MVE_NO_PNG_SUPPORT
161 if (fext4 == ".png")
162 {
163 save_png_file(image, filename);
164 return;
165 }
166#endif
167
168#ifndef MVE_NO_TIFF_SUPPORT
169 if (fext4 == ".tif" || fext5 == ".tiff")
170 {
171 save_tiff_file(image, filename);
172 return;
173 }
174#endif
175
176 if (fext4 == ".ppm")
177 {
178 save_ppm_file(image, filename);
179 return;
180 }
181
182 throw util::Exception("Output filetype not supported");
183}
184
185void
186save_file (ByteImage::Ptr image, std::string const& filename)
187{
188 save_file(ByteImage::ConstPtr(image), filename);
189}
190
191void
192save_file (FloatImage::ConstPtr image, std::string const& filename)
193{
194
195 using namespace util::string;
196 std::string fext4 = lowercase(right(filename, 4));
197 if (fext4 == ".pfm")
198 {
199 save_pfm_file(image, filename);
200 return;
201 }
202
203 throw util::Exception("Output filetype not supported");
204}
205
206void
207save_file (FloatImage::Ptr image, std::string const& filename)
208{
209 save_file(FloatImage::ConstPtr(image), filename);
210}
211
212/* ---------------------------------------------------------------- */
213
214#ifndef MVE_NO_PNG_SUPPORT
215
216namespace
217{
218 void
219 load_png_headers_intern (FILE* fp, ImageHeaders* headers,
220 png_structp* png, png_infop* png_info)
221 {
222 /* Identify the PNG signature. */
223 png_byte signature[8];
224 if (std::fread(signature, 1, 8, fp) != 8)
225 {
226 std::fclose(fp);
227 throw util::Exception("PNG signature could not be read");
228 }
229 if (png_sig_cmp(signature, 0, 8) != 0)
230 {
231 std::fclose(fp);
232 throw util::Exception("PNG signature did not match");
233 }
234
235 /* Initialize PNG structures. */
236 *png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
237 nullptr, nullptr, nullptr);
238 if (!*png)
239 {
240 std::fclose(fp);
241 throw util::Exception("Out of memory");
242 }
243
244 *png_info = png_create_info_struct(*png);
245 if (!*png_info)
246 {
247 png_destroy_read_struct(png, nullptr, nullptr);
248 std::fclose(fp);
249 throw util::Exception("Out of memory");
250 }
251
252 /* Init PNG file IO */
253 png_init_io(*png, fp);
254 png_set_sig_bytes(*png, 8);
255
256 /* Read PNG header info. */
257 png_read_info(*png, *png_info);
258
259 headers->width = png_get_image_width(*png, *png_info);
260 headers->height = png_get_image_height(*png, *png_info);
261 headers->channels = png_get_channels(*png, *png_info);
262
263 int const bit_depth = png_get_bit_depth(*png, *png_info);
264 if (bit_depth <= 8)
265 headers->type = IMAGE_TYPE_UINT8;
266 else if (bit_depth == 16)
267 headers->type = IMAGE_TYPE_UINT16;
268 else
269 {
270 png_destroy_read_struct(png, png_info, nullptr);
271 std::fclose(fp);
272 throw util::Exception("PNG with unknown bit depth");
273 }
274 }
275}
276
277ByteImage::Ptr
278load_png_file (std::string const& filename)
279{
280 // TODO: use throw-safe FILE* wrapper
281 FILE* fp = std::fopen(filename.c_str(), "rb");
282 if (fp == nullptr)
283 throw util::FileException(filename, std::strerror(errno));
284
285 /* Read PNG header info. */
286 ImageHeaders headers;
287 png_structp png = nullptr;
288 png_infop png_info = nullptr;
289 load_png_headers_intern(fp, &headers, &png, &png_info);
290
291 /* Check if bit depth is valid. */
292 int const bit_depth = png_get_bit_depth(png, png_info);
293 if (bit_depth > 8)
294 {
295 png_destroy_read_struct(&png, &png_info, nullptr);
296 std::fclose(fp);
297 throw util::Exception("PNG with more than 8 bit");
298 }
299
300 /* Apply transformations. */
301 int const color_type = png_get_color_type(png, png_info);
302 if (color_type == PNG_COLOR_TYPE_PALETTE)
303 png_set_palette_to_rgb(png);
304 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
305 png_set_expand_gray_1_2_4_to_8(png);
306 if (png_get_valid(png, png_info, PNG_INFO_tRNS))
307 png_set_tRNS_to_alpha(png);
308
309 /* Update the info struct to reflect the transformations. */
310 png_read_update_info(png, png_info);
311
312 /* Create image. */
313 ByteImage::Ptr image = ByteImage::create();
314 image->allocate(headers.width, headers.height, headers.channels);
315 ByteImage::ImageData& data = image->get_data();
316
317 /* Setup row pointers. */
318 std::vector<png_bytep> row_pointers;
319 row_pointers.resize(headers.height);
320 for (int i = 0; i < headers.height; ++i)
321 row_pointers[i] = &data[i * headers.width * headers.channels];
322
323 /* Read the whole PNG in memory. */
324 png_read_image(png, &row_pointers[0]);
325
326 /* Clean up. */
327 png_destroy_read_struct(&png, &png_info, nullptr);
328 std::fclose(fp);
329
330 return image;
331}
332
333ImageHeaders
334load_png_file_headers (std::string const& filename)
335{
336 FILE* fp = std::fopen(filename.c_str(), "rb");
337 if (fp == nullptr)
338 throw util::FileException(filename, std::strerror(errno));
339
340 /* Read PNG header info. */
341 ImageHeaders headers;
342 png_structp png = nullptr;
343 png_infop png_info = nullptr;
344 load_png_headers_intern(fp, &headers, &png, &png_info);
345
346 /* Clean up. */
347 png_destroy_read_struct(&png, &png_info, nullptr);
348 std::fclose(fp);
349
350 return headers;
351}
352
353void
355 std::string const& filename, int compression_level)
356{
357 if (image == nullptr)
358 throw std::invalid_argument("Null image given");
359
360 FILE *fp = std::fopen(filename.c_str(), "wb");
361 if (!fp)
362 throw util::FileException(filename, std::strerror(errno));
363
364 //png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
365 // (png_voidp)user_error_ptr, user_error_fn, user_warning_fn);
366 png_structp png_ptr = png_create_write_struct
367 (PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
368
369 if (!png_ptr)
370 {
371 std::fclose(fp);
372 throw util::Exception("Out of memory");
373 }
374
375 png_infop info_ptr = png_create_info_struct(png_ptr);
376 if (!info_ptr)
377 {
378 png_destroy_write_struct(&png_ptr, (png_infopp)nullptr);
379 std::fclose(fp);
380 throw util::Exception("Out of memory");
381 }
382
383 png_init_io(png_ptr, fp);
384
385 // void write_row_callback(png_ptr, png_uint_32 row, int pass);
386 //png_set_write_status_fn(png_ptr, write_row_callback);
387
388 /* Determine color type to be written. */
389 int color_type;
390 switch (image->channels())
391 {
392 case 1: color_type = PNG_COLOR_TYPE_GRAY; break;
393 case 2: color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break;
394 case 3: color_type = PNG_COLOR_TYPE_RGB; break;
395 case 4: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break;
396 default:
397 {
398 png_destroy_write_struct(&png_ptr, &info_ptr);
399 std::fclose(fp);
400 throw util::Exception("Cannot determine image color type");
401 }
402 }
403
404 /* Set compression level (6 seems to be the default). */
405 png_set_compression_level(png_ptr, compression_level);
406
407 /* Write image. */
408 png_set_IHDR(png_ptr, info_ptr, image->width(), image->height(),
409 8 /* Bit depth */, color_type, PNG_INTERLACE_NONE,
410 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
411
412 /* Setup row pointers. */
413 std::vector<png_bytep> row_pointers;
414 row_pointers.resize(image->height());
415 ByteImage::ImageData const& data = image->get_data();
416 for (int i = 0; i < image->height(); ++i)
417 row_pointers[i] = const_cast<png_bytep>(
418 &data[i * image->width() * image->channels()]);
419
420 /* Setup transformations. */
421 int png_transforms = PNG_TRANSFORM_IDENTITY;
422 //png_transforms |= PNG_TRANSFORM_INVERT_ALPHA;
423
424 /* Write to file. */
425 png_set_rows(png_ptr, info_ptr, &row_pointers[0]);
426 png_write_png(png_ptr, info_ptr, png_transforms, nullptr);
427 png_write_end(png_ptr, info_ptr);
428
429 /* Cleanup. */
430 png_destroy_write_struct(&png_ptr, &info_ptr);
431 std::fclose(fp);
432}
433
434#endif /* MVE_NO_PNG_SUPPORT */
435
436/* ---------------------------------------------------------------- */
437
438#ifndef MVE_NO_JPEG_SUPPORT
439
440void
441jpg_error_handler (j_common_ptr /*cinfo*/)
442{
443 throw util::Exception("JPEG format not recognized");
444}
445
446void
447jpg_message_handler (j_common_ptr /*cinfo*/, int msg_level)
448{
449 if (msg_level < 0)
450 throw util::Exception("JPEG data corrupt");
451}
452
454load_jpg_file (std::string const& filename, std::string* exif)
455{
456 FILE* fp = std::fopen(filename.c_str(), "rb");
457 if (fp == nullptr)
458 throw util::FileException(filename, std::strerror(errno));
459
460 jpeg_decompress_struct cinfo;
461 jpeg_error_mgr jerr;
462 ByteImage::Ptr image;
463 try
464 {
465 /* Setup error handler and JPEG reader. */
466 cinfo.err = jpeg_std_error(&jerr);
467 jerr.error_exit = &jpg_error_handler;
468 jerr.emit_message = &jpg_message_handler;
469 jpeg_create_decompress(&cinfo);
470 jpeg_stdio_src(&cinfo, fp);
471
472 if (exif)
473 {
474 /* Request APP1 marker to be saved (this is the EXIF data). */
475 jpeg_save_markers(&cinfo, JPEG_APP0 + 1, 0xffff);
476 }
477
478 /* Read JPEG header. */
479 int ret = jpeg_read_header(&cinfo, static_cast<boolean>(false));
480 if (ret != JPEG_HEADER_OK)
481 throw util::Exception("JPEG header not recognized");
482
483 /* Examine JPEG markers. */
484 if (exif)
485 {
486 jpeg_saved_marker_ptr marker = cinfo.marker_list;
487 if (marker != nullptr && marker->marker == JPEG_APP0 + 1
488 && marker->data_length > 6
489 && std::equal(marker->data, marker->data + 6, "Exif\0\0"))
490 {
491 char const* data = reinterpret_cast<char const*>(marker->data);
492 exif->append(data, data + marker->data_length);
493 }
494 }
495
496 if (cinfo.out_color_space != JCS_GRAYSCALE
497 && cinfo.out_color_space != JCS_RGB)
498 throw util::Exception("Invalid JPEG color space");
499
500 /* Create image. */
501 int const width = cinfo.image_width;
502 int const height = cinfo.image_height;
503 int const channels = (cinfo.out_color_space == JCS_RGB ? 3 : 1);
504 image = ByteImage::create(width, height, channels);
505 ByteImage::ImageData& data = image->get_data();
506
507 /* Start decompression. */
508 jpeg_start_decompress(&cinfo);
509
510 unsigned char* data_ptr = &data[0];
511 while (cinfo.output_scanline < cinfo.output_height)
512 {
513 jpeg_read_scanlines(&cinfo, &data_ptr, 1);
514 data_ptr += channels * cinfo.output_width;
515 }
516
517 /* Shutdown JPEG decompression. */
518 jpeg_finish_decompress(&cinfo);
519 jpeg_destroy_decompress(&cinfo);
520 std::fclose(fp);
521 }
522 catch (...)
523 {
524 jpeg_destroy_decompress(&cinfo);
525 std::fclose(fp);
526 throw;
527 }
528
529 return image;
530}
531
532ImageHeaders
533load_jpg_file_headers (std::string const& filename)
534{
535 FILE* fp = std::fopen(filename.c_str(), "rb");
536 if (fp == nullptr)
537 throw util::FileException(filename, std::strerror(errno));
538
539 jpeg_decompress_struct cinfo;
540 jpeg_error_mgr jerr;
541 ImageHeaders headers;
542 try
543 {
544 /* Setup error handler and JPEG reader. */
545 cinfo.err = jpeg_std_error(&jerr);
546 jerr.error_exit = &jpg_error_handler;
547 jerr.emit_message = &jpg_message_handler;
548 jpeg_create_decompress(&cinfo);
549 jpeg_stdio_src(&cinfo, fp);
550
551 /* Read JPEG header. */
552 int ret = jpeg_read_header(&cinfo, static_cast<boolean>(false));
553 if (ret != JPEG_HEADER_OK)
554 throw util::Exception("JPEG header not recognized");
555
556 if (cinfo.out_color_space != JCS_GRAYSCALE
557 && cinfo.out_color_space != JCS_RGB)
558 throw util::Exception("Invalid JPEG color space");
559
560 headers.width = cinfo.image_width;
561 headers.height = cinfo.image_height;
562 headers.channels = (cinfo.out_color_space == JCS_RGB ? 3 : 1);
563 headers.type = IMAGE_TYPE_UINT8;
564
565 jpeg_destroy_decompress(&cinfo);
566 std::fclose(fp);
567 }
568 catch (...)
569 {
570 jpeg_destroy_decompress(&cinfo);
571 std::fclose(fp);
572 throw;
573 }
574
575 return headers;
576}
577
578// http://download.blender.org/source/chest/blender_2.03_tree/jpeg/example.c
579void
580save_jpg_file (ByteImage::ConstPtr image, std::string const& filename, int quality)
581{
582 if (image == nullptr)
583 throw std::invalid_argument("Null image given");
584
585 if (image->channels() != 1 && image->channels() != 3)
586 throw util::Exception("Invalid image color space");
587
588 FILE* fp = std::fopen(filename.c_str(), "wb");
589 if (!fp)
590 throw util::FileException(filename, std::strerror(errno));
591
592 jpeg_compress_struct cinfo;
593 jpeg_error_mgr jerr;
594
595 /* Setup error handler and info object. */
596 cinfo.err = jpeg_std_error(&jerr);
597 jpeg_create_compress(&cinfo);
598 jpeg_stdio_dest(&cinfo, fp);
599
600 /* Specify image dimensions. */
601 cinfo.image_width = image->width();
602 cinfo.image_height = image->height();
603 cinfo.input_components = image->channels();
604 cinfo.in_color_space = (image->channels() == 1 ? JCS_GRAYSCALE : JCS_RGB);
605
606 /* Set default compression parameters. */
607 jpeg_set_defaults(&cinfo);
608 jpeg_set_quality(&cinfo, quality, TRUE);
609 jpeg_start_compress(&cinfo, TRUE);
610
611 ByteImage::ImageData const& data = image->get_data();
612 int row_stride = image->width() * image->channels();
613 while (cinfo.next_scanline < cinfo.image_height)
614 {
615 JSAMPROW row_pointer = const_cast<JSAMPROW>(
616 &data[cinfo.next_scanline * row_stride]);
617 jpeg_write_scanlines(&cinfo, &row_pointer, 1);
618 }
619 jpeg_finish_compress(&cinfo);
620 jpeg_destroy_compress(&cinfo);
621 std::fclose(fp);
622}
623
624#endif /* MVE_NO_JPEG_SUPPORT */
625
626/* ---------------------------------------------------------------- */
627
628#ifndef MVE_NO_TIFF_SUPPORT
629
630void
631tiff_error_handler (char const* /*module*/, char const* fmt, va_list ap)
632{
633 char msg[2048];
634 ::vsprintf(msg, fmt, ap);
635 throw util::Exception(msg);
636}
637
638ImageHeaders
639load_tiff_file_headers (std::string const& filename)
640{
641 ImageHeaders headers;
642 TIFFSetWarningHandler(nullptr);
643 TIFFSetErrorHandler(tiff_error_handler);
644
645 TIFF* tif = TIFFOpen(filename.c_str(), "r");
646 if (tif == nullptr)
647 throw util::FileException(filename, "TIFF file format not recognized");
648
649 try
650 {
651 uint32_t width, height;
652 uint16_t channels, bits, sampleFormat;
653 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
654 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
655 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &channels);
656 TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits);
657 TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sampleFormat);
658
659 headers.width = width;
660 headers.height = height;
661 headers.channels = channels;
662 headers.type = IMAGE_TYPE_UNKNOWN;
663
664 if (bits == 8) {
665 switch(sampleFormat) {
666 case SAMPLEFORMAT_UINT:
667 headers.type = IMAGE_TYPE_UINT8;
668 break;
669 case SAMPLEFORMAT_INT:
670 headers.type = IMAGE_TYPE_SINT8;
671 break;
672 case SAMPLEFORMAT_IEEEFP:
673 headers.type = IMAGE_TYPE_FLOAT;
674 break;
675 default:
676 break;
677 }
678 } else if (bits == 16) {
679 switch(sampleFormat) {
680 case SAMPLEFORMAT_UINT:
681 headers.type = IMAGE_TYPE_UINT16;
682 break;
683 case SAMPLEFORMAT_INT:
684 headers.type = IMAGE_TYPE_SINT16;
685 break;
686 case SAMPLEFORMAT_IEEEFP:
687 headers.type = IMAGE_TYPE_FLOAT;
688 break;
689 default:
690 break;
691 }
692 } else if (bits == 32) {
693 switch(sampleFormat) {
694 case SAMPLEFORMAT_UINT:
695 headers.type = IMAGE_TYPE_UINT32;
696 break;
697 case SAMPLEFORMAT_INT:
698 headers.type = IMAGE_TYPE_SINT32;
699 break;
700 case SAMPLEFORMAT_IEEEFP:
701 headers.type = IMAGE_TYPE_FLOAT;
702 break;
703 default:
704 break;
705 }
706 } else if (bits == 64) {
707 switch(sampleFormat) {
708 case SAMPLEFORMAT_UINT:
709 headers.type = IMAGE_TYPE_UINT64;
710 break;
711 case SAMPLEFORMAT_INT:
712 headers.type = IMAGE_TYPE_SINT64;
713 break;
714 case SAMPLEFORMAT_IEEEFP:
715 headers.type = IMAGE_TYPE_FLOAT;
716 break;
717 default:
718 break;
719 }
720 }
721
722 if (headers.type == IMAGE_TYPE_UNKNOWN){
723 throw util::Exception("TIFF file has unsupported bits and/or sample format.");
724 }
725
726 TIFFClose(tif);
727 return headers;
728 }
729 catch (std::exception& e)
730 {
731 TIFFClose(tif);
732 throw;
733 }
734}
735
737load_tiff_file (std::string const& filename)
738{
739 TIFFSetWarningHandler(nullptr);
740 TIFFSetErrorHandler(tiff_error_handler);
741
742 TIFF* tif = TIFFOpen(filename.c_str(), "r");
743 if (!tif)
744 throw util::Exception("TIFF file format not recognized");
745
746 try
747 {
748 /* Read width and height from TIFF and create MVE image. */
749 uint32_t width, height;
750 uint16_t channels, bits;
751 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
752 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
753 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &channels);
754 TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits);
755 if (bits != 8)
756 throw util::Exception("Expected 8 bit TIFF file");
757 ByteImage::Ptr image = ByteImage::create(width, height, channels);
758
759 /* Scanline based TIFF reading. */
760 uint32_t rowstride = TIFFScanlineSize(tif);
761 ByteImage::ImageData& data = image->get_data();
762 for (uint32_t row = 0; row < height; row++)
763 {
764 tdata_t row_pointer = &data[row * rowstride];
765 TIFFReadScanline(tif, row_pointer, row);
766 }
767
768 TIFFClose(tif);
769 return image;
770 }
771 catch (std::exception& e)
772 {
773 TIFFClose(tif);
774 throw;
775 }
776}
777
778void
779save_tiff_file (ByteImage::ConstPtr image, std::string const& filename)
780{
781 if (image == nullptr)
782 throw std::invalid_argument("Null image given");
783
784 TIFF* tif = TIFFOpen(filename.c_str(), "w");
785 if (!tif)
786 throw util::FileException(filename, "Unknown TIFF file error");
787
788 uint32_t width = image->width();
789 uint32_t height = image->height();
790 uint32_t channels = image->channels();
791 TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
792 TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
793 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, channels);
794 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
795 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
796 TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
797 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
798
799 tdata_t buffer = const_cast<uint8_t*>(image->get_data_pointer());
800 int64_t ret = TIFFWriteEncodedStrip(tif, 0, buffer,
801 image->get_value_amount());
802
803 TIFFClose(tif);
804
805 if (ret < 0)
806 throw util::Exception("Error writing TIFF image");
807}
808
810load_tiff_16_file (std::string const& filename)
811{
812 if (sizeof(uint16_t) != 2)
813 throw util::Exception("Need 16bit data type for TIFF image.");
814
815 TIFFSetWarningHandler(nullptr);
816 TIFFSetErrorHandler(tiff_error_handler);
817
818 TIFF* tif = TIFFOpen(filename.c_str(), "r");
819 if (!tif)
820 throw util::Exception("TIFF file format not recognized");
821
822 try
823 {
824 /* Read width and height from TIFF and create MVE image. */
825 uint32_t width, height;
826 uint16_t channels, bits;
827 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
828 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
829 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &channels);
830 TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits);
831 if (bits != 16)
832 throw util::Exception("TIFF file bits per sample don't match");
833
834 RawImage::Ptr image = Image<uint16_t>::create(width, height, channels);
835
836 /* Scanline based TIFF reading. */
837 uint32_t rowstride = TIFFScanlineSize(tif) / sizeof(uint16_t);
838 Image<uint16_t>::ImageData& data = image->get_data();
839 for (uint32_t row = 0; row < height; row++)
840 {
841 tdata_t row_pointer = &data[row * rowstride];
842 TIFFReadScanline(tif, row_pointer, row);
843 }
844
845 TIFFClose(tif);
846 return image;
847 }
848 catch (std::exception& e)
849 {
850 TIFFClose(tif);
851 throw;
852 }
853}
854
855void
856save_tiff_16_file (RawImage::ConstPtr image, std::string const& filename)
857{
858 if (image == nullptr)
859 throw std::invalid_argument("Null image given");
860
861 TIFF* tif = TIFFOpen(filename.c_str(), "w");
862 if (!tif)
863 throw util::FileException(filename, "Unknown TIFF file error");
864
865 uint32_t width = image->width();
866 uint32_t height = image->height();
867 uint32_t channels = image->channels();
868 TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
869 TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
870 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, channels);
871 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8 * sizeof(uint16_t));
872 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
873 TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
874 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
875
876 tdata_t buffer = const_cast<uint16_t*>(image->get_data_pointer());
877 int64_t ret = TIFFWriteEncodedStrip(tif, 0, buffer,
878 image->get_value_amount() * sizeof(uint16_t));
879
880 TIFFClose(tif);
881
882 if (ret < 0)
883 throw util::Exception("Error writing TIFF image");
884}
885
887load_tiff_float_file (std::string const& filename)
888{
889 if (sizeof(float) != 4)
890 throw util::Exception("Need 32bit data type for TIFF image.");
891
892 TIFFSetWarningHandler(nullptr);
893 TIFFSetErrorHandler(tiff_error_handler);
894
895 TIFF* tif = TIFFOpen(filename.c_str(), "r");
896 if (!tif)
897 throw util::Exception("TIFF file format not recognized");
898
899 try
900 {
901 /* Read width and height from TIFF and create MVE image. */
902 uint32_t width, height;
903 uint16_t channels, bits;
904 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
905 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
906 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &channels);
907 TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits);
908 if (bits != 32)
909 throw util::Exception("TIFF file bits per sample don't match");
910
911 FloatImage::Ptr image = Image<float>::create(width, height, channels);
912
913 /* Scanline based TIFF reading. */
914 uint32_t rowstride = TIFFScanlineSize(tif) / sizeof(float);
915 Image<float>::ImageData& data = image->get_data();
916 for (uint32_t row = 0; row < height; row++)
917 {
918 tdata_t row_pointer = &data[row * rowstride];
919 TIFFReadScanline(tif, row_pointer, row);
920 }
921
922 TIFFClose(tif);
923 return image;
924 }
925 catch (std::exception& e)
926 {
927 TIFFClose(tif);
928 throw;
929 }
930}
931
932void
933save_tiff_float_file (FloatImage::ConstPtr image, std::string const& filename)
934{
935 if (image == nullptr)
936 throw std::invalid_argument("Null image given");
937
938 TIFF* tif = TIFFOpen(filename.c_str(), "w");
939 if (!tif)
940 throw util::FileException(filename, "Unknown TIFF file error");
941
942 uint32_t width = image->width();
943 uint32_t height = image->height();
944 uint32_t channels = image->channels();
945 TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
946 TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
947 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, channels);
948 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8 * sizeof(float));
949 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
950 TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
951 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
952 TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
953
954 tdata_t buffer = const_cast<float*>(image->get_data_pointer());
955 int64_t ret = TIFFWriteEncodedStrip(tif, 0, buffer,
956 image->get_value_amount() * sizeof(float));
957
958 TIFFClose(tif);
959
960 if (ret < 0)
961 throw util::Exception("Error writing TIFF image");
962}
963
964#endif /* MVE_NO_TIFF_SUPPORT */
965
966/* ---------------------------------------------------------------- */
967
968/*
969 * PFM file format for float images.
970 * http://netpbm.sourceforge.net/doc/pfm.html
971 * FIXME: Convert to C++ I/O (std::fstream)
972 */
973
975load_pfm_file (std::string const& filename)
976{
977 std::ifstream in(filename.c_str(), std::ios::binary);
978 if (!in.good())
979 throw util::FileException(filename, std::strerror(errno));
980
981 char signature[2];
982 in.read(signature, 2);
983
984 // check signature and determine channels
985 int channels = 0;
986 if (signature[0] == 'P' && signature[1] == 'f')
987 channels = 1;
988 else if (signature[0] == 'P' && signature[1] == 'F')
989 channels = 3;
990 else
991 {
992 in.close();
993 throw util::Exception("PPM signature did not match");
994 }
995
996 /* Read width and height as well as max value. */
997 int width = 0;
998 int height = 0;
999 float scale = -1.0;
1000 in >> width >> height >> scale;
1001
1002 /* Read final whitespace character. */
1003 char temp;
1004 in.read(&temp, 1);
1005
1006 /* Check image width and height. Shouldn't be too large. */
1007 if (width * height > PPM_MAX_PIXEL_AMOUNT)
1008 {
1009 in.close();
1010 throw util::Exception("Image too friggin huge");
1011 }
1012
1013 /* Read image rows in reverse order according to PFM specification. */
1014 FloatImage::Ptr image = FloatImage::create(width, height, channels);
1015 std::size_t row_size = image->get_byte_size() / image->height();
1016 char* ptr = reinterpret_cast<char*>(image->end()) - row_size;
1017 for (int y = 0; y < height; ++y, ptr -= row_size)
1018 in.read(ptr, row_size);
1019 in.close();
1020
1021 /* Handle endianess. BE if scale > 0, LE if scale < 0. */
1022 if (scale < 0.0f)
1023 {
1024 std::transform(image->begin(), image->end(), image->begin(),
1025 (float(*)(float const&))util::system::letoh<float>);
1026 scale = -scale;
1027 }
1028 else
1029 {
1030 std::transform(image->begin(), image->end(), image->begin(),
1031 (float(*)(float const&))util::system::betoh<float>);
1032 }
1033
1034 /* Handle scale. Multiply image values if scale is not 1.0. */
1035 if (scale != 1.0f)
1036 {
1037 std::for_each(image->begin(), image->end(),
1039 }
1040
1041 return image;
1042}
1043
1044void
1045save_pfm_file (FloatImage::ConstPtr image, std::string const& filename)
1046{
1047 if (image == nullptr)
1048 throw std::invalid_argument("Null image given");
1049
1050 std::string magic_number;
1051 if (image->channels() == 1)
1052 magic_number = "Pf";
1053 else if (image->channels() == 3)
1054 magic_number = "PF";
1055 else
1056 throw std::invalid_argument("Supports 1 and 3 channel images only");
1057
1058#ifdef HOST_BYTEORDER_LE
1059 std::string scale = "-1.0"; // we currently don't support scales
1060#else
1061 std::string scale = "1.0"; // we currently don't support scales
1062#endif
1063
1064 std::ofstream out(filename.c_str(), std::ios::binary);
1065 if (!out.good())
1066 throw util::FileException(filename, std::strerror(errno));
1067
1068 out << magic_number << "\n";
1069 out << image->width() << " " << image->height() << " " << scale << "\n";
1070
1071 /* Output rows in reverse order according to PFM specification. */
1072 std::size_t row_size = image->get_byte_size() / image->height();
1073 char const* ptr = reinterpret_cast<char const*>(image->end()) - row_size;
1074 for (int y = 0; y < image->height(); ++y, ptr -= row_size)
1075 out.write(ptr, row_size);
1076 out.close();
1077}
1078
1079/* ---------------------------------------------------------------- */
1080
1081/*
1082 * PPM file format for 8 and 16 bit images. The bit8 argument is set to
1083 * true, 8 bit PPMs with maxval set to less than 256 are loaded.
1084 * Otherwise, 16 bit PPMs with maxval less than 65536 are loaded.
1085 * http://netpbm.sourceforge.net/doc/ppm.html
1086 */
1088load_ppm_file_intern (std::string const& filename, bool bit8)
1089{
1090 std::ifstream in(filename.c_str(), std::ios::binary);
1091 if (!in.good())
1092 throw util::FileException(filename, std::strerror(errno));
1093
1094 char signature[2];
1095 in.read(signature, 2);
1096
1097 // check signature and determine channels
1098 int channels = 0;
1099 if (signature[0] == 'P' && signature[1] == '5')
1100 channels = 1;
1101 else if (signature[0] == 'P' && signature[1] == '6')
1102 channels = 3;
1103 else
1104 {
1105 in.close();
1106 throw util::Exception("PPM signature did not match");
1107 }
1108
1109 /* Read width and height as well as max value. */
1110 int width = 0;
1111 int height = 0;
1112 int maxval = 0;
1113 in >> width >> height >> maxval;
1114
1115 /* Read final whitespace character. */
1116 char temp;
1117 in.read(&temp, 1);
1118
1119 /* Check image width and height. Shouldn't be too large. */
1120 if (width * height > PPM_MAX_PIXEL_AMOUNT)
1121 {
1122 in.close();
1123 throw util::Exception("Image too friggin huge");
1124 }
1125
1126 ImageBase::Ptr ret;
1127
1128 /* Max value should be in <256 for 8 bit and <65535 for 16 bit. */
1129 if (maxval < 256 && bit8)
1130 {
1131 /* Read image content. */
1132 ByteImage::Ptr image = ByteImage::create(width, height, channels);
1133 in.read(image->get_byte_pointer(), image->get_byte_size());
1134 ret = image;
1135 }
1136 else if (maxval < 65536 && !bit8)
1137 {
1138 /* Read image content, convert from big-endian to host order. */
1139 RawImage::Ptr image = RawImage::create(width, height, channels);
1140 in.read(image->get_byte_pointer(), image->get_byte_size());
1141 for (int i = 0; i < image->get_value_amount(); ++i)
1142 image->at(i) = util::system::betoh(image->at(i));
1143 ret = image;
1144 }
1145 else
1146 {
1147 in.close();
1148 throw util::Exception("PPM max value is invalid");
1149 }
1150
1151 in.close();
1152 return ret;
1153}
1154
1156load_ppm_16_file (std::string const& filename)
1157{
1158 return std::dynamic_pointer_cast<RawImage>
1159 (load_ppm_file_intern(filename, false));
1160}
1161
1163load_ppm_file (std::string const& filename)
1164{
1165 return std::dynamic_pointer_cast<ByteImage>
1166 (load_ppm_file_intern(filename, true));
1167}
1168
1169void
1170save_ppm_file_intern (ImageBase::ConstPtr image, std::string const& filename)
1171{
1172 if (image == nullptr)
1173 throw std::invalid_argument("Null image given");
1174
1175 std::string magic_number;
1176 if (image->channels() == 1)
1177 magic_number = "P5";
1178 else if (image->channels() == 3)
1179 magic_number = "P6";
1180 else
1181 throw std::invalid_argument("Supports 1 and 3 channel images only");
1182
1183 int maxval = 0;
1184 if (image->get_type() == IMAGE_TYPE_UINT8)
1185 maxval = 255;
1186 else if (image->get_type() == IMAGE_TYPE_UINT16)
1187 maxval = 65535;
1188 else
1189 throw std::invalid_argument("Invalid image format");
1190
1191 std::ofstream out(filename.c_str(), std::ios::binary);
1192 if (!out.good())
1193 throw util::FileException(filename, std::strerror(errno));
1194
1195 out << magic_number << "\n";
1196 out << image->width() << " " << image->height() << " " << maxval << "\n";
1197
1198 if (image->get_type() == IMAGE_TYPE_UINT8)
1199 {
1200 /* Byte images can be saved as-is. */
1201 out.write(image->get_byte_pointer(), image->get_byte_size());
1202 }
1203 else
1204 {
1205 /* PPM is big-endian, so we need to convert 16 bit data. */
1206 RawImage::ConstPtr handle
1207 = std::dynamic_pointer_cast<RawImage const>(image);
1208 for (int i = 0; i < handle->get_value_amount(); ++i)
1209 {
1210 RawImage::ValueType value = util::system::betoh(handle->at(i));
1211 out.write((char const*)(&value), sizeof(RawImage::ValueType));
1212 }
1213 }
1214 out.close();
1215}
1216
1217void
1218save_ppm_16_file (RawImage::ConstPtr image, std::string const& filename)
1219{
1220 save_ppm_file_intern(image, filename);
1221}
1222
1223void
1224save_ppm_file (ByteImage::ConstPtr image, std::string const& filename)
1225{
1226 save_ppm_file_intern(image, filename);
1227}
1228
1229/* ---------------------------------------------------------------- */
1230
1231namespace
1232{
1233 void
1234 load_mvei_headers_intern (std::istream& in, ImageHeaders* headers)
1235 {
1236 char signature[MVEI_FILE_SIGNATURE_LEN];
1237 in.read(signature, MVEI_FILE_SIGNATURE_LEN);
1238 if (!std::equal(signature, signature + MVEI_FILE_SIGNATURE_LEN,
1240 throw util::Exception("Invalid file signature");
1241
1242 /* Read image headers data, */
1243 int32_t width, height, channels, raw_type;
1244 in.read(reinterpret_cast<char*>(&width), sizeof(int32_t));
1245 in.read(reinterpret_cast<char*>(&height), sizeof(int32_t));
1246 in.read(reinterpret_cast<char*>(&channels), sizeof(int32_t));
1247 in.read(reinterpret_cast<char*>(&raw_type), sizeof(int32_t));
1248
1249 if (!in.good())
1250 throw util::Exception("Error reading headers");
1251
1252 headers->width = width;
1253 headers->height = height;
1254 headers->channels = channels;
1255 headers->type = static_cast<ImageType>(raw_type);
1256 }
1257}
1258
1259ImageBase::Ptr
1260load_mvei_file (std::string const& filename)
1261{
1262 std::ifstream in(filename.c_str(), std::ios::binary);
1263 if (!in.good())
1264 throw util::FileException(filename, std::strerror(errno));
1265
1266 /* Load image header data. */
1267 ImageHeaders headers;
1268 load_mvei_headers_intern(in, &headers);
1269 if (headers.width * headers.height > MVEI_MAX_PIXEL_AMOUNT)
1270 throw util::Exception("Ridiculously large image");
1271
1272 /* Load image data. */
1273 ImageBase::Ptr image = create_for_type(headers.type,
1274 headers.width, headers.height, headers.channels);
1275 in.read(image->get_byte_pointer(), image->get_byte_size());
1276 if (!in.good())
1277 throw util::FileException(filename, std::strerror(errno));
1278
1279 return image;
1280}
1281
1282ImageHeaders
1283load_mvei_file_headers (std::string const& filename)
1284{
1285 std::ifstream in(filename.c_str(), std::ios::binary);
1286 if (!in.good())
1287 throw util::FileException(filename, std::strerror(errno));
1288
1289 ImageHeaders headers;
1290 load_mvei_headers_intern(in, &headers);
1291 return headers;
1292}
1293
1294void
1295save_mvei_file (ImageBase::ConstPtr image, std::string const& filename)
1296{
1297 if (image == nullptr)
1298 throw std::invalid_argument("Null image given");
1299
1300 // Note: This is a narrowing conversion.
1301 int32_t width = static_cast<int32_t>(image->width());
1302 int32_t height = static_cast<int32_t>(image->height());
1303 int32_t channels = static_cast<int32_t>(image->channels());
1304 int32_t type = image->get_type();
1305 char const* data = image->get_byte_pointer();
1306 std::size_t size = image->get_byte_size();
1307
1308 std::ofstream out(filename.c_str(), std::ios::binary);
1309 if (!out.good())
1310 throw util::FileException(filename, std::strerror(errno));
1311
1313 out.write(reinterpret_cast<char const*>(&width), sizeof(int32_t));
1314 out.write(reinterpret_cast<char const*>(&height), sizeof(int32_t));
1315 out.write(reinterpret_cast<char const*>(&channels), sizeof(int32_t));
1316 out.write(reinterpret_cast<char const*>(&type), sizeof(int32_t));
1317 out.write(data, size);
1318
1319 if (!out.good())
1320 throw util::FileException(filename, std::strerror(errno));
1321}
1322
1325
std::shared_ptr< ImageBase const > ConstPtr
Definition image_base.h:56
std::shared_ptr< ImageBase > Ptr
Definition image_base.h:55
Multi-channel image class of arbitrary but homogenous data type.
Definition image.h:40
std::shared_ptr< Image< T > > Ptr
Definition image.h:42
std::shared_ptr< Image< T > const > ConstPtr
Definition image.h:43
std::vector< T > ImageData
Definition image.h:44
T ValueType
Definition image.h:45
Universal, simple exception class.
Definition exception.h:24
virtual const char * what(void) const
Definition exception.h:43
Exception class for file exceptions with additional filename.
Definition exception.h:53
#define MVEI_FILE_SIGNATURE
Definition image_io.cc:45
#define MVEI_FILE_SIGNATURE_LEN
Definition image_io.cc:46
#define PPM_MAX_PIXEL_AMOUNT
Definition image_io.cc:42
#define MVEI_MAX_PIXEL_AMOUNT
Definition image_io.cc:47
#define MVE_IMAGE_NAMESPACE_END
Definition defines.h:17
#define MVE_NAMESPACE_BEGIN
Definition defines.h:13
#define MVE_IMAGE_NAMESPACE_BEGIN
Definition defines.h:16
#define MVE_NAMESPACE_END
Definition defines.h:14
void save_tiff_float_file(FloatImage::ConstPtr image, std::string const &filename)
Writes a 32bit float TIFF to file.
Definition image_io.cc:933
void save_mvei_file(ImageBase::ConstPtr image, std::string const &filename)
Writes a native MVE image.
Definition image_io.cc:1295
void tiff_error_handler(char const *, char const *fmt, va_list ap)
Definition image_io.cc:631
void save_ppm_16_file(RawImage::ConstPtr image, std::string const &filename)
Save a 16 bit PPM file.
Definition image_io.cc:1218
ByteImage::Ptr load_png_file(std::string const &filename)
Loads a PNG file.
Definition image_io.cc:278
ByteImage::Ptr load_file(std::string const &filename)
Loads an image, detecting file type.
Definition image_io.cc:57
ByteImage::Ptr load_tiff_file(std::string const &filename)
Loads a TIFF file.
Definition image_io.cc:737
RawImage::Ptr load_tiff_16_file(std::string const &filename)
Loads a 16bit TIFF file.
Definition image_io.cc:810
FloatImage::Ptr load_tiff_float_file(std::string const &filename)
Loads a 32bit float TIFF file.
Definition image_io.cc:887
ImageBase::Ptr load_mvei_file(std::string const &filename)
Loads a native MVE image.
Definition image_io.cc:1260
void save_ppm_file_intern(ImageBase::ConstPtr image, std::string const &filename)
Definition image_io.cc:1170
ImageHeaders load_file_headers(std::string const &filename)
Loads the image headers, detecting file type.
Definition image_io.cc:107
ImageHeaders load_mvei_file_headers(std::string const &filename)
Loads the meta information for a native MVE image.
Definition image_io.cc:1283
ByteImage::Ptr load_ppm_file(std::string const &filename)
Loads a 8 bit PPM file.
Definition image_io.cc:1163
RawImage::Ptr load_ppm_16_file(std::string const &filename)
Loads a 16 bit PPM file.
Definition image_io.cc:1156
void save_jpg_file(ByteImage::ConstPtr image, std::string const &filename, int quality)
Saves image data to a JPEG file.
Definition image_io.cc:580
ImageHeaders load_png_file_headers(std::string const &filename)
Loads PNG file headers only.
Definition image_io.cc:334
void save_pfm_file(FloatImage::ConstPtr image, std::string const &filename)
Saves float image data to PFM file.
Definition image_io.cc:1045
void save_tiff_file(ByteImage::ConstPtr image, std::string const &filename)
Writes a TIFF to file.
Definition image_io.cc:779
void save_ppm_file(ByteImage::ConstPtr image, std::string const &filename)
Writes a 8 bit PPM file.
Definition image_io.cc:1224
void jpg_message_handler(j_common_ptr, int msg_level)
Definition image_io.cc:447
void save_png_file(ByteImage::ConstPtr image, std::string const &filename, int compression_level)
Saves image data to a PNG file.
Definition image_io.cc:354
ByteImage::Ptr load_jpg_file(std::string const &filename, std::string *exif)
Loads a JPEG file.
Definition image_io.cc:454
void save_tiff_16_file(RawImage::ConstPtr image, std::string const &filename)
Writes a 16bit TIFF to file.
Definition image_io.cc:856
ImageBase::Ptr create_for_type(ImageType type, int64_t width, int64_t height, int64_t chans)
Creates an image instance for a given type.
Definition image.h:137
void save_file(ByteImage::ConstPtr image, std::string const &filename)
Saves a byte image to file, detecting file type.
Definition image_io.cc:146
ImageHeaders load_jpg_file_headers(std::string const &filename)
Loads JPEG file headers only.
Definition image_io.cc:533
ImageBase::Ptr load_ppm_file_intern(std::string const &filename, bool bit8)
Definition image_io.cc:1088
FloatImage::Ptr load_pfm_file(std::string const &filename)
Loads a PFM file.
Definition image_io.cc:975
ImageHeaders load_tiff_file_headers(std::string const &filename)
Loads TIFF file headers only.
Definition image_io.cc:639
void jpg_error_handler(j_common_ptr)
Definition image_io.cc:441
ImageType
Identifiers for image types.
Definition image_base.h:28
@ IMAGE_TYPE_UINT64
Definition image_base.h:34
@ IMAGE_TYPE_UINT32
Definition image_base.h:33
@ IMAGE_TYPE_UINT16
Definition image_base.h:32
@ IMAGE_TYPE_UINT8
Definition image_base.h:31
@ IMAGE_TYPE_SINT16
Definition image_base.h:37
@ IMAGE_TYPE_SINT32
Definition image_base.h:38
@ IMAGE_TYPE_UNKNOWN
Definition image_base.h:29
@ IMAGE_TYPE_SINT8
Definition image_base.h:36
@ IMAGE_TYPE_SINT64
Definition image_base.h:39
@ IMAGE_TYPE_FLOAT
Definition image_base.h:41
String conversions and helper functions.
Definition defines.h:35
T betoh(T const &x)
Big endian to host order conversion.
for-each functor: multiplies operand with constant factor.
Definition algo.h:223
Image meta data.
Definition image_io.h:26