コードもまぁ、そんな複雑ではないな。
実質、C#イテレータブロックのテストみたいな感じ。

描画クラス実装。

    class DrowImageSMPTEX : DrawImageBase
    {
        /// <summary>
        /// SMTPE形式に準じたカラーバーを表示。
        /// 下段1/4はオリジナル
        /// </summary>
        /// <param name="aimg">描画するカンバス</param>
        protected override void doDrowImage(Bitmap aimg)
        {
            Rectangle barRect = new Rectangle();

            barRect.X = 0;
            barRect.Width = aimg.Width;
            barRect.Y = 0;

            foreach (IBarPattern barPattern in BarPattern())
            {
                barRect.Height = (aimg.Height * barPattern.height) / 100;
                this.DrowColorBar(aimg, barPattern, barRect);
                barRect.Y = barRect.Bottom;
            }
        }

        /// <summary>
        /// カラーバーのパターンを取得するイテレータブロック
        /// </summary>
        static public IEnumerable<IBarPattern> BarPattern()
        {
            yield return new Bar7Color();
            yield return new Bar7RevColor();
            yield return new BarGrayColorMixed();
            yield return new BarGrayGradation();
        }
    }

あ、doDrowImageにフォーム渡す必要はまったくなかったので取っ払いました。


カラーバーのパターン定義

namespace Color_Bar.BarPattern
{
    interface IBarPattern
    {
        bool hasNext();
        Int32 next();
        int count { get; }
        int height { get; }
    }

    abstract class BarPatternBase : IBarPattern
    {
        protected Int32[] FBarcolor = {};
        protected int FIndex = 0;
        protected int FHeight = 0;

        public BarPatternBase()
        {
            FHeight = getHeight();
            FBarcolor = getBarcolor();
        }

        abstract protected int getHeight();
        abstract protected Int32[] getBarcolor();

        public bool hasNext()
        {
            return FIndex < FBarcolor.Length - 1;
        }

        public Int32 next()
        {
            return FBarcolor[FIndex++];
        }

        public int count
        {
            get
            {
                return FBarcolor.Length;
            }
        }

        public int height
        {
            get
            {
                return FHeight;
            }
        }
    }
    
    class Bar7Color : BarPatternBase
    {
        protected override int getHeight()
        {
            return 66;
        }

        protected override Int32[] getBarcolor()
        {
            return new Int32[] { 0xB4B4B4, 0xB4B40C, 0x0CB4B4, 0x0CB40C, 0xB40CB4, 0XB40C0C, 0x0C0CB4 };
        }
    }

    class Bar7RevColor : BarPatternBase
    {
        protected override int getHeight()
        {
            return 8;
        }

        protected override Int32[] getBarcolor()
        {
            return new Int32[] { 0x0C0CB4, 0x000000, 0xB40CB4, 0x000000, 0x0CB4B4, 0x000000, 0xB4B4B4 };
        }
    }

    class BarGrayColorMixed : BarPatternBase
    {
        protected override int getHeight()
        {
            return 13;
        }

        protected override Int32[] getBarcolor()
        {
            return new Int32[] { 0x808080, 0x858580, 0x808585, 0x808580, 0x858085, 0x858080, 0x808085 };
        }
    }

    class BarGrayGradation : BarPatternBase
    {
        protected override int getHeight()
        {
            return 15;
        }

        protected override Int32[] getBarcolor()
        {
            return new Int32[] { 0x808080, 0xFFFFFF, 0xE0E0E0, 0xC0C0C0, 0xA0A0A0, 0x808080, 0x606060, 0x404040, 0x202020, 0x000000, 0x808080 };
        }
    }
}

getHeightはカンバス内の割合(%)。サイズ計算の都合上、プロットするバーの合計が100%丁度だと下に隙間が出来ることがあるので、一番下のパターンは+3%ほど大きめに定義しとくのがヨロシ。


カラーバーパターンをカンバスに描画

    abstract class DrawImageBase : IDrowPattern
    {
        // 略

        /// <summary>
        /// カラー配列を元にカラーバーを描画
        /// </summary>
        /// <param name="aimg">描画するキャンバス</param>
        /// <param name="acolor">カラー配列</param>
        /// <param name="aRange">aimg内での描画座標</param>
        protected void DrowColorBar(Bitmap aimg, Int32[] acolor, Rectangle aRange)
        {
            Graphics g = Graphics.FromImage(aimg);

            int barwidth = (int)aRange.Width / acolor.Length;
            Rectangle tmpRect = new Rectangle();
            tmpRect.Y = aRange.Top;
            tmpRect.Height = aRange.Height;

            for (int i = 0; i < acolor.Length; i++)
            {
                Color tmpColor = Color.FromArgb(0xFF, Color.FromArgb(acolor[i]));
                SolidBrush b = new SolidBrush(tmpColor);

                tmpRect.X = aRange.Left + (barwidth * i);

                if (i == acolor.Length) {
                    tmpRect.Width = barwidth;
                } else {
                    tmpRect.Width = aRange.Width;
                }
                g.FillRectangle(b, tmpRect);
            }
        }

        /// <summary>
        /// カラーバーインターフェイスを元にカラーバーを描画
        /// </summary>
        /// <param name="aimg">描画するキャンバス</param>
        /// <param name="aBarPattern">カラーバーインターフェイス</param>
        /// <param name="aRange">aimg内での描画座標</param>
        protected void DrowColorBar(Bitmap aimg, IBarPattern aBarPattern, Rectangle aRange)
        {
            // めんどくさいので配列にとって配列版DrowColorBarを呼び出す
            Int32[] colorarray = new Int32[aBarPattern.count];

            for (int i = 0; i < colorarray.Length; i++) {
                colorarray[i] = aBarPattern.next();
            }
            DrowColorBar(aimg, colorarray, aRange);
        }
    }

当初、配列を直接定義してた名残。直すのも面倒だし、今のところはいいか。