ION AIR PRO買ってから自転車の車載カメラ動画撮ったり見たりしてるのだが、時々スピードメーターとか心拍数とか出てる奴がある。
どうやらdashwareとかソフト使ってるみたいなのだが、できれば金かけずにやりたい。そもそも無圧縮aviファイルって結局パラパラ漫画なんだろ。と思っていたら
http://eternalwindows.jp/winmm/avi/avi07.html
に良い情報が。どこの誰だか知らないが感謝ですよ。
私の使ってるGPSはeTrex VENTURE。どうせ1秒以上の間隔でしかログ取れないし(設定できるのかも知れないが知らん)それ以上の精度には興味はない。あくまで遊びである。カシミール3Dでデータ読んでコピペでエクセルを使ってポイント名、時間(秒数)、速度の3項目だけのプレーンテキストのデータファイルをin.txtと名前つけて作る。
No. 61 11 25.3
No. 62 11 31.2
No. 63 2 31.5
No. 64 5 32.8
No. 65 13 34.7…
(ダミー文字列)区切りタブ(ダミー文字列)区切りタブ(次のスピードが維持された秒数)区切りタブ(スピード)
ダミー文字列とはポイント名なのだが、あったほうがどっからログをカットするのか分かりやすいのでsscanfでdmy,dmy2と面倒を見る。
あとはaviutlの拡張編集を使えばそれっぽいものが出来る。
#include <windows.h> #include <stdio.h> #include <vfw.h> #pragma comment (lib, "vfw32.lib") #define MAX_SEC 9999//とりあえず166分まで…。floatにしたのもなんとなくメモリ気にして。 int dofile( float table[]) { FILE *fp; int i,j; char buf[256];/*テキストファイル1行の最大文字数*/ char dmy[256]; char dmy2[256]; int sec; float km; fp = fopen( "in.txt", "r"); if( fp == NULL ) { MessageBox(NULL, "fopenのエラー", "OK", MB_OK); exit( 0); } i = 0; while( fgets( buf, sizeof( buf), fp) != NULL ) { //とりあえずテキストデータは「No. 60 0 0」(タブ区切り) if( sscanf( buf, "%s %s %d %f", dmy, dmy2, &sec, &km) == 4 ) { for( j = 0; j < sec; j++ ) { table[i + j] = km; } i += j; if( i > MAX_SEC ) { MessageBox(NULL, "166分超えた", "OK", MB_OK); exit( 0); } } else { MessageBox(NULL, "sscanfのエラー", "OK", MB_OK); exit( 0); } } fclose( fp); return i; } void WriteStream(PAVISTREAM pavi, LPAVISTREAMINFO lpsi, float table[]) { HDC hdcMem; HBITMAP hbmpMem, hbmpMemPrev; DWORD i; TCHAR szBuf[256]; LPVOID lpBits; BITMAPINFOHEADER bmiHeader; ZeroMemory(&bmiHeader, sizeof(BITMAPINFOHEADER)); bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmiHeader.biWidth = lpsi->rcFrame.right; bmiHeader.biHeight = lpsi->rcFrame.bottom; bmiHeader.biPlanes = 1; bmiHeader.biBitCount = 24; bmiHeader.biCompression = BI_RGB; bmiHeader.biSizeImage = bmiHeader.biHeight * ((3 * bmiHeader.biWidth + 3) / 4) * 4; AVIStreamSetFormat(pavi, 0, &bmiHeader, sizeof(BITMAPINFOHEADER)); hdcMem = CreateCompatibleDC(NULL); hbmpMem = CreateDIBSection(NULL, (LPBITMAPINFO)&bmiHeader, DIB_RGB_COLORS, &lpBits, NULL, 0); hbmpMemPrev = (HBITMAP)SelectObject(hdcMem, hbmpMem); SetBkMode(hdcMem, TRANSPARENT); for (i = 0; i < lpsi->dwLength; i++) { sprintf(szBuf, "%4.1fkm/h", table[i]); FillRect(hdcMem, &lpsi->rcFrame, (HBRUSH)GetStockObject(GRAY_BRUSH)); DrawText(hdcMem, szBuf, -1, &lpsi->rcFrame, DT_CENTER | DT_VCENTER | DT_SINGLELINE); AVIStreamWrite(pavi, i, 1, lpBits, bmiHeader.biSizeImage, AVIIF_KEYFRAME, NULL, NULL); } SelectObject(hdcMem, hbmpMemPrev); DeleteObject(hbmpMem); DeleteDC(hdcMem); } int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow) { int nframe;//フレーム総数。 float table[MAX_SEC];//1秒毎のkm/h。 PAVIFILE pfile; PAVISTREAM pavi; AVISTREAMINFO si; nframe = dofile( table); AVIFileInit(); if (AVIFileOpen(&pfile, TEXT("out.avi"), OF_CREATE | OF_WRITE, NULL) != 0) { MessageBox(NULL, TEXT("ファイルの作成または書き込みオープンに失敗しました。"), TEXT("OK"), MB_OK); AVIFileExit(); return 0; } ZeroMemory(&si, sizeof(AVISTREAMINFO)); si.fccType = streamtypeVIDEO; si.fccHandler = comptypeDIB; si.dwScale = 1; si.dwRate = 1;//1秒1フレーム。 si.dwLength = nframe; si.dwQuality = (DWORD)-1; SetRect(&si.rcFrame, 0, 0, 32*3, 32);//3倍しただけ if (AVIFileCreateStream(pfile, &pavi, &si) != 0) { MessageBox(NULL, TEXT("ストリームの作成に失敗しました。"), TEXT("OK"), MB_OK); AVIFileRelease(pfile); AVIFileExit(); return 0; } WriteStream(pavi, &si ,table); MessageBox(NULL, TEXT("書き込みを終了しました。"), TEXT("OK"), MB_OK); AVIStreamRelease(pavi); AVIFileRelease(pfile); AVIFileExit(); return 0; }