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