スペクトログラム2 - peace098beat/windows_applicaciton GitHub Wiki

Fitibtコンターに使った用

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FitBitvsMouseLogApp
{
    public class Spectrogram : Panel
    {
        // スペクトログラムのBitmapばっふぁ 
        Bitmap bitmap_buffer = null;

        // フォント
        Font Font_s = new Font("Arial", 7);
        Font Font_m = new Font("Arial", 9);
        Font Font_l = new Font("Arial", 11);

        TextFormatFlags FontAlignMid = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter; // センター寄オプション
        TextFormatFlags FontAlignLeft = TextFormatFlags.Left | TextFormatFlags.VerticalCenter; // センター寄オプション
        TextFormatFlags FontAlignRight = TextFormatFlags.Right | TextFormatFlags.VerticalCenter; // センター寄オプション

        public Spectrogram()
        {

            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.DoubleBuffered = true; // ダブルバッファリング: ちらつき防止
        }



        public List<double[]> ValueMatrix = null;
        public double vMax = double.MinValue;
        public double vMin = double.MaxValue;

        /// <summary>
        /// 描画するデータのセット
        /// </summary>
        /// <param name="ValueMatrix">描画する2テンソルデータ</param>
        /// <param name="BmpHeight">描画するビットマップの高さ</param>
        public void Plot(List<double[]> ValueMatrix, int BmpHeight = 512)
        {
            this.ValueMatrix = ValueMatrix;

            this.ValueMatrix.Reverse();

            int boxpix = 8;

            int xWidth = 512;                                                   // 画像の高さを設定
            int yWidth = ValueMatrix.Count;

            int bmpWidth = xWidth;
            int bmpHeight = yWidth * boxpix;

            bitmap_buffer = new Bitmap(bmpWidth, bmpHeight);

            // カラーマップ
            var cmap = ColorMap.GenerateColorMapColors();

            // 最大,最小
            vMax = double.MinValue;
            vMin = double.MaxValue;

            double _vMin = double.MaxValue;

            for (int i = 0; i < ValueMatrix.Count; i++)
            {
                for (int j = 0; j < ValueMatrix[i].Length; j++)
                {
                    //ValueMatrix[i][j] = Math.Log(ValueMatrix[i][j]+1);
                }


                vMax = Math.Max(vMax, ValueMatrix[i].Max());
                vMin = Math.Min(vMin, ValueMatrix[i].Min());


            }
 
            for (int yi = 0; yi < yWidth; yi++) //縦トレース
            {
                for (int xi = 0; xi < xWidth; xi++) // 横トレース
                {
                    //色を決める
                    int xindex = (int)Math.Floor(ValueMatrix[yi].Length * ((double)xi / xWidth));

                    var value = ValueMatrix[yi][xindex];

                    //正規化
                    value = (value - vMin) / (vMax - vMin);
                    if (value > 1.0) value = 1.0;
                    if (value < 0.0) value = 0.0;

                    int cindex = (int)(255 * value);
                    Color c = cmap[cindex];

                    ////1つのピクセルの色を変える
                    for (int i = 0; i < boxpix; i++)
                    {
                        bitmap_buffer.SetPixel(xi, (bmpHeight - 1) - (yi * boxpix + i), c);
                    }
                    bitmap_buffer.SetPixel(xi, (bmpHeight - 1) - (yi * boxpix + 0), Color.FromArgb(100, 100, 100, 100));
                }
            }


            //補間方法を指定して画像を縮小して描画する

            this.Refresh();
        }

        public List<DateTime> YDatetimeList = null;
        public void SetYDateTime(List<DateTime> dList)
        {
            this.YDatetimeList = new List<DateTime>(dList);
            this.YDatetimeList.Reverse();
            this.Refresh();

        }

        protected override void OnResize(EventArgs eventargs)
        {
            base.OnResize(eventargs);
        }



        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if (bitmap_buffer == null) return;


            // Graphicsオブジェクトを作成する
            var g = e.Graphics;

            //補間方法として最近傍補間を指定する
            //g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
            ////補間方法として高品質双三次補間を指定する
            //g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;

            //画像を縮小して描画する
            g.DrawImage(bitmap_buffer, 0, 0, this.Width, this.Height);

            //g.DrawLine(new Pen(Color.White), new Point(mouse_x, 0), new Point(mouse_x, pictureBox1.Height));
            //g.DrawLine(new Pen(Color.White), new Point(0, mouse_y), new Point(pictureBox1.Width, mouse_y));

            double x, y, xDiv, yDiv;
            /*
             * Y軸罫線
             */
            if (YDatetimeList != null)
            {
                int yMaxCount = YDatetimeList.Count;

                int Yskip = 10;
                if (yMaxCount < 100) Yskip = 1;
                else Yskip = 7;

                for (int yi = 0; yi < yMaxCount; yi += Yskip) //縦トレース
                {
                    //Rectangle RC_DateText = new Rectangle((int)(Width * 0.5), (int)((Height-1) - (double)(yi / yMaxCount) * Height), 200, 20);
                    yDiv = (double)Height / yMaxCount;

                    y = Height - (yi * yDiv) - yDiv;

                    Rectangle RC_DateText = new Rectangle((int)(Width * 0.0), (int)y, 200, 20);
                    string text = $"{YDatetimeList[yi].ToLongDateString()}:{YDatetimeList[yi].DayOfWeek.ToString()}";
                    TextRenderer.DrawText(g, text, Font_l, RC_DateText, Color.Black, FontAlignLeft);
                }
            }

            /*
             * X軸文字
             */
            if (YDatetimeList != null)
            {
                int xMaxCout = 9;
                for (int xi = 0; xi < xMaxCout; xi++)
                {
                    xDiv = (double)Width / (xMaxCout - 1);
                    x = xi * xDiv;

                    y = (1 - 0.05) * Height;

                    Rectangle RC_DateText2 = new Rectangle((int)x, (int)y, 200, 20);

                    TextRenderer.DrawText(g, $"{3 * xi}時", Font_l, RC_DateText2, Color.Black, FontAlignLeft);

                    g.DrawLine(Pens.Gray, new Point((int)x, 0), new Point((int)x, Height));

                }

            }

            /*
             * 最大値vMax, 最小値vMin
             */
            x = 0.8 * Width;
            y = (1 - 0.05) * Height;
            Rectangle RC_DateText3 = new Rectangle((int)x, (int)y, 200, 20);
            TextRenderer.DrawText(g, $"Max:{(int)vMax}, Min:{(int)vMin}", Font_l, RC_DateText3, Color.Black, FontAlignLeft);



            // END
        }


    }
}

ColorMap.cs

using System;
using System.Collections.Generic;
using System.Drawing;

namespace FitBitvsMouseLogApp
{
    public class ColorMap
    {


        /// <summary>
        /// 100分率から256階調のカラーマップを生成
        /// </summary>
        /// <param name="in_value"></param>
        /// <returns></returns>
        public static int[] ColorScaleFloat2RGB3i(double in_value)
        {
            // 0.0~1.0 の範囲の値をサーモグラフィみたいな色にする
            // 0.0                    1.0
            // 青    水    緑    黄    赤
            // 最小値以下 = 青
            // 最大値以上 = 赤
            int[] ret;
            int a = 255;    // alpha値
            int r, g, b;    // RGB値
            double value = in_value;
            double tmp_val = Math.Cos(4 * Math.PI * value);
            int col_val = (int)((-tmp_val / 2 + 0.5) * 255);
            if (value >= (4.0 / 4.0)) { r = 255; g = 0; b = 0; }   // 赤
            else if (value >= (3.0 / 4.0)) { r = 255; g = col_val; b = 0; }   // 黄~赤
            else if (value >= (2.0 / 4.0)) { r = col_val; g = 255; b = 0; }   // 緑~黄
            else if (value >= (1.0 / 4.0)) { r = 0; g = 255; b = col_val; }   // 水~緑
            else if (value >= (0.0 / 4.0)) { r = 0; g = col_val; b = 255; }   // 青~水
            else { r = 0; g = 0; b = 255; }   // 青
            // int
            ret = new int[3] { r, g, b };
            return ret;
        }

        /// <summary>
        /// 100分率から256階調のカラーマップを生成
        /// </summary>
        /// <param name="in_value"></param>
        /// <returns></returns>
        public static float[] ColorScaleFloat2RGB3f(double in_value)
        {
            // int
            int[] RGB = ColorScaleFloat2RGB3i(in_value);

            // int -> float
            return new float[3] { (float)RGB[0] / 255.0f, (float)RGB[1] / 255.0f, (float)RGB[2] / 255.0f };
        }

        /// <summary>
        /// 256階調のカラーマップを生成
        /// </summary>
        /// <returns></returns>
        public static List<float[]> GenerateColorMap3f()
        {
            List<float[]> ColorMapf = new List<float[]>();

            int N = 255;

            double value;

            for (int n = 0; n <= N; n++)
            {
                value = (double)n / N;

                float[] Colorf = ColorMap.ColorScaleFloat2RGB3f(value);

                ColorMapf.Add(Colorf);
            }

            if (ColorMapf.Count != 256) throw new ArgumentOutOfRangeException($"ColorMapf.Count:{ColorMapf.Count} != 256");

            return ColorMapf;
        }

        /// <summary>
        /// 256階調のカラーマップを生成
        /// </summary>
        /// <returns></returns>
        public static List<int[]> GenerateColorMap3i()
        {
            List<int[]> ColorMapf = new List<int[]>();

            int N = 255;

            double value;

            for (int n = 0; n <= N; n++)
            {
                value = (double)n / N;

                int[] Color3i = ColorMap.ColorScaleFloat2RGB3i(value);

                ColorMapf.Add(Color3i);
            }

            if (ColorMapf.Count != 256) throw new ArgumentOutOfRangeException($"ColorMapf.Count:{ColorMapf.Count} != 256");

            return ColorMapf;
        }

        /// <summary>
        /// 256階調のカラーマップを生成
        /// </summary>
        /// <returns></returns>
        public static Color[] GenerateColorMapColors()
        {
            int N = 255;

            Color[] ColorMapf = new Color[256];

            double value;

            for (int n = 0; n <= N; n++)
            {
                value = (double)n / N;

                int[] Color3i = ColorMap.ColorScaleFloat2RGB3i(value);

                ColorMapf[n] = Color.FromArgb(Color3i[0], Color3i[1], Color3i[2]);
            }

            if (ColorMapf.Length != 256) throw new ArgumentOutOfRangeException($"ColorMapf.Count:{ColorMapf.Length} != 256");

            return ColorMapf;
        }
    }
}
⚠️ **GitHub.com Fallback** ⚠️