1
2
3 #include "toonz/tcamera.h"
4 #include "toonz/stage.h"
5 #include "tstream.h"
6 #include "texception.h"
7
8 //=============================================================================
9 // TCamera
10
TCamera()11 TCamera::TCamera()
12 //: m_size(12, 9), m_res(768, 576), m_xPrevalence(true)
13 //: m_size(36, 20.25),
14 : m_size(16, 9),
15 m_res(1920, 1080),
16 m_xPrevalence(true) {}
17
18 //-------------------------------------------------------------------
19
setSize(const TDimensionD & size,bool preserveDpi,bool preserveAR)20 void TCamera::setSize(const TDimensionD &size, bool preserveDpi,
21 bool preserveAR) {
22 double currAR = getAspectRatio();
23 TPointD currDpi = getDpi();
24 m_size.lx = size.lx;
25 if (preserveAR)
26 m_size.ly = m_size.lx / currAR; // WARNING! if also preserveDpi==true, the
27 // AR could lose precision...
28 else
29 m_size.ly = size.ly;
30
31 if (!preserveDpi) return;
32
33 m_res.lx = troundp(currDpi.x * m_size.lx);
34 m_res.ly = troundp(currDpi.y * m_size.ly);
35 m_size.lx = m_res.lx / currDpi.x;
36 if (preserveAR) //&& currDpi.x==currDpi.y)
37 {
38 double aux = m_size.lx / currAR - m_res.ly / currDpi.y;
39 m_size.ly = m_size.lx / currAR;
40 } else
41 m_size.ly = m_res.ly / currDpi.y;
42 }
43
44 //-------------------------------------------------------------------
45
getAspectRatio() const46 double TCamera::getAspectRatio() const { return m_size.lx / m_size.ly; }
47
48 //-------------------------------------------------------------------
49
setRes(const TDimension & res)50 void TCamera::setRes(const TDimension &res) {
51 assert(res.lx > 0);
52 assert(res.ly > 0);
53
54 if (m_res != res) {
55 m_res = res;
56 m_interestRect = TRect();
57 }
58 }
59
60 //-------------------------------------------------------------------
61
getDpi() const62 TPointD TCamera::getDpi() const {
63 TPointD dpi;
64 if (m_size.lx > 0 && m_size.ly > 0) {
65 dpi.x = m_res.lx / m_size.lx;
66 dpi.y = m_res.ly / m_size.ly;
67 }
68 return dpi;
69 }
70
71 //-------------------------------------------------------------------
72
isPixelSquared() const73 bool TCamera::isPixelSquared() const {
74 return areAlmostEqual(m_res.lx * m_size.ly, m_res.ly * m_size.lx);
75 }
76
77 //-------------------------------------------------------------------
78
getStageToCameraRef() const79 TAffine TCamera::getStageToCameraRef() const {
80 return TAffine(m_res.lx / (Stage::inch * m_size.lx), 0, 0.5 * m_res.lx, 0,
81 m_res.ly / (Stage::inch * m_size.ly), 0.5 * m_res.ly);
82 }
83
84 //-------------------------------------------------------------------
85
getCameraToStageRef() const86 TAffine TCamera::getCameraToStageRef() const {
87 const double factor = Stage::inch;
88
89 TDimensionD cameraSize = getSize();
90 cameraSize.lx *= factor;
91 cameraSize.ly *= factor;
92 TPointD center(0.5 * cameraSize.lx, 0.5 * cameraSize.ly);
93
94 return TAffine(factor * m_size.lx / (double)m_res.lx, 0, -center.x, 0,
95 factor * m_size.ly / (double)m_res.ly, -center.y);
96 }
97
98 //-------------------------------------------------------------------
99
getStageRect() const100 TRectD TCamera::getStageRect() const {
101 TDimensionD cameraSize = getSize();
102 const double factor = Stage::inch;
103 cameraSize.lx *= factor;
104 cameraSize.ly *= factor;
105 TRectD rect(cameraSize);
106 rect -= 0.5 * (rect.getP00() + rect.getP11());
107 return rect;
108 }
109
110 //-------------------------------------------------------------------
111
setInterestRect(const TRect & rect)112 void TCamera::setInterestRect(const TRect &rect) {
113 // Not using the TRect's common intersection. Unfortunately, in case
114 // the rect's coordinates have lx or ly < 0, the intersection returns
115 // the default (empty) rect. We want to maintain the coordinates instead.
116 // m_interestRect = rect * TRect(m_res);
117
118 m_interestRect.x0 = std::max(rect.x0, 0);
119 m_interestRect.y0 = std::max(rect.y0, 0);
120 m_interestRect.x1 = std::min(rect.x1, m_res.lx - 1);
121 m_interestRect.y1 = std::min(rect.y1, m_res.ly - 1);
122 }
123
124 //-------------------------------------------------------------------
125
getInterestStageRect() const126 TRectD TCamera::getInterestStageRect() const {
127 return getCameraToStageRef() * TRectD(m_interestRect.x0, m_interestRect.y0,
128 m_interestRect.x1 + 1,
129 m_interestRect.y1 + 1);
130 }
131
132 //-------------------------------------------------------------------
133
setInterestStageRect(const TRectD & rect)134 void TCamera::setInterestStageRect(const TRectD &rect) {
135 TRectD cameraInterestRectD(getStageToCameraRef() * rect);
136
137 setInterestRect(TRect(
138 tfloor(cameraInterestRectD.x0), tfloor(cameraInterestRectD.y0),
139 tceil(cameraInterestRectD.x1) - 1, tceil(cameraInterestRectD.y1) - 1));
140 }
141
142 //-------------------------------------------------------------------
143
saveData(TOStream & os) const144 void TCamera::saveData(TOStream &os) const {
145 os.child("cameraSize") << m_size.lx << m_size.ly;
146 os.child("cameraRes") << m_res.lx << m_res.ly;
147 os.child("cameraXPrevalence") << (int)m_xPrevalence;
148 os.child("interestRect") << m_interestRect.x0 << m_interestRect.y0
149 << m_interestRect.x1 << m_interestRect.y1;
150 }
151
152 //-------------------------------------------------------------------
153
loadData(TIStream & is)154 void TCamera::loadData(TIStream &is) {
155 std::string tagName;
156 while (is.matchTag(tagName)) {
157 if (tagName == "cameraSize" || tagName == "size")
158 is >> m_size.lx >> m_size.ly;
159 else if (tagName == "cameraRes" || tagName == "res")
160 is >> m_res.lx >> m_res.ly;
161 else if (tagName == "cameraXPrevalence") {
162 int xPrevalence;
163 is >> xPrevalence;
164 m_xPrevalence = (bool)xPrevalence;
165 } else if (tagName == "interestRect") {
166 is >> m_interestRect.x0 >> m_interestRect.y0 >> m_interestRect.x1 >>
167 m_interestRect.y1;
168 } else
169 throw TException("TCamera::loadData. unexpected tag: " + tagName);
170 is.matchEndTag();
171 }
172 }
173