licornea_tools
raw_image_io.cc
Go to the documentation of this file.
1 #include "raw_image_io.h"
2 #include "opencv.h"
3 #include <fstream>
4 
5 namespace tlz {
6 
7 namespace {
8 
9 template<typename T>
10 void read_raw(std::ifstream& stream, T* out, std::size_t length) {
11  stream.read(reinterpret_cast<std::ifstream::char_type*>(out), length);
12 }
13 
14 template<typename T>
15 void write_raw(std::ofstream& stream, const T* in, std::size_t length) {
16  stream.write(reinterpret_cast<const std::ifstream::char_type*>(in), length);
17 }
18 
19 
20 
21 cv::Mat_<cv::Vec3b> import_ycbcr420(std::ifstream& yuv_stream, int width, int height) {
22  cv::Size sz(width, height);
23  cv::Size sub_sz(width/2, height/2);
24 
25  cv::Mat_<uchar> y_channel(sz);
26  read_raw(yuv_stream, y_channel.data, width*height);
27 
28  cv::Mat_<uchar> cb_channel(sub_sz);
29  read_raw(yuv_stream, cb_channel.data, width*height/4);
30  cv::resize(cb_channel, cb_channel, sz, 0, 0, cv::INTER_CUBIC);
31 
32  cv::Mat_<uchar> cr_channel(sub_sz);
33  read_raw(yuv_stream, cr_channel.data, width*height/4);
34  cv::resize(cr_channel, cr_channel, sz, 0, 0, cv::INTER_CUBIC);
35 
36  cv::Mat_<cv::Vec3b> ycrcb;
37  std::vector<cv::Mat> src {y_channel, cr_channel, cb_channel};
38  cv::merge(src, ycrcb);
39 
40  cv::Mat_<cv::Vec3b> bgr;
41  cv::cvtColor(ycrcb, bgr, CV_YCrCb2BGR);
42 
43  return bgr;
44 }
45 
46 void export_ycbcr420(std::ofstream& yuv_stream, const cv::Mat_<cv::Vec3b>& bgr) {
47  cv::Size sz = bgr.size();
48  cv::Size sub_sz(sz.width/2, sz.height/2);
49 
50  cv::Mat_<cv::Vec3b> ycrcb;
51  cv::cvtColor(bgr, ycrcb, CV_BGR2YCrCb);
52 
53  cv::Mat_<uchar> y_channel(sz), cb_channel(sz), cr_channel(sz);
54  std::vector<cv::Mat> dst { y_channel, cr_channel, cb_channel };
55  cv::split(ycrcb, dst);
56  cv::resize(cb_channel, cb_channel, sub_sz, 0, 0, cv::INTER_CUBIC);
57  cv::resize(cr_channel, cr_channel, sub_sz, 0, 0, cv::INTER_CUBIC);
58 
59  write_raw(yuv_stream, y_channel.data, y_channel.cols*y_channel.rows);
60  write_raw(yuv_stream, cb_channel.data, cb_channel.cols*cb_channel.rows);
61  write_raw(yuv_stream, cr_channel.data, cr_channel.cols*cr_channel.rows);
62 }
63 
64 
65 cv::Mat_<cv::Vec3b> import_rgb_planar(std::ifstream& yuv_stream, int width, int height) {
66  cv::Size sz(width, height);
67 
68  cv::Mat_<uchar> r_channel(sz);
69  read_raw(yuv_stream, r_channel.data, width*height);
70 
71  cv::Mat_<uchar> g_channel(sz);
72  read_raw(yuv_stream, g_channel.data, width*height);
73 
74  cv::Mat_<uchar> b_channel(sz);
75  read_raw(yuv_stream, b_channel.data, width*height);
76 
77  cv::Mat_<cv::Vec3b> bgr(sz);
78  int from_to[] = { 0, 0, 0, 1, 0, 2 };
79  std::vector<cv::Mat> dst { bgr };
80  std::vector<cv::Mat> src { b_channel, g_channel, r_channel };
81  cv::mixChannels(src, dst, from_to, 3);
82 
83  return bgr;
84 }
85 
86 void export_rgb_planar(std::ofstream& yuv_stream, const cv::Mat_<cv::Vec3b>& bgr) {
87  cv::Size sz = bgr.size();
88 
89  cv::Mat_<uchar> r_channel(sz), g_channel(sz), b_channel(sz);
90  std::vector<cv::Mat> dst { b_channel, g_channel, r_channel };
91  cv::split(bgr, dst);
92 
93  write_raw(yuv_stream, r_channel.data, sz.width*sz.height);
94  write_raw(yuv_stream, g_channel.data, sz.width*sz.height);
95  write_raw(yuv_stream, b_channel.data, sz.width*sz.height);
96 }
97 
98 
99 
100 cv::Mat_<cv::Vec3b> import_rgb_interleaved(std::ifstream& yuv_stream, int width, int height) {
101  cv::Size sz(width, height);
102  cv::Mat_<uchar> rgb(sz);
103  read_raw(yuv_stream, rgb.data, 3*width*height);
104  cv::Mat_<uchar> bgr;
105  cv::cvtColor(rgb, bgr, CV_RGB2BGR);
106  return bgr;
107 }
108 
109 void export_rgb_interleaved(std::ofstream& yuv_stream, const cv::Mat_<cv::Vec3b>& bgr) {
110  cv::Mat_<cv::Vec3b> rgb;
111  cv::cvtColor(bgr, rgb, CV_BGR2RGB);
112  write_raw(yuv_stream, rgb.data, 3*rgb.cols*rgb.rows);
113 }
114 
115 
116 
117 }
118 
119 cv::Mat import_raw_color(const std::string& yuv_filename, int width, int height, raw_image_format form) {
120  std::ifstream yuv_stream(yuv_filename, std::ios_base::binary);
121  switch(form) {
122  case raw_image_format::ycbcr420: return import_ycbcr420(yuv_stream, width, height);
123  case raw_image_format::rgb_planar: return import_rgb_planar(yuv_stream, width, height);
124  case raw_image_format::rgb_interleaved: return import_rgb_interleaved(yuv_stream, width, height);
125  default: throw std::invalid_argument("invalid raw image format");
126  }
127 }
128 
129 
130 cv::Mat import_raw_mono(const std::string& yuv_filename, int width, int height, int bit_depth) {
131  int type;
132  switch(bit_depth) {
133  case 8: type = CV_8U; break;
134  case 16: type = CV_16U; break;
135  default: throw std::invalid_argument("invalid raw image bit depth");
136  }
137  cv::Mat mat(height, width, type);
138  int length = width * height * bit_depth/8;
139  std::ifstream yuv_stream(yuv_filename, std::ios_base::binary);
140  read_raw(yuv_stream, mat.data, length);
141  return mat;
142 }
143 
144 
145 void export_raw_color(const cv::Mat& img, const std::string& yuv_filename, raw_image_format form) {
146  std::ofstream yuv_stream(yuv_filename, std::ios_base::binary);
147  switch(form) {
148  case raw_image_format::ycbcr420: export_ycbcr420(yuv_stream, img); break;
149  case raw_image_format::rgb_planar: export_rgb_planar(yuv_stream, img); break;
150  case raw_image_format::rgb_interleaved: export_rgb_interleaved(yuv_stream, img); break;
151  default: throw std::invalid_argument("invalid raw image format");
152  }
153 }
154 
155 
156 void export_raw_mono(const cv::Mat& img, const std::string& yuv_filename, int out_bit_depth) {
157  int type;
158  int in_bit_depth;
159  switch(img.depth()) {
160  case CV_8U: in_bit_depth = 8; break;
161  case CV_16U: in_bit_depth = 16; break;
162  default: throw std::invalid_argument("invalid input image bit depth");
163  }
164  switch(out_bit_depth) {
165  case 8: type = CV_8U; break;
166  case 16: type = CV_16U; break;
167  default: throw std::invalid_argument("invalid raw image bit depth");
168  }
169  real alpha = std::exp2(out_bit_depth - in_bit_depth);
170  cv::Mat out_mat;
171  img.convertTo(out_mat, type, alpha);
172  int length = img.cols * img.rows * out_bit_depth/8;
173  std::ofstream yuv_stream(yuv_filename, std::ios_base::binary);
174  write_raw(yuv_stream, out_mat.data, length);
175 }
176 
177 
178 }
void export_raw_color(const cv::Mat &img, const std::string &yuv_filename, raw_image_format form)
void export_raw_mono(const cv::Mat &img, const std::string &yuv_filename, int out_bit_depth)
cv::Mat import_raw_mono(const std::string &yuv_filename, int width, int height, int bit_depth)
cv::Mat import_raw_color(const std::string &yuv_filename, int width, int height, raw_image_format form)
double real
Definition: common.h:16
raw_image_format
Definition: raw_image_io.h:8