Fix integer overflow in ft_rendered_size_line
[ilaris-y4m-tools.git] / subsample.cpp
blob56a6864e19880cf59e8bda93fc4621de90d213d0
1 #include "yuv4mpeg.hpp"
2 #include "yuvconvert.hpp"
3 #include "parseval.hpp"
4 #include <iostream>
6 int main(int argc, char** argv)
8 bool ibits16 = false;
9 bool obits16 = false;
10 bool bilinear = false;
11 bool magnify = false;
12 for(int i = 1; i < argc; i++) {
13 std::string arg = argv[i];
14 regex_results r;
15 if(r = regex("--16bit", arg)) {
16 obits16 = true;
17 } else if(r = regex("--bilinear", arg)) {
18 bilinear = true;
19 } else if(r = regex("--double", arg)) {
20 magnify = true;
21 } else {
22 std::cerr << "subsample: Unrecognized option '" << arg << "'" << std::endl;
23 return 1;
27 //Open files.
28 FILE* in = stdin;
29 FILE* out = stdout;
30 mark_pipe_as_binary(in);
31 mark_pipe_as_binary(out);
33 //Fixup header.
34 try {
35 struct yuv4mpeg_stream_header strmh(in);
36 if(strmh.chroma == "444")
37 ibits16 = false;
38 else if(strmh.chroma == "444p16")
39 ibits16 = true;
40 else
41 throw std::runtime_error("Unsupported input chroma type (need 8bit444 or 16bit444)");
42 if(magnify && (ibits16 || obits16))
43 throw std::runtime_error("Magnify is only supported for 8-bit");
44 if(!magnify && (strmh.width | strmh.height) & 1)
45 throw std::runtime_error("Input width and height must be even");
46 strmh.chroma = obits16 ? "420p16" : "420";
47 if(magnify) {
48 strmh.width *= 2;
49 strmh.height *= 2;
51 std::string _strmh = std::string(strmh);
52 write_or_die(out, _strmh);
54 std::vector<char> buffer;
55 std::vector<char> buffer3;
56 if(!magnify)
57 buffer.resize((ibits16 ? 2 : 1) * 3 * strmh.width * strmh.height);
58 else
59 buffer.resize(3 * strmh.width * strmh.height / 4);
60 buffer3.resize((obits16 ? 2 : 1) * 3 * strmh.width * strmh.height / 2);
61 //Write frames.
62 while(true) {
63 std::string _framh;
64 if(!read_line2(in, _framh))
65 break;
66 read_or_die(in, &buffer[0], buffer.size());
67 struct yuv4mpeg_frame_header framh(_framh);
68 if(strmh.interlace == 'm')
69 framh.chroma = 'p';
70 if(magnify)
71 yuvc_magify_luma(reinterpret_cast<uint8_t*>(&buffer3[0]),
72 reinterpret_cast<const uint8_t*>(&buffer[0]), strmh.width / 2,
73 strmh.height / 2);
74 else if(ibits16 && obits16)
75 yuvc_shrink_croma(reinterpret_cast<uint16_t*>(&buffer3[0]),
76 reinterpret_cast<const uint16_t*>(&buffer[0]), strmh.width, strmh.height,
77 !bilinear);
78 else if(ibits16 && !obits16)
79 yuvc_shrink_croma(reinterpret_cast<uint8_t*>(&buffer3[0]),
80 reinterpret_cast<const uint16_t*>(&buffer[0]), strmh.width, strmh.height,
81 !bilinear);
82 else if(!ibits16 && obits16)
83 yuvc_shrink_croma(reinterpret_cast<uint16_t*>(&buffer3[0]),
84 reinterpret_cast<const uint8_t*>(&buffer[0]), strmh.width, strmh.height,
85 !bilinear);
86 else if(!ibits16 && !obits16)
87 yuvc_shrink_croma(reinterpret_cast<uint8_t*>(&buffer3[0]),
88 reinterpret_cast<const uint8_t*>(&buffer[0]), strmh.width, strmh.height,
89 !bilinear);
90 write_or_die(out, _framh);
91 write_or_die(out, &buffer3[0], buffer3.size());
93 } catch(std::exception& e) {
94 std::cerr << "subsample: Error: " << e.what() << std::endl;
95 return 1;
97 return 0;