Add filter on color plane ability to analyzer.

Change-Id: I9a72daf5bcc7510828c555ccc19d6e57eea57fc9
diff --git a/examples/analyzer.cc b/examples/analyzer.cc
index 43abaf2..3a02e32 100644
--- a/examples/analyzer.cc
+++ b/examples/analyzer.cc
@@ -23,6 +23,13 @@
 #define OD_FLIPSIGNI(a, b) (((a) + OD_SIGNMASK(b)) ^ OD_SIGNMASK(b))
 #define OD_DIV_ROUND(x, y) (((x) + OD_FLIPSIGNI((y) >> 1, x)) / (y))
 
+enum {
+  OD_LUMA_MASK = 1 << 0,
+  OD_CB_MASK = 1 << 1,
+  OD_CR_MASK = 1 << 2,
+  OD_ALL_MASK = OD_LUMA_MASK | OD_CB_MASK | OD_CR_MASK
+};
+
 class AV1Decoder {
  private:
   FILE *input;
@@ -38,6 +45,8 @@
   aom_image_t *image;
   int frame;
 
+  int plane_mask;
+
   AV1Decoder();
   ~AV1Decoder();
 
@@ -126,6 +135,8 @@
   const bool bit_accounting;
   double *bpp_q3;
 
+  int plane_mask;
+
   // The display size is the decode size, scaled by the zoom.
   int getDisplayWidth() const;
   int getDisplayHeight() const;
@@ -148,6 +159,8 @@
   int getZoom() const;
   bool setZoom(int zoom);
 
+  void setShowPlane(bool show_plane, int mask);
+
   void onPaint(wxPaintEvent &event);  // NOLINT
 };
 
@@ -158,10 +171,18 @@
 AnalyzerPanel::AnalyzerPanel(wxWindow *parent, const wxString &path,
                              const bool bit_accounting)
     : wxPanel(parent), path(path), zoom(0), pixels(NULL),
-      bit_accounting(bit_accounting), bpp_q3(NULL) {}
+      bit_accounting(bit_accounting), bpp_q3(NULL), plane_mask(OD_ALL_MASK) {}
 
 AnalyzerPanel::~AnalyzerPanel() { close(); }
 
+void AnalyzerPanel::setShowPlane(bool show_plane, int mask) {
+  if (show_plane) {
+    plane_mask |= mask;
+  } else {
+    plane_mask &= ~mask;
+  }
+}
+
 void AnalyzerPanel::render() {
   aom_image_t *img = decoder.image;
   int y_stride = img->stride[0];
@@ -181,15 +202,21 @@
       int64_t yval;
       int64_t cbval;
       int64_t crval;
+      int pmask;
       unsigned rval;
       unsigned gval;
       unsigned bval;
       yval = *y;
       cbval = *cb;
       crval = *cr;
-      yval -= 16;
-      cbval -= 128;
-      crval -= 128;
+      pmask = plane_mask;
+      if (pmask & OD_LUMA_MASK) {
+        yval -= 16;
+      } else {
+        yval = 128;
+      }
+      cbval = ((pmask & OD_CB_MASK) >> 1) * (cbval - 128);
+      crval = ((pmask & OD_CR_MASK) >> 2) * (crval - 128);
       /*This is intentionally slow and very accurate.*/
       rval = OD_CLAMPI(0, (int32_t)OD_DIV_ROUND(
                               2916394880000LL * yval + 4490222169144LL * crval,
@@ -364,6 +391,9 @@
   void onZoomOut(wxCommandEvent &event);     // NOLINT
   void onActualSize(wxCommandEvent &event);  // NOLINT
 
+  void onToggleViewMenuCheckBox(wxCommandEvent &event);          // NOLINT
+  void onResetAndToggleViewMenuCheckBox(wxCommandEvent &event);  // NOLINT
+
   void onNextFrame(wxCommandEvent &event);  // NOLINT
   void onGotoFrame(wxCommandEvent &event);  // NOLINT
   void onRestart(wxCommandEvent &event);    // NOLINT
@@ -372,10 +402,14 @@
 
   bool open(const wxString &path);
   bool setZoom(int zoom);
+  void updateViewMenu();
 };
 
 enum {
   wxID_NEXT_FRAME = 6000,
+  wxID_SHOW_Y,
+  wxID_SHOW_U,
+  wxID_SHOW_V,
   wxID_GOTO_FRAME,
   wxID_RESTART,
   wxID_ACTUAL_SIZE
@@ -388,6 +422,9 @@
 EVT_MENU(wxID_ZOOM_IN, AnalyzerFrame::onZoomIn)
 EVT_MENU(wxID_ZOOM_OUT, AnalyzerFrame::onZoomOut)
 EVT_MENU(wxID_ACTUAL_SIZE, AnalyzerFrame::onActualSize)
+EVT_MENU(wxID_SHOW_Y, AnalyzerFrame::onResetAndToggleViewMenuCheckBox)
+EVT_MENU(wxID_SHOW_U, AnalyzerFrame::onResetAndToggleViewMenuCheckBox)
+EVT_MENU(wxID_SHOW_V, AnalyzerFrame::onResetAndToggleViewMenuCheckBox)
 EVT_MENU(wxID_NEXT_FRAME, AnalyzerFrame::onNextFrame)
 EVT_MENU(wxID_GOTO_FRAME, AnalyzerFrame::onGotoFrame)
 EVT_MENU(wxID_RESTART, AnalyzerFrame::onRestart)
@@ -418,6 +455,13 @@
   viewMenu->Append(wxID_ZOOM_OUT, _("Zoom-Out\tCtrl--"), _("Half image size"));
   viewMenu->Append(wxID_ACTUAL_SIZE, _("Actual size\tCtrl-0"),
                    _("Actual size of the frame"));
+  viewMenu->AppendSeparator();
+  viewMenu->AppendCheckItem(wxID_SHOW_Y, _("&Y plane\tCtrl-Y"),
+                            _("Show Y plane"));
+  viewMenu->AppendCheckItem(wxID_SHOW_U, _("&U plane\tCtrl-U"),
+                            _("Show U plane"));
+  viewMenu->AppendCheckItem(wxID_SHOW_V, _("&V plane\tCtrl-V"),
+                            _("Show V plane"));
   mb->Append(viewMenu, _("&View"));
 
   playbackMenu = new wxMenu();
@@ -463,6 +507,22 @@
   setZoom(MIN_ZOOM);
 }
 
+void AnalyzerFrame::onToggleViewMenuCheckBox(wxCommandEvent &event) {  // NOLINT
+  GetMenuBar()->Check(event.GetId(), event.IsChecked());
+  updateViewMenu();
+}
+
+void AnalyzerFrame::onResetAndToggleViewMenuCheckBox(
+    wxCommandEvent &event) {  // NOLINT
+  int id = event.GetId();
+  if (id != wxID_SHOW_Y && id != wxID_SHOW_U && id != wxID_SHOW_V) {
+    GetMenuBar()->Check(wxID_SHOW_Y, true);
+    GetMenuBar()->Check(wxID_SHOW_U, true);
+    GetMenuBar()->Check(wxID_SHOW_V, true);
+  }
+  onToggleViewMenuCheckBox(event);
+}
+
 void AnalyzerFrame::onNextFrame(wxCommandEvent &WXUNUSED(event)) {
   panel->nextFrame();
   panel->Refresh(false);
@@ -507,6 +567,15 @@
   return false;
 }
 
+void AnalyzerFrame::updateViewMenu() {
+  panel->setShowPlane(GetMenuBar()->IsChecked(wxID_SHOW_Y), OD_LUMA_MASK);
+  panel->setShowPlane(GetMenuBar()->IsChecked(wxID_SHOW_U), OD_CB_MASK);
+  panel->setShowPlane(GetMenuBar()->IsChecked(wxID_SHOW_V), OD_CR_MASK);
+  SetClientSize(panel->GetSize());
+  panel->render();
+  panel->Refresh(false);
+}
+
 class Analyzer : public wxApp {
  private:
   AnalyzerFrame *frame;