UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
qtp.cpp
1// UFO
2#include <ufo/io/qtp.hpp>
3
4// STL
5#include <cstddef>
6#include <cstring>
7#include <filesystem>
8#include <format>
9#include <stdexcept>
10
11// JPEG
12#include <jerror.h>
13#include <jpeglib.h> // Include after cstddef to define size_t
14
15namespace ufo
16{
17namespace detail
18{
19void jpeg_error_throw(j_common_ptr p_cinfo)
20{
21 if (p_cinfo->is_decompressor) {
22 jpeg_destroy_decompress(reinterpret_cast<jpeg_decompress_struct*>(p_cinfo));
23 } else {
24 jpeg_destroy_compress(reinterpret_cast<jpeg_compress_struct*>(p_cinfo));
25 }
26
27 char buffer[JMSG_LENGTH_MAX];
28 (*p_cinfo->err->format_message)(p_cinfo, buffer);
29 throw std::runtime_error(buffer);
30}
31
32bool readQTP(FileHandler fp, std::uint8_t* image)
33{
34 jpeg_decompress_struct cinfo;
35 jpeg_error_mgr jerr;
36 JSAMPARRAY buffer;
37
38 try {
39 cinfo.err = jpeg_std_error(&jerr);
40 jerr.error_exit = jpeg_error_throw;
41 jpeg_create_decompress(&cinfo);
42 jpeg_stdio_src(&cinfo, fp.get());
43 jpeg_read_header(&cinfo, TRUE);
44
45 // We only support two channel types: RGB and Gray
46 int num_of_channels = 3;
47 int bytes_per_channel = 1;
48 switch (cinfo.jpeg_color_space) {
49 case JCS_RGB:
50 case JCS_YCbCr:
51 cinfo.out_color_space = JCS_RGB;
52 cinfo.out_color_components = 3;
53 num_of_channels = 3;
54 break;
55 case JCS_GRAYSCALE:
56 cinfo.jpeg_color_space = JCS_GRAYSCALE;
57 cinfo.out_color_components = 1;
58 num_of_channels = 1;
59 break;
60 case JCS_CMYK:
61 case JCS_YCCK:
62 default:
63 std::println(stderr, "[UFO | Read JPEG] Color space not supported");
64 jpeg_destroy_decompress(&cinfo);
65 fp.close();
66 return false;
67 }
68
69 jpeg_start_decompress(&cinfo);
70 int row_stride = cinfo.output_width * cinfo.output_components;
71 buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);
72 while (cinfo.output_scanline < cinfo.output_height) {
73 jpeg_read_scanlines(&cinfo, buffer, 1);
74 std::memcpy(image, buffer[0], row_stride);
75 image += row_stride;
76 }
77 jpeg_finish_decompress(&cinfo);
78 jpeg_destroy_decompress(&cinfo);
79 fp.close();
80 return true;
81 } catch (std::runtime_error const& err) {
82 std::println(stderr, "[UFO | Read JPEG] libjpeg error: {}", err.what());
83 fp.close();
84 return false;
85 }
86}
87
88bool writeQTP(FileHandler& fp, std::uint8_t const* image, std::uint32_t width,
89 std::uint32_t height, int num_channels, int quality)
90{
91 jpeg_compress_struct cinfo;
92 jpeg_error_mgr jerr;
93 JSAMPROW row_pointer[1];
94
95 try {
96 cinfo.err = jpeg_std_error(&jerr);
97 jerr.error_exit = jpeg_error_throw;
98
99 jpeg_create_compress(&cinfo);
100 jpeg_stdio_dest(&cinfo, fp.get());
101
102 cinfo.image_width = width;
103 cinfo.image_height = height;
104 cinfo.input_components = num_channels;
105 cinfo.in_color_space = 1 == num_channels ? JCS_GRAYSCALE : JCS_RGB;
106
107 jpeg_set_defaults(&cinfo);
108 jpeg_set_quality(&cinfo, quality, TRUE);
109 jpeg_start_compress(&cinfo, TRUE);
110
111 int row_stride = width * num_channels;
112 std::vector<std::uint8_t> buffer(row_stride);
113 while (cinfo.next_scanline < cinfo.image_height) {
114 std::memcpy(buffer.data(), image, row_stride);
115 row_pointer[0] = buffer.data();
116 jpeg_write_scanlines(&cinfo, row_pointer, 1);
117 image += row_stride;
118 }
119
120 jpeg_finish_compress(&cinfo);
121 fp.close();
122 jpeg_destroy_compress(&cinfo);
123
124 return true;
125 } catch (std::runtime_error const& err) {
126 std::println(stderr, "[UFO | Write JPEG] Error: {}", err.what());
127 fp.close();
128
129 return false;
130 }
131}
132} // namespace detail
133
134ImageProperties imagePropertiesQTP(std::filesystem::path const& file)
135{
136 FileHandler fp(file.c_str(), "rb");
137
138 if (!fp) {
139 throw std::runtime_error(std::format(
140 "[UFO | Image Properties JPEG] Failed to open file: {}", file.string()));
141 }
142
143 jpeg_decompress_struct cinfo;
144 jpeg_error_mgr jerr;
145
146 try {
147 cinfo.err = jpeg_std_error(&jerr);
148 jerr.error_exit = detail::jpeg_error_throw;
149 jpeg_create_decompress(&cinfo);
150 jpeg_stdio_src(&cinfo, fp.get());
151 jpeg_read_header(&cinfo, TRUE);
152 } catch (std::runtime_error const& err) {
153 throw std::runtime_error(
154 std::format("[UFO | Read JPEG] libjpeg error: {}", err.what()));
155 fp.close();
156 }
157
158 if (JCS_GRAYSCALE != cinfo.jpeg_color_space && JCS_RGB != cinfo.jpeg_color_space &&
159 JCS_YCbCr != cinfo.jpeg_color_space) {
160 jpeg_destroy_decompress(&cinfo);
161 fp.close();
162 throw std::runtime_error("[UFO | Read JPEG] Color space not supported");
163 }
164
165 ImageProperties prop;
166 prop.width = cinfo.image_width;
167 prop.height = cinfo.image_height;
168 prop.bit_depth = 8;
169 prop.alpha = false;
170 prop.grayscale = cinfo.jpeg_color_space == JCS_GRAYSCALE;
171
172 jpeg_destroy_decompress(&cinfo);
173
174 return prop;
175}
176} // namespace ufo
All vision-related classes and functions.
Definition cloud.hpp:49