diff --git a/stuff/config/current.txt b/stuff/config/current.txt
index d42fcf2..26a6afd 100644
--- a/stuff/config/current.txt
+++ b/stuff/config/current.txt
@@ -1224,6 +1224,16 @@
   <item>"STD_iwa_BokehFx.distance5"		"Layer5 Distance"</item>
   <item>"STD_iwa_BokehFx.bokeh_adjustment5"	"Layer5 Bokeh Adjustment"</item>
   
+  <item>"STD_iwa_TimeCodeFx"	"TimeCode Iwa"</item>
+  <item>"STD_iwa_TimeCodeFx.displayType"	"Display Type"</item>
+  <item>"STD_iwa_TimeCodeFx.frameRate"	"Frame Rate"</item>
+  <item>"STD_iwa_TimeCodeFx.startFrame"	"Start Frame"</item>
+  <item>"STD_iwa_TimeCodeFx.position"	"Text Position"</item>
+  <item>"STD_iwa_TimeCodeFx.size"	"Text Size"</item>
+  <item>"STD_iwa_TimeCodeFx.textColor"	"Text Color"</item>
+  <item>"STD_iwa_TimeCodeFx.showBox"	"Show Box"</item>
+  <item>"STD_iwa_TimeCodeFx.boxColor"	"Box Color"</item>
+
  <!------------------------------ Tiled Particles Iwa ------------------------------------------->
 
   <item>STD_iwa_TiledParticlesFx "Tiled Particles Iwa" </item>
diff --git a/stuff/profiles/layouts/fxs/STD_iwa_TimeCodeFx.xml b/stuff/profiles/layouts/fxs/STD_iwa_TimeCodeFx.xml
new file mode 100644
index 0000000..87d3662
--- /dev/null
+++ b/stuff/profiles/layouts/fxs/STD_iwa_TimeCodeFx.xml
@@ -0,0 +1,14 @@
+<fxlayout>
+	<page name="TimeCode Iwa">
+ 	<vbox>
+		<control>displayType</control>
+		<control>frameRate</control>
+		<control>startFrame</control>
+		<control>position</control>
+		<control>size</control>
+		<control>textColor</control>
+		<control>showBox</control>
+		<control>boxColor</control>
+  	</vbox>
+  	</page>
+</fxlayout>
diff --git a/stuff/profiles/layouts/fxs/fxs.lst b/stuff/profiles/layouts/fxs/fxs.lst
index db7accc..3c42800 100644
--- a/stuff/profiles/layouts/fxs/fxs.lst
+++ b/stuff/profiles/layouts/fxs/fxs.lst
@@ -144,6 +144,7 @@
     STD_inopnCloudsFx
     STD_particlesFx 
     STD_iwa_TiledParticlesFx
+    STD_iwa_TimeCodeFx
   </Render>
   <Stylize>
     STD_colorEmbossFx
diff --git a/toonz/sources/stdfx/CMakeLists.txt b/toonz/sources/stdfx/CMakeLists.txt
index d2b8fab..aa6bad6 100644
--- a/toonz/sources/stdfx/CMakeLists.txt
+++ b/toonz/sources/stdfx/CMakeLists.txt
@@ -73,6 +73,7 @@ set(HEADERS
     iwa_pnperspectivefx.h
     iwa_soapbubblefx.h
 	iwa_bokehfx.h
+	iwa_timecodefx.h
 )
 
 set(SOURCES
@@ -250,6 +251,7 @@ set(SOURCES
 	${SDKROOT}/kiss_fft130/kiss_fft.c
 	${SDKROOT}/kiss_fft130/tools/kiss_fftnd.c
 	iwa_bokehfx.cpp
+	iwa_timecodefx.cpp
 )
 
 set(OBJCSOURCES
diff --git a/toonz/sources/stdfx/iwa_timecodefx.cpp b/toonz/sources/stdfx/iwa_timecodefx.cpp
new file mode 100644
index 0000000..6ae54d0
--- /dev/null
+++ b/toonz/sources/stdfx/iwa_timecodefx.cpp
@@ -0,0 +1,175 @@
+#include "iwa_timecodefx.h"
+
+#include "tparamuiconcept.h"
+
+#include <QFont>
+#include <QFontMetrics>
+#include <QImage>
+#include <QPainter>
+//------------------------------------------------------------------
+
+Iwa_TimeCodeFx::Iwa_TimeCodeFx()
+    : m_displayType(new TIntEnumParam(TYPE_HHMMSSFF, "HH;MM;SS;FF"))
+    , m_frameRate(24)
+    , m_startFrame(0)
+    , m_position(TPointD(0.0, 0.0))
+    , m_size(25)
+    , m_textColor(TPixel32::White)
+    , m_showBox(true)
+    , m_boxColor(TPixel32::Black) {
+  m_displayType->addItem(TYPE_FRAME, "Frame Number");
+  m_position->getX()->setMeasureName("fxLength");
+  m_position->getY()->setMeasureName("fxLength");
+  m_size->setMeasureName("fxLength");
+  m_size->setValueRange(0.1, (std::numeric_limits<double>::max)());
+
+  bindParam(this, "displayType", m_displayType);
+  bindParam(this, "frameRate", m_frameRate);
+  bindParam(this, "startFrame", m_startFrame);
+  bindParam(this, "position", m_position);
+  bindParam(this, "size", m_size);
+  bindParam(this, "textColor", m_textColor);
+  bindParam(this, "showBox", m_showBox);
+  bindParam(this, "boxColor", m_boxColor);
+}
+
+//------------------------------------------------------------------
+
+bool Iwa_TimeCodeFx::doGetBBox(double frame, TRectD &bBox,
+                               const TRenderSettings &ri) {
+  bBox = TConsts::infiniteRectD;
+  return true;
+}
+
+//------------------------------------------------------------------
+
+void Iwa_TimeCodeFx::doCompute(TTile &tile, double frame,
+                               const TRenderSettings &ri) {
+  double fac   = sqrt(fabs(ri.m_affine.det()));
+  int size     = (int)(fac * fabs(m_size->getValue(frame)));
+  TPoint point = convert(
+      fac * m_position->getValue(frame) -
+      (tile.m_pos + tile.getRaster()->getCenterD()) +
+      TPointD(ri.m_cameraBox.getLx() / 2.0, ri.m_cameraBox.getLy() / 2.0));
+
+  QFont font("Arial", size);
+  font.setWeight(QFont::Normal);
+  QFontMetrics fm(font);
+  QString timeCodeStr = getTimeCodeStr(frame, ri);
+  int width           = fm.width(timeCodeStr);
+  int height          = fm.height();
+
+  QImage img(width, height, QImage::Format_ARGB32);
+
+  if (m_showBox->getValue()) {
+    TPixel32 boxColor = m_boxColor->getValue(frame);
+    img.fill(QColor((int)boxColor.r, (int)boxColor.g, (int)boxColor.b,
+                    (int)boxColor.m));
+  } else
+    img.fill(Qt::transparent);
+
+  QPainter painter(&img);
+  TPixel32 color = m_textColor->getValue(frame);
+  painter.setPen(
+      QColor((int)color.r, (int)color.g, (int)color.b, (int)color.m));
+  painter.setFont(font);
+  painter.drawText(QPoint(0, fm.ascent()), timeCodeStr);
+
+  tile.getRaster()->clear();
+  TRaster32P ras32 = (TRaster32P)tile.getRaster();
+  TRaster64P ras64 = (TRaster64P)tile.getRaster();
+  if (ras32)
+    putTimeCodeImage<TRaster32P, TPixel32>(ras32, point, img);
+  else if (ras64)
+    putTimeCodeImage<TRaster64P, TPixel64>(ras64, point, img);
+  else
+    throw TException("Iwa_TimeCodeFx: unsupported Pixel Type");
+}
+
+//------------------------------------------------------------------
+
+void Iwa_TimeCodeFx::getParamUIs(TParamUIConcept *&concepts, int &length) {
+  concepts = new TParamUIConcept[length = 1];
+
+  concepts[0].m_type  = TParamUIConcept::POINT;
+  concepts[0].m_label = "Position";
+  concepts[0].m_params.push_back(m_position);
+}
+
+//------------------------------------------------------------------
+
+std::string Iwa_TimeCodeFx::getAlias(double frame,
+                                     const TRenderSettings &info) const {
+  std::string alias = getFxType();
+  alias += "[";
+
+  std::string paramalias("");
+  for (int i = 0; i < getParams()->getParamCount(); ++i) {
+    TParam *param = getParams()->getParam(i);
+    paramalias += param->getName() + "=" + param->getValueAlias(frame, 3);
+  }
+
+  return alias + std::to_string(frame) + "," + std::to_string(getIdentifier()) +
+         paramalias + "]";
+}
+
+//------------------------------------------------------------------
+
+QString Iwa_TimeCodeFx::getTimeCodeStr(double frame,
+                                       const TRenderSettings &ri) {
+  int f = (int)frame + m_startFrame->getValue();
+
+  if (m_displayType->getValue() == TYPE_HHMMSSFF) {
+    bool neg = (f < 0);
+    f        = abs(f);
+    int fps  = m_frameRate->getValue();
+    int hh   = f / (fps * 60 * 60);
+    f -= hh * fps * 60 * 60;
+    int mm = f / (fps * 60);
+    f -= mm * fps * 60;
+    int ss = f / fps;
+    int ff = f % fps;
+    return QString((neg) ? "-" : "") +
+           QString::number(hh).rightJustified(2, '0') + QString(";") +
+           QString::number(mm).rightJustified(2, '0') + QString(";") +
+           QString::number(ss).rightJustified(2, '0') + QString(";") +
+           QString::number(ff).rightJustified(2, '0');
+  } else {   // TYPE_FRAMENUMBER
+    f += 1;  // starting from "000001" with no frame offset.
+    return QString((f < 0) ? "-" : "") +
+           QString::number(abs(f)).rightJustified(6, '0');
+  }
+}
+
+//------------------------------------------------------------------
+
+template <typename RASTER, typename PIXEL>
+void Iwa_TimeCodeFx::putTimeCodeImage(const RASTER srcRas, TPoint &pos,
+                                      QImage &img) {
+  for (int j = 0; j < img.height(); j++) {
+    int rasY = pos.y + j;
+    if (rasY < 0) continue;
+    if (srcRas->getLy() <= rasY) break;
+
+    PIXEL *pix  = srcRas->pixels(rasY);
+    QRgb *img_p = (QRgb *)img.scanLine(img.height() - j - 1);
+    for (int i = 0; i < img.width(); i++, img_p++) {
+      int rasX = pos.x + i;
+      if (rasX < 0) continue;
+      if (srcRas->getLx() <= rasX) break;
+
+      pix[rasX].r = (PIXEL::Channel)(
+          qRed(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX);
+      pix[rasX].g = (PIXEL::Channel)(
+          qGreen(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX);
+      pix[rasX].b = (PIXEL::Channel)(
+          qBlue(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX);
+      pix[rasX].m = (PIXEL::Channel)(
+          qAlpha(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX);
+    }
+  }
+}
+
+//==============================================================================
+
+FX_PLUGIN_IDENTIFIER(Iwa_TimeCodeFx, "iwa_TimeCodeFx");
diff --git a/toonz/sources/stdfx/iwa_timecodefx.h b/toonz/sources/stdfx/iwa_timecodefx.h
new file mode 100644
index 0000000..a62c08b
--- /dev/null
+++ b/toonz/sources/stdfx/iwa_timecodefx.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#ifndef IWA_TIMECODEFX_H
+#define IWA_TIMECODEFX_H
+
+#include "stdfx.h"
+#include "tfxparam.h"
+#include "tparamset.h"
+
+//******************************************************************
+//	Iwa_TimeCode Fx  class
+//******************************************************************
+
+class Iwa_TimeCodeFx final : public TStandardZeraryFx {
+  FX_PLUGIN_DECLARATION(Iwa_TimeCodeFx)
+
+public:
+  TIntEnumParamP m_displayType;  // - SMPTE HH;MM;SS;FF
+                                 // - FrameNumber [######]
+  TIntParamP m_frameRate;
+  TIntParamP m_startFrame;
+  TPointParamP m_position;
+  TDoubleParamP m_size;
+  TPixelParamP m_textColor;
+  TBoolParamP m_showBox;
+  TPixelParamP m_boxColor;
+
+  QString getTimeCodeStr(double frame, const TRenderSettings &ri);
+
+  template <typename RASTER, typename PIXEL>
+  void putTimeCodeImage(const RASTER srcRas, TPoint &pos, QImage &img);
+
+public:
+  enum { TYPE_HHMMSSFF, TYPE_FRAME };
+
+  Iwa_TimeCodeFx();
+
+  bool isZerary() const override { return true; }
+
+  bool canHandle(const TRenderSettings &info, double frame) override {
+    return true;
+  }
+
+  bool doGetBBox(double frame, TRectD &bBox,
+                 const TRenderSettings &ri) override;
+  void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override;
+  void getParamUIs(TParamUIConcept *&concepts, int &length) override;
+
+  std::string getAlias(double frame,
+                       const TRenderSettings &info) const override;
+};
+
+#endif
\ No newline at end of file