Fix integer overflow in ft_rendered_size_line
[ilaris-y4m-tools.git] / vflip.cpp
blob467c82d953046ab943a501965eb085e066f49f56
1 #include "yuv4mpeg.hpp"
2 #include "parseval.hpp"
3 #include "marker.hpp"
4 #include "rendertext.hpp"
5 #include <iostream>
7 void swap_buffers(char* a, char* b, size_t s)
9 for(size_t i = 0; i < s; i++)
10 std::swap(a[i], b[i]);
13 void do_flip(char* content, size_t fsize, size_t height, unsigned mode)
15 if(mode == 0) {
16 //Mode 0: Flip RGB or greyscale.
17 size_t lsize = fsize / height;
18 for(size_t i = 0; i < height / 2; i++)
19 swap_buffers(content + lsize * i, content + lsize * (height - i - 1), lsize);
20 } else if(mode == 1) {
21 //Mode 1: Flip YUV420.
22 size_t psize = fsize * 2 / 3;
23 do_flip(content, psize, height, 0);
24 do_flip(content + psize, psize >> 2, height >> 1, 0);
25 do_flip(content + psize + (psize >> 2), psize >> 2, height >> 1, 0);
26 } else if(mode == 2) {
27 //Mode 2: Flip YUV422.
28 size_t psize = fsize / 2;
29 do_flip(content, psize, height, 0);
30 do_flip(content + psize, psize >> 1, height >> 1, 0);
31 do_flip(content + psize + (psize >> 1), psize >> 1, height >> 1, 0);
32 } else if(mode == 3) {
33 //Mode 3: Flip YUV444.
34 size_t psize = fsize / 3;
35 do_flip(content, psize, height, 0);
36 do_flip(content + psize, psize, height, 0);
37 do_flip(content + psize + psize, psize, height, 0);
41 int main(int argc, char** argv)
43 size_t framesize = 0;
44 for(int i = 1; i < argc; i++) {
45 std::string arg = argv[i];
46 try {
47 std::cerr << "vflip: Unrecognized option '" << arg << "'" << std::endl;
48 return 1;
49 } catch(std::exception& e) {
50 std::cerr << "vflip: Error in option '" << arg << "': " << e.what() << std::endl;
51 return 1;
55 //Open files.
56 FILE* in = stdin;
57 FILE* out = stdout;
58 mark_pipe_as_binary(in);
59 mark_pipe_as_binary(out);
61 //Fixup header.
62 try {
63 unsigned mode;
64 struct yuv4mpeg_stream_header strmh(in);
65 if(strmh.chroma == "rgb") {
66 framesize = 3 * strmh.width * strmh.height; mode = 0;
67 } else if(strmh.chroma == "420") {
68 framesize = 3 * strmh.width * strmh.height / 2; mode = 1;
69 } else if(strmh.chroma == "420p16") {
70 framesize = 6 * strmh.width * strmh.height / 2; mode = 1;
71 } else if(strmh.chroma == "422") {
72 framesize = 2 * strmh.width * strmh.height; mode = 2;
73 } else if(strmh.chroma == "422p16") {
74 framesize = 4 * strmh.width * strmh.height; mode = 2;
75 } else if(strmh.chroma == "444") {
76 framesize = 3 * strmh.width * strmh.height; mode = 3;
77 } else if(strmh.chroma == "444p16") {
78 framesize = 6 * strmh.width * strmh.height; mode = 3;
79 } else
80 throw std::runtime_error("Unsupported input chroma type '" + strmh.chroma + "'");
81 write_or_die(out, static_cast<std::string>(strmh));
83 std::string _framh, _framh2;
84 std::vector<char> buffer;
85 buffer.resize(framesize);
86 struct yuv4mpeg_frame_header framh;
88 //Frame loop.
89 while(true) {
90 if(!read_line2(in, _framh))
91 return 0; //End.
92 framh = yuv4mpeg_frame_header(_framh);
93 read_or_die(in, &buffer[0], buffer.size());
94 do_flip(&buffer[0], framesize, strmh.height, mode);
95 write_or_die(out, static_cast<std::string>(framh));
96 write_or_die(out, &buffer[0], buffer.size());
98 } catch(std::exception& e) {
99 std::cerr << "vflip: Error: " << e.what() << std::endl;
100 return 1;
102 return 0;