dcp::Size
Film::frame_size () const
{
- return fit_ratio_within (container()->ratio(), full_frame ());
+ return fit_ratio_within (container()->ratio(), full_frame (), 1);
}
dcp::EncryptedKDM
return pvf;
}
- dcp::Size image_size = content->scale().size (content, _video_container_size, _film->frame_size ());
+ dcp::Size image_size = content->scale().size (content, _video_container_size, _film->frame_size (), _approximate_size ? 4 : 1);
if (_approximate_size) {
image_size.width &= ~3;
image_size.height &= ~3;
shared_ptr<Image> out = im->crop_scale_window (total_crop, _inter_size, _out_size, _scaler, PIX_FMT_RGB24, true);
- Position<int> const container_offset ((_out_size.width - _inter_size.width) / 2, (_out_size.height - _inter_size.width) / 2);
-
if (burn_subtitle && _subtitle.image) {
out->alpha_blend (_subtitle.image, _subtitle.position);
}
assert (j2k);
return j2k->j2k ();
}
+
+Position<int>
+PlayerVideo::inter_position () const
+{
+ return Position<int> ((_out_size.width - _inter_size.width) / 2, (_out_size.height - _inter_size.height) / 2);
+}
+
+
return _colour_conversion;
}
+ /** @return Position of the content within the overall image once it has been scaled up */
+ Position<int> inter_position () const;
+
+ /** @return Size of the content within the overall image once it has been scaled up */
+ dcp::Size inter_size () const {
+ return _inter_size;
+ }
+
private:
boost::shared_ptr<const ImageProxy> _in;
DCPTime _time;
return a - (a % t);
}
+/** @param n A number.
+ * @param r Rounding `boundary' (must be a power of 2)
+ * @return n rounded to the nearest r
+ */
+int
+round_to (float n, int r)
+{
+ assert (r == 1 || r == 2 || r == 4);
+ return int (n + float(r) / 2) &~ (r - 1);
+}
+
/** Read a sequence of key / value pairs from a text stream;
* the keys are the first words on the line, and the values are
* the remainder of the line following the key. Lines beginning
}
dcp::Size
-fit_ratio_within (float ratio, dcp::Size full_frame)
+fit_ratio_within (float ratio, dcp::Size full_frame, int round)
{
if (ratio < full_frame.ratio ()) {
- return dcp::Size (rint (full_frame.height * ratio), full_frame.height);
+ return dcp::Size (round_to (full_frame.height * ratio, round), full_frame.height);
}
- return dcp::Size (full_frame.width, rint (full_frame.width / ratio));
+ return dcp::Size (full_frame.width, round_to (full_frame.width / ratio, round));
}
void *
extern boost::filesystem::path mo_path ();
#endif
extern std::string tidy_for_filename (std::string);
-extern dcp::Size fit_ratio_within (float ratio, dcp::Size);
+extern dcp::Size fit_ratio_within (float ratio, dcp::Size, int);
extern std::string entities_to_text (std::string e);
extern std::map<std::string, std::string> split_get_request (std::string url);
extern int dcp_audio_frame_rate (int);
extern int stride_round_up (int, int const *, int);
+extern int round_to (float n, int r);
extern std::multimap<std::string, std::string> read_key_value (std::istream& s);
extern int get_required_int (std::multimap<std::string, std::string> const & kv, std::string k);
extern float get_required_float (std::multimap<std::string, std::string> const & kv, std::string k);
* @param film_container The size of the film's image.
*/
dcp::Size
-VideoContentScale::size (shared_ptr<const VideoContent> c, dcp::Size display_container, dcp::Size film_container) const
+VideoContentScale::size (shared_ptr<const VideoContent> c, dcp::Size display_container, dcp::Size film_container, int round) const
{
if (_ratio) {
- return fit_ratio_within (_ratio->ratio (), display_container);
+ return fit_ratio_within (_ratio->ratio (), display_container, round);
}
dcp::Size const ac = c->video_size_after_crop ();
/* Force scale if the film_container is smaller than the content's image */
if (_scale || film_container.width < ac.width || film_container.height < ac.height) {
- return fit_ratio_within (ac.ratio (), display_container);
+ return fit_ratio_within (ac.ratio (), display_container, 1);
}
/* Scale the image so that it will be in the right place in film_container, even if display_container is a
different size.
*/
return dcp::Size (
- c->video_size().width * float(display_container.width) / film_container.width,
- c->video_size().height * float(display_container.height) / film_container.height
+ round_to (c->video_size().width * float(display_container.width) / film_container.width, round),
+ round_to (c->video_size().height * float(display_container.height) / film_container.height, round)
);
}
VideoContentScale (bool);
VideoContentScale (cxml::NodePtr);
- dcp::Size size (boost::shared_ptr<const VideoContent>, dcp::Size, dcp::Size) const;
+ dcp::Size size (boost::shared_ptr<const VideoContent>, dcp::Size, dcp::Size, int round) const;
std::string id () const;
std::string name () const;
void as_xml (xmlpp::Node *) const;
FilmViewer::FilmViewer (shared_ptr<Film> f, wxWindow* p)
: wxPanel (p)
, _panel (new wxPanel (this))
+ , _outline_content (new wxCheckBox (this, wxID_ANY, _("Outline content")))
, _slider (new wxSlider (this, wxID_ANY, 0, 0, 4096))
, _back_button (new wxButton (this, wxID_ANY, wxT("<")))
, _forward_button (new wxButton (this, wxID_ANY, wxT(">")))
_v_sizer->Add (_panel, 1, wxEXPAND);
+ _v_sizer->Add (_outline_content, 0, wxALL, DCPOMATIC_SIZER_GAP);
+
wxBoxSizer* h_sizer = new wxBoxSizer (wxHORIZONTAL);
wxBoxSizer* time_sizer = new wxBoxSizer (wxVERTICAL);
_panel->Bind (wxEVT_PAINT, boost::bind (&FilmViewer::paint_panel, this));
_panel->Bind (wxEVT_SIZE, boost::bind (&FilmViewer::panel_sized, this, _1));
+ _outline_content->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&FilmViewer::refresh_panel, this));
_slider->Bind (wxEVT_SCROLL_THUMBTRACK, boost::bind (&FilmViewer::slider_moved, this));
_slider->Bind (wxEVT_SCROLL_PAGEUP, boost::bind (&FilmViewer::slider_moved, this));
_slider->Bind (wxEVT_SCROLL_PAGEDOWN, boost::bind (&FilmViewer::slider_moved, this));
get (_position, _last_get_accurate);
}
+void
+FilmViewer::refresh_panel ()
+{
+ _panel->Refresh ();
+ _panel->Update ();
+}
+
void
FilmViewer::get (DCPTime p, bool accurate)
{
_frame = pvf.front()->image (true);
_frame = _frame->scale (_frame->size(), Scaler::from_id ("fastbilinear"), PIX_FMT_RGB24, false);
_position = pvf.front()->time ();
+ _inter_position = pvf.front()->inter_position ();
+ _inter_size = pvf.front()->inter_size ();
} catch (dcp::DCPReadError& e) {
/* This can happen on the following sequence of events:
* - load encrypted DCP
}
set_position_text ();
- _panel->Refresh ();
- _panel->Update ();
+ refresh_panel ();
_last_get_accurate = accurate;
}
dc.SetPen (p);
dc.SetBrush (b);
dc.DrawRectangle (0, _out_size.height, _panel_size.width, _panel_size.height - _out_size.height);
- }
-}
+ }
+ if (_outline_content->GetValue ()) {
+ wxPen p (wxColour (255, 0, 0), 2);
+ dc.SetPen (p);
+ dc.SetBrush (*wxTRANSPARENT_BRUSH);
+ dc.DrawRectangle (_inter_position.x, _inter_position.y, _inter_size.width, _inter_size.height);
+ }
+}
void
FilmViewer::slider_moved ()
{
_panel_size.width = ev.GetSize().GetWidth();
_panel_size.height = ev.GetSize().GetHeight();
+
calculate_sizes ();
get (_position, _last_get_accurate);
}
if (panel_ratio < film_ratio) {
/* panel is less widscreen than the film; clamp width */
_out_size.width = _panel_size.width;
- _out_size.height = _out_size.width / film_ratio;
+ _out_size.height = rint (_out_size.width / film_ratio);
} else {
/* panel is more widescreen than the film; clamp height */
_out_size.height = _panel_size.height;
- _out_size.width = _out_size.height * film_ratio;
+ _out_size.width = rint (_out_size.height * film_ratio);
}
/* Catch silly values */
_out_size.width = max (64, _out_size.width);
_out_size.height = max (64, _out_size.height);
- /* The player will round its image down to the nearest 4 pixels
+ /* The player will round its image size down to the next lowest 4 pixels
to speed up its scale, so do similar here to avoid black borders
around things. This is a bit of a hack.
*/
void player_changed (bool);
void set_position_text ();
void get (DCPTime, bool);
+ void refresh_panel ();
boost::shared_ptr<Film> _film;
boost::shared_ptr<Player> _player;
wxSizer* _v_sizer;
wxPanel* _panel;
+ wxCheckBox* _outline_content;
wxSlider* _slider;
wxButton* _back_button;
wxButton* _forward_button;
boost::shared_ptr<const Image> _frame;
DCPTime _position;
+ Position<int> _inter_position;
+ dcp::Size _inter_size;
/** Size of our output (including padding if we have any) */
dcp::Size _out_size;
}
dcp::Size const container_size = _parent->film()->frame_size ();
- dcp::Size const scaled = vcs->scale().size (vcs, container_size, container_size);
+ dcp::Size const scaled = vcs->scale().size (vcs, container_size, container_size, 1);
if (scaled != vcs->video_size_after_crop ()) {
d << wxString::Format (
Ratio const * r = Ratio::from_id ("119");
BOOST_CHECK (r);
- BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080)), dcp::Size (1290, 1080));
+ BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080), 1), dcp::Size (1290, 1080));
r = Ratio::from_id ("133");
BOOST_CHECK (r);
- BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080)), dcp::Size (1440, 1080));
+ BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080), 1), dcp::Size (1440, 1080));
r = Ratio::from_id ("137");
BOOST_CHECK (r);
- BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080)), dcp::Size (1480, 1080));
+ BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080), 1), dcp::Size (1480, 1080));
r = Ratio::from_id ("138");
BOOST_CHECK (r);
- BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080)), dcp::Size (1485, 1080));
+ BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080), 1), dcp::Size (1485, 1080));
r = Ratio::from_id ("166");
BOOST_CHECK (r);
- BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080)), dcp::Size (1800, 1080));
+ BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080), 1), dcp::Size (1800, 1080));
r = Ratio::from_id ("178");
BOOST_CHECK (r);
- BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080)), dcp::Size (1920, 1080));
+ BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080), 1), dcp::Size (1920, 1080));
r = Ratio::from_id ("185");
BOOST_CHECK (r);
- BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080)), dcp::Size (1998, 1080));
+ BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080), 1), dcp::Size (1998, 1080));
r = Ratio::from_id ("239");
BOOST_CHECK (r);
- BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080)), dcp::Size (2048, 858));
+ BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080), 1), dcp::Size (2048, 858));
r = Ratio::from_id ("full-frame");
BOOST_CHECK (r);
- BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080)), dcp::Size (2048, 1080));
+ BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), dcp::Size (2048, 1080), 1), dcp::Size (2048, 1080));
}