はじめに
前回の改良版になります。
今回の改良ポイントは、行ごとにフォントサイズを変更出来るようにしました。
それからテキスト以外にもロゴなどの画像もスクロール出来るようにしました。
さらに表示した内容をAVI形式の動画として保存出来るようにしました。
出来上がりイメージ
できあがる動画(AVI形式)のサイズが大きいので、Windows10標準の「フォト」でトリミングしてMP4形式で保存してあります。
ソースのダウンロード
VisualStudio 2019 Comunityで作成したソースファイルをzip圧縮してあります。
ちょこっと解説
動画の保存には、Accord Video for Windowsを利用してみました。
インストールは、VisualStudio のツールメニューから
「NuGetパッケージマネージャ」の「ソリューションのNuGetパッケージ管理」を実行して表示された画面の左上の「参照」をクリックします。
検索欄にvfwと入力すると「Accord.Video.VFW」が表示されるのでクリックします。
プロジェクトを選択してインストールできます。
動画関連で追加したコード【RollForm.cs】
11行目 using Accord.Video.VFW; を追加
31行目 AVIWriter mAviWriter = new AVIWriter(); を追加
93行目 mAviWriter.FrameRate = 60; を追加。フレームレートを60で設定
94行目 mAviWriter.Open("EndRoll.avi", SCR_WIDTH, SCR_HEIGHT); を追加。動画ファイル名をEndRoll.aviとしてRollFormのサイズでオープンします。
140行目 mAviWriter.AddFrame(mScreen); を追加。ここで表示画面を動画に追加してます。
149行目~153行目 に画面が閉じる際に動画ファイルをクローズするようにしてます。
mAviWriter.Close();
ほんの数行で簡単に実装できました。
フォントサイズで追加・変更となったコード
前回は表示テキストをひとまとめにしてましたが、行ごとに分割しました。
73行目 mRollText = this.RollText.Split('\n');
改行コードで分割して配列に格納してます。
RollForm_Paintでテキストを出力していましたが、OutputText(Graphics g)を作成してテキスト出力部分を移動しました。179行目以降
今回、出力するテキストの先頭に種類とフォントサイズを指定出来るようにしました。指定方法は以下の通りです。
TXT,11;ここに出力される文字
セミコロン”;”で区切ります。”ここに出力される文字”を11ポイントで出力できます。
ロゴなどの画像の指定は以下の通りです。
IMG,327,54;画像.jpg
TXTと同様にセミコロン”;”で区切ります。IMGの後の数字は画像サイズです。327が幅で54が高さです。
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Accord.Video.VFW; namespace EndRoll { public partial class RollForm : Form { static readonly int TILE_SIZE = 8; static readonly int TIMER_INTERVAL = 16; static readonly int MAP_WIDTH = 80; static readonly int MAP_HEIGHT = 50; static readonly int SCR_WIDTH = MAP_WIDTH * TILE_SIZE; static readonly int SCR_HEIGHT = MAP_HEIGHT * TILE_SIZE; static readonly int WND_WIDTH = SCR_WIDTH * 2; static readonly int WND_HEIGHT = SCR_HEIGHT * 2; //static readonly int WAIT = 60; static readonly int DPI = 96; static readonly float POINT_TO_PIXEL = (int)(DPI / 72 * 100) / 100; static readonly int LINE_SPACE = 8; AVIWriter mAviWriter = new AVIWriter(); Bitmap mScreen = new Bitmap(SCR_WIDTH, SCR_HEIGHT); Bitmap[] mTile; byte[,] mTileLayout; int mTimer; int mKeyEsc; bool mCancel; bool mEnd; int mX, mY, mDX, mDY; int mRowsCount; Random mRnd = new Random(); int mLen; public string RollText { get; set; } private string[] mRollText; public RollForm() { InitializeComponent(); } private void RollForm_Load(object sender, EventArgs e) { string s = RollText; int ndx; Bitmap bm = new Bitmap("tile.png"); ClientSize = new Size(WND_WIDTH, WND_HEIGHT); DoubleBuffered = true; mKeyEsc = 0; mCancel = false; mX = 0; mY = MAP_HEIGHT + 2; mDY = 0; mRowsCount = (s.Length - s.Replace("\r", "").Length) * TILE_SIZE; //mRowsCount = (s.Length - s.Replace("\r", "").Length); mRollText = this.RollText.Split('\n'); mLen = bm.Width / TILE_SIZE; mTile = new Bitmap[mLen]; for (int i = 0; i < mLen; i++) { mTile[i] = bm.Clone(new Rectangle(i * TILE_SIZE, 0, TILE_SIZE, TILE_SIZE), bm.PixelFormat); } mTileLayout = new byte[MAP_WIDTH, MAP_HEIGHT]; for (int y = 0; y < MAP_HEIGHT; y++) { for (int x = 0; x < MAP_WIDTH; x++) { ndx = mRnd.Next(mLen); mTileLayout[x,y] = (byte)ndx; } } // AVI Writer mAviWriter.FrameRate = 60; mAviWriter.Open("EndRoll.avi", SCR_WIDTH, SCR_HEIGHT); Task.Run(() => { mTimer = System.Environment.TickCount; while (!mEnd) { OnTimer(); mTimer += TIMER_INTERVAL; Task.Delay(Math.Max(1, mTimer - System.Environment.TickCount)).Wait(); } this.DialogResult = DialogResult.OK; return; }); } private void RollForm_Paint(object sender, PaintEventArgs e) { Graphics g = Graphics.FromImage(mScreen); //Font f = new Font("Meiryo", 11); //StringFormat sfmt = new StringFormat(); //sfmt.Alignment = StringAlignment.Center; g.Clear(BackColor); for (int y = 0; y < MAP_HEIGHT; y++) { for (int x = 0; x < MAP_WIDTH; x++) { g.DrawImage(mTile[mTileLayout[x,y]], x *TILE_SIZE, y *TILE_SIZE); } } if (mCancel) { this.DialogResult = DialogResult.Cancel; return; } //Debug.Print((mY * TILE_SIZE + mDY).ToString()); //g.DrawString(RollText, f, Brushes.White, mX * TILE_SIZE + TILE_SIZE * MAP_WIDTH / 2, mY * TILE_SIZE + mDY, sfmt); OutputText(g); e.Graphics.DrawImage(mScreen, 0, 0, WND_WIDTH, WND_HEIGHT); //mScreen.Save("test.png"); // AVI mAviWriter.AddFrame(mScreen); } private void RollForm_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Escape) mKeyEsc++; } private void RollForm_FormClosed(object sender, FormClosedEventArgs e) { mAviWriter.Close(); mAviWriter.Dispose(); } private void OnTimer() { Tick(); if (mKeyEsc > 0) mCancel = true; Invalidate(); } private void Tick() { if (Math.Abs(mDY) < TILE_SIZE-1) { mDY--; return; } mDY = 0; if (mY < mRowsCount * -1) { mEnd = true; return; } mY--; } private void OutputText(Graphics g) { StringFormat sfmt = new StringFormat(); sfmt.Alignment = StringAlignment.Center; Font f = new Font("Meiryo", 11); int l = mRollText.Length; string[] s, s2; int addY = 0; string flg; Bitmap bm; int bmX=0, bmY=0; for (int i = 0; i < l; i++) { s = new string[2]; if (mRollText[i].Length > 3) { s2 = mRollText[i].Split(';'); flg = s2[0].Split(',')[0]; if (flg == "TXT") { s[0] = s2[0].Split(',')[1]; s[1] = s2[1]; } else if (flg == "IMG") { bmX = int.Parse(s2[0].Split(',')[1]); bmY = int.Parse(s2[0].Split(',')[2]); s[1] = s2[1]; } } else { flg = "TXT"; s[0] = "11"; s[1] = ""; } if (flg == "TXT") { f = new Font("Meiryo", float.Parse(s[0])); g.DrawString(s[1], f, Brushes.White, mX * TILE_SIZE + TILE_SIZE * MAP_WIDTH / 2, mY * TILE_SIZE + mDY + addY, sfmt); addY += (int)(float.Parse(s[0]) * POINT_TO_PIXEL) + LINE_SPACE; } else if (flg == "IMG") { bm = new Bitmap(s[1]); g.DrawImage(bm, mX * TILE_SIZE + (TILE_SIZE * MAP_WIDTH - bmX) / 2, mY * TILE_SIZE + mDY + addY); addY += bmY + LINE_SPACE; } } } } } |
最後に
前回、今回とはじめてYouTubeに動画をアップして記事中に埋め込んでみましたが意外と簡単にできてホットしております。
とりあえずやってみたかったことが大体実現できることがわかったので、ひとまず完了です。