2#pragma warning(disable:4996)
5#include "sliced_volume_io.h"
7#include <cgv/utils/file.h>
9#include <cgv/utils/dir.h>
10#include <cgv/os/cmdline_tools.h>
11#include <cgv/media/video/video_reader.h>
12#include <cgv/media/image/image_reader.h>
25 bool read_volume_from_video_with_ffmpeg(volume& V,
const std::string& file_name,
27 size_t offset, FlipType flip_t,
void (*on_progress_update)(
int,
void*),
void* user_data,
bool cycle_till_eof)
29 std::string fn_in_quotes = std::string(
"\"") + cgv::utils::file::platform_path(file_name) +
"\"";
30 if (dims(0) == -1 || dims(1) == -1 || dims(2) < 0) {
31 int w, h, n = dims(2);
33 std::string cmd =
"ffprobe -v error ";
35 cmd +=
"-count_frames ";
36 cmd +=
"-select_streams v:0 -show_entries stream=width,height";
38 cmd +=
",nb_read_frames";
41 cmd +=
" -show_entries side_data=rotation -of default=nokey=1:noprint_wrappers=1 ";
43 std::cout <<
"Analyze Video with " << cmd << std::endl;
44 std::string video_info = cgv::os::query_system_output(cmd,
false);
45 std::vector<cgv::utils::line> lines;
47 bool do_swap_sides =
false;
48 if (lines.size() >= 4) {
51 if (rot == 90 || rot == -90)
55 std::stringstream ss(video_info);
65 std::cerr <<
"Video file <" << file_name <<
"> does not support nb_frames - need to could frames, please wait!" << std::endl;
68 std::cerr <<
"Error: could not analyze video file <" << file_name <<
"> with ffprobe" << std::endl;
74 if (dims(2) < 0 && offset > n) {
75 std::cerr <<
"Error: frame offset " << offset <<
" larger than frame count of video file <" << file_name <<
"> with ffprobe" << std::endl;
80 extent(0) *= -dims(0);
82 else if (dims(0) != w) {
83 std::cerr <<
"Warning: mismatching video width - "
84 << dims(0) <<
" in svx file '" << file_name <<
"' vs "
85 << w <<
" in video file '" << file_name <<
"'" << std::endl;
89 extent(1) *= -dims(1);
91 else if (dims(1) != h) {
92 std::cerr <<
"Warning: mismatching video height - "
93 << dims(1) <<
" in svx file '" << file_name <<
"' vs "
94 << h <<
" in video file '" << file_name <<
"'" << std::endl;
97 dims(2) = int(n - offset);
98 extent(2) *= -dims(2);
107 V.get_format().set_component_format(cf);
108 V.get_format().set_width(dims(0));
109 V.get_format().set_height(dims(1));
110 V.get_format().set_depth(dims(2));
111 if (on_progress_update)
112 on_progress_update(-1, user_data);
113 dims(2) = int(V.get_format().get_depth());
115 V.ref_extent() = extent;
116 std::string cmd =
"ffmpeg -i ";
118 cmd +=
" -loglevel quiet";
119 if (!cycle_till_eof) {
120 cmd +=
" -frames:v ";
124 cmd +=
" -vf \"select=gte(n\\,";
128 if(flip_t != FT_NO_FLIP)
132 if (flip_t == FT_HORIZONTAL)
134 if (flip_t == FT_VERTICAL)
136 if (flip_t == FT_VERTICAL_AND_HORIZONTAL)
137 cmd +=
"hflip vflip ";
139 cmd +=
" -f rawvideo -pix_fmt ";
163 std::cout <<
"COMMAND:\n" << cmd <<
"\n" << std::endl;
164 if (on_progress_update)
165 on_progress_update(0, user_data);
167 size_t bytes_read = cgv::os::read_system_output(cmd, V.get_data_ptr<uint8_t>(), V.get_size(),
168 "reading video",
false, on_progress_update, user_data, V.get_slice_size(), cycle_till_eof);
169 if (bytes_read < V.get_size()) {
170 std::cerr <<
"Warning: could only read " << bytes_read <<
" of volume with size " << V.get_size() << std::endl;
172 if (on_progress_update)
173 on_progress_update(V.get_dimensions()(2) + 1, user_data);
176 bool read_from_sliced_volume(
const std::string& file_name, volume& V)
178 ooc_sliced_volume svol;
179 if (!svol.open_read(file_name)) {
180 std::cerr <<
"could not open " << file_name << std::endl;
183 volume::dimension_type dims = svol.get_dimensions();
185 std::vector<std::string> slice_file_names;
186 std::string file_path;
187 SourceType st = ST_VIDEO;
188 if (svol.file_name_pattern.find_first_of(
'*') != std::string::npos)
190 else if (svol.file_name_pattern.find_first_of(
'$') != std::string::npos)
192 if (st == ST_FILTER) {
193 file_path = cgv::utils::file::get_path(svol.file_name_pattern);
194 if (!file_path.empty() && file_path.back() !=
'/')
196 void* handle = cgv::utils::file::find_first(svol.file_name_pattern);
197 while (handle != 0) {
198 if (!cgv::utils::file::find_directory(handle))
199 slice_file_names.push_back(cgv::utils::file::find_name(handle));
200 handle = cgv::utils::file::find_next(handle);
206 if (st == ST_VIDEO) {
209 if (vr_ptr->
open(svol.file_name_pattern)) {
213 dims(2) = vr_ptr->
get<uint32_t>(
"nr_frames");
214 svol.ref_extent()(2) *= -dims(2);
222 bool result = read_volume_from_video_with_ffmpeg(V, svol.file_name_pattern, dims, svol.get_extent(), svol.get_format().get_component_format(), svol.offset);
230 dims(2) = int(slice_file_names.size() - svol.offset);
233 while (cgv::utils::file::exists(svol.get_slice_file_name(dims(2))))
236 svol.ref_extent()(2) *= -dims(2);
238 if ((dims(0) == -1 || dims(1) == -1)) {
239 std::string fst_file_name;
240 if (st == ST_FILTER) {
241 if (svol.offset >= slice_file_names.size()) {
242 std::cerr <<
"ERROR: offset larger than number of files" << std::endl;
245 fst_file_name = file_path + slice_file_names[svol.offset];
248 fst_file_name = svol.get_slice_file_name(0);
250 if (!cgv::utils::file::exists(fst_file_name)) {
251 std::cerr <<
"ERROR could not find first slice <" << fst_file_name <<
">" << std::endl;
255 if (!ir.open(fst_file_name)) {
256 std::cerr <<
"ERROR could not open first slice <" << fst_file_name <<
">" << std::endl;
263 svol.ref_extent()(0) *= -dims(0);
267 svol.ref_extent()(1) *= -dims(1);
271 V.get_format().set_component_format(svol.get_format().get_component_format());
273 V.ref_extent() = svol.get_extent();
275 std::size_t slize_size = V.get_voxel_size() * V.get_format().get_width() * V.get_format().get_height();
278 for (
int i = 0; i < (int)dims(2); ++i) {
281 if (!svol.read_slice(i)) {
282 std::cerr <<
"could not read slice " << i <<
" with filename \"" << svol.get_slice_file_name(i) <<
"\"." << std::endl;
287 int j = i + svol.offset;
288 if ((
unsigned)j > slice_file_names.size()) {
289 std::cerr <<
"could not read slice " << i <<
" from with filename with index " << j <<
" as only " << slice_file_names.size() <<
" match pattern." << std::endl;
292 if (!svol.read_slice(i, file_path + slice_file_names[j])) {
293 std::cerr <<
"could not read slice " << i <<
" from file \"" << slice_file_names[j] <<
"\"." << std::endl;
300 std::cerr <<
"could not frame " << i <<
" from avi file \"" << svol.file_name_pattern <<
"\"." << std::endl;
308 std::copy(src_ptr, src_ptr + slize_size, dst_ptr);
309 dst_ptr += slize_size;
315 bool write_as_sliced_volume(
const std::string& file_name,
const std::string& _file_name_pattern,
const volume& V)
317 ooc_sliced_volume svol;
318 svol.get_format().set_component_format(V.get_format().get_component_format());
319 svol.resize(V.get_dimensions());
320 svol.ref_extent() = V.get_extent();
321 std::string file_name_pattern = _file_name_pattern;
323 std::string path = cgv::utils::file::get_path(file_name);
325 file_name_pattern = path +
"/" + file_name_pattern;
326 if (!svol.open_write(file_name, file_name_pattern,
unsigned(V.get_format().get_depth()))) {
327 std::cerr <<
"could not open " << file_name <<
" for write." << std::endl;
331 std::size_t slize_size = V.get_voxel_size() * V.get_format().get_width() * V.get_format().get_height();
334 for (
int i = 0; i < (int)svol.get_nr_slices(); ++i) {
335 std::copy(src_ptr, src_ptr + slize_size, dst_ptr);
336 if (!svol.write_slice(i))
338 src_ptr += slize_size;
More advanced text processing for splitting text into lines or tokens.
T get(const std::string &property)
query a property of the element and perform standard conversions if necessary.
complete implementation of method actions that only call one method when entering a node
cgv::type::func::transfer_const< P, S * >::type get_ptr() const
return a data pointer to type S
the data view gives access to a data array of one, two, three or four dimensions.
@ CF_RGB
color format with two components R and G
const char * get_type_name(TypeId tid)
function that returns the name of a type specified through TypeId
@ TI_UINT8
signed integer stored in 64 bits
@ TI_UINT16
unsigned integer stored in 8 bits
unsigned char uint8_type
this type provides an 8 bit unsigned integer type
unsigned int replace(std::string &s, char c1, char c2)
replace char c1 with c2 in the given string _s and return number of replacements
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
bool is_integer(const char *begin, const char *end, int &value)
check if the text range (begin,end( defines an integer value. If yes, store the value in the passed r...
void split_to_lines(const char *global_begin, const char *global_end, std::vector< line > &lines, bool truncate_trailing_spaces)
this function splits a text range at the newline characters into single lines.
Helper functions to process strings.