コードもまぁ、そんな複雑ではないな。
実質、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); } }
当初、配列を直接定義してた名残。直すのも面倒だし、今のところはいいか。