トップページ > 記事閲覧
動画保存について
名前:タニシン 日時: 2020/05/27 11:45

こんにちは。 突然で済みませんが、画面を動画ファイル形式で保存することはプログラム上で可能でしょうか。 現時点ではDXライブラリで動画を保存して再度DXライブラリに組み込むのに 1. SaveDrawScreenで連番で画像ファイル化 2. 外部ソフトで連番ファイルを動画ファイルに変換 という手順で行なっていますが、外部ソフトを使わないといけないため不便に感じております。 また、連番ファイルは動画ファイル変換後は使用しないため削除作業も必要になります。 プログラム内で動画を保存して保存後に再生プレビューする機能を実装したいため、できれば内部で完結させたいと考えております。
メンテ

Page: 1 |

Re: 動画保存について ( No.1 )
名前:B.E 日時:2020/05/28 05:17

DXライブラリには動画保存機能ないんじゃないですかね…。(隠し関数にも見当たらないので…) ただ、動画の保存自体はWindowsならvfw32.libを使えばできますよ。 DXの描画画面をソフトウェアイメージに転送してポインタを取得し、それを指定して書き出すって感じです。 以下、DXライブラリで描画した画面をvfw32.libで動画保存するサンプルです。 #include "DxLib.h" #include <vfw.h> #pragma comment(lib,"vfw32.lib") int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int WIDTH = 800, HEIGHT = 600; int TotalFrame = 600; // ウインドウモードで起動 ChangeWindowMode(TRUE); SetGraphMode(WIDTH, HEIGHT, 32); if (DxLib_Init() < 0) return -1; // 描画先を裏画面に変更 SetDrawScreen(DX_SCREEN_BACK); // 動画保存用のソフトウエア用画像を作成 int SoftImageHandle = MakeRGB8ColorSoftImage(WIDTH, HEIGHT); // vfw32.libを初期化 AVIFileInit(); // AVISTREAMINFOを宣言・初期化 AVISTREAMINFO si = {0}; si.fccType = streamtypeVIDEO; si.fccHandler = comptypeDIB; si.dwScale = 1; si.dwRate = 60; si.dwLength = TotalFrame; si.dwQuality = -1; si.rcFrame = { 0,0,WIDTH,HEIGHT }; si.szName[0] = ' '; // BITMAPINFOHEADERを宣言・初期化 BITMAPINFOHEADER bmih = {0}; bmih.biSize = sizeof(BITMAPINFOHEADER); bmih.biWidth = WIDTH; bmih.biHeight = HEIGHT; bmih.biPlanes = 1; bmih.biBitCount = 24; bmih.biCompression = BI_RGB; // 圧縮ダイアログを表示してCOMPVARSを得る COMPVARS cv = { 0 }; cv.cbSize = sizeof(COMPVARS); cv.dwFlags = ICMF_COMPVARS_VALID; cv.fccHandler = comptypeDIB; cv.lQ = ICQUALITY_DEFAULT; if (!ICCompressorChoose(NULL, ICMF_CHOOSE_DATARATE | ICMF_CHOOSE_KEYFRAME, NULL, NULL, &cv, NULL)) { return 1;//キャンセルされた } // COMPVARSからAVICOMPRESSOPTIONSを初期化 AVICOMPRESSOPTIONS opt = {0}; opt.fccType = streamtypeVIDEO; opt.fccHandler = cv.fccHandler; opt.dwKeyFrameEvery = cv.lKey; opt.dwQuality = cv.lQ; opt.dwBytesPerSecond = cv.lDataRate; opt.dwFlags = (cv.lDataRate > 0 ? AVICOMPRESSF_DATARATE : 0) | (cv.lKey > 0 ? AVICOMPRESSF_KEYFRAMES : 0); opt.lpFormat = NULL; opt.lpParms = cv.lpState; opt.cbParms = cv.cbState; // 書き出し開始 PAVIFILE pavi; PAVISTREAM pstm, ptmp; if (AVIFileOpen(&pavi,"Test.avi", OF_CREATE | OF_WRITE | OF_SHARE_DENY_NONE, NULL) != 0) { MessageBox(NULL, "ファイルの作成またはオープンに失敗しました。", NULL, MB_ICONWARNING); return 1; } if (AVIFileCreateStream(pavi, &pstm, &si) != 0) { MessageBox(NULL, "ストリームの作成に失敗しました。", NULL, MB_ICONWARNING); AVIFileRelease(pavi); return 1; } if (AVIMakeCompressedStream(&ptmp, pstm, &opt, NULL) != AVIERR_OK) { MessageBox(NULL, "圧縮ストリームの作成に失敗しました。", NULL, MB_ICONWARNING); AVIFileRelease(pavi); return 1; } if (AVIStreamSetFormat(ptmp, 0, &bmih, sizeof(BITMAPINFOHEADER)) != 0) { MessageBox(NULL, "圧縮ストリームの設定に失敗しました。", NULL, MB_ICONWARNING); AVIFileRelease(pavi); return 1; } for(int FrameCnt = 0; FrameCnt < TotalFrame; FrameCnt++) { // 画面クリア ClearDrawScreen(); // ●を描画 DrawCircleAA(0.5f * WIDTH, 0.5f * HEIGHT, (float)FrameCnt, 64, 0x00ff00, TRUE); // フレームを描画 DrawFormatString(0, 0, 0xffffff, "%04d", FrameCnt); // 描画先の画像をソフトイメージに取得する GetDrawScreenSoftImage(0, 0, WIDTH, HEIGHT, SoftImageHandle); // ソフトウエアイメージハンドルを上下反転する(こうしないと動画が上下反転するので…) ReverseSoftImageV(SoftImageHandle) ; //動画ファイルにフレームを書き込む(ソフトウェアイメージの画像データの先頭のアドレスを指定) AVIStreamWrite(ptmp, FrameCnt, 1, GetImageAddressSoftImage(SoftImageHandle), WIDTH * HEIGHT * 3, AVIIF_KEYFRAME, NULL, NULL); // 裏画面の内容を表画面に反映 ScreenFlip(); if (ProcessMessage())break; } // 動画保存後始末 AVIStreamRelease(ptmp); AVIStreamRelease(pstm); AVIFileRelease(pavi); ICCompressorFree(&cv); AVIFileExit(); // 終了処理 DxLib_End(); return 0; } こんな感じで、とりあえずAVIは書き出せます。 ただし、vfw32.libはAVI1.0しか対応してなくて2Gまでのファイルしか保存できないので、 2G以上のファイルを書き出したい場合OpenCVとかを使うのが比較的簡単かなと思います。 その代わりOpenCVはAVIのコーデックで対応してないのが結構あります。 (まあ、mp4とか書き出せるのでそれで十分事足りると思いますが…。) ※ソフトイメージを上下反転する処理を忘れていたのでコード修正しました。すいません。
メンテ
Re: 動画保存について ( No.2 )
名前:タニシン(解決) 日時:2020/06/14 02:03

B.E さん 返信が遅くなってしまいすみません。 ご丁寧にコードまでありがとうございます。 このコードを応用すればプログラム内で実装が完了できそうです。 ただOpenCVの知見はあまりないので調査は別の機会で行おうと思います。 やりたいことはできたので解決といたします。 ありがとうございました。
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存