/** * * 女医ハックAviUtlプラグイン AviUtl99c以降 * Copyright (C) 2008 id:yuaaaa * * $Id$ */ #include #include #include #include #include "filter.h" using namespace System::Drawing; HWND g_hwnd; bool g_utf8 = false; PIXEL *g_rgbpic = NULL; //スレッドセーフ的なアレを犠牲に... size_t g_rgbpicsize = 0; gcroot g_joyhack; gcrootg_fswatch; gcrootg_errmsg; WCHAR g_filename[MAX_PATH] = L""; typedef struct { WCHAR filename[MAX_PATH]; } JHFilter_EXDATA; JHFilter_EXDATA g_exdata = {L""}; //JHFilter_EXDATA g_exdatadef = {""}; //--------------------------------------------------------------------- // フィルタ構造体定義 //--------------------------------------------------------------------- #define TRACK_N 3 // トラックバーの数 TCHAR *track_name[] = { _T("Delay"), _T("fps(n/30)") , _T("FontSize") }; // トラックバーの名前 int track_default[] = { 0, 30, 30 }; // トラックバーの初期値 int track_s[] = { -600, 1, 6 }; // トラックバーの下限値 int track_e[] = { +600, 60, 128 }; // トラックバーの上限値 #define MY_TRACK_DELAY 0 #define MY_TRACK_FPS 1 #define MY_TRACK_FONTSIZE 2 #define CHECK_N 7 // チェックボックスの数 TCHAR *check_name[] = { _T("Change Immediately"), _T("Debug Output"), _T("Disable Cache"), _T("Use UTF-8"), _T("Copy ErrorString"), _T("Reload") , _T("File Select...") }; // チェックボックスの名前 int check_default[] = { 0, 0, 0, 0, -1 , -1, -1 }; // チェックボックスの初期値 (値は0か1) #define MY_CHECK_IMMEDIATE 0 #define MY_CHECK_DEBUG 1 #define MY_CHECK_CACHE 2 #define MY_CHECK_UTF8 3 #define MY_CHECK_ERRORSTR 4 #define MY_CHECK_RELOAD 5 #define MY_CHECK_FILE 6 FILTER_DLL filter = { FILTER_FLAG_EX_INFORMATION // フィルタのフラグ | FILTER_FLAG_EX_DATA, // FILTER_FLAG_ALWAYS_ACTIVE : フィルタを常にアクティブにします // FILTER_FLAG_CONFIG_POPUP : 設定をポップアップメニューにします // FILTER_FLAG_CONFIG_CHECK : 設定をチェックボックスメニューにします // FILTER_FLAG_CONFIG_RADIO : 設定をラジオボタンメニューにします // FILTER_FLAG_EX_DATA : 拡張データを保存出来るようにします。 // FILTER_FLAG_PRIORITY_HIGHEST : フィルタのプライオリティを常に最上位にします // FILTER_FLAG_PRIORITY_LOWEST : フィルタのプライオリティを常に最下位にします // FILTER_FLAG_WINDOW_THICKFRAME : サイズ変更可能なウィンドウを作ります // FILTER_FLAG_WINDOW_SIZE : 設定ウィンドウのサイズを指定出来るようにします // FILTER_FLAG_DISP_FILTER : 表示フィルタにします // FILTER_FLAG_EX_INFORMATION : フィルタの拡張情報を設定できるようにします // FILTER_FLAG_NO_CONFIG : 設定ウィンドウを表示しないようにします // FILTER_FLAG_AUDIO_FILTER : オーディオフィルタにします // FILTER_FLAG_RADIO_BUTTON : チェックボックスをラジオボタンにします // FILTER_FLAG_WINDOW_HSCROLL : 水平スクロールバーを持つウィンドウを作ります // FILTER_FLAG_WINDOW_VSCROLL : 垂直スクロールバーを持つウィンドウを作ります // FILTER_FLAG_IMPORT : インポートメニューを作ります // FILTER_FLAG_EXPORT : エクスポートメニューを作ります 0,0, // 設定ウインドウのサイズ (FILTER_FLAG_WINDOW_SIZEが立っている時に有効) _T("JoyHack"), // フィルタの名前 TRACK_N, // トラックバーの数 (0なら名前初期値等もNULLでよい) track_name, // トラックバーの名前郡へのポインタ track_default, // トラックバーの初期値郡へのポインタ track_s,track_e, // トラックバーの数値の下限上限 (NULLなら全て0〜256) CHECK_N, // チェックボックスの数 (0なら名前初期値等もNULLでよい) check_name, // チェックボックスの名前郡へのポインタ check_default, // チェックボックスの初期値郡へのポインタ func_proc, // フィルタ処理関数へのポインタ (NULLなら呼ばれません) func_init, // 開始時に呼ばれる関数へのポインタ (NULLなら呼ばれません) func_exit, // 終了時に呼ばれる関数へのポインタ (NULLなら呼ばれません) func_update, // 設定が変更されたときに呼ばれる関数へのポインタ (NULLなら呼ばれません) func_WndProc, // 設定ウィンドウにウィンドウメッセージが来た時に呼ばれる関数へのポインタ (NULLなら呼ばれません) NULL,NULL, // システムで使いますので使用しないでください &g_exdata, // 拡張データ領域へのポインタ (FILTER_FLAG_EX_DATAが立っている時に有効) sizeof(JHFilter_EXDATA), // 拡張データサイズ (FILTER_FLAG_EX_DATAが立っている時に有効) _T("JoyHack AviUtlフィルタ by ..."), // フィルタ情報へのポインタ (FILTER_FLAG_EX_INFORMATIONが立っている時に有効) NULL, // セーブが開始される直前に呼ばれる関数へのポインタ (NULLなら呼ばれません) NULL, // セーブが終了した直前に呼ばれる関数へのポインタ (NULLなら呼ばれません) NULL, //exfunc NULL, //hwnd NULL, //dll_hinst NULL, //ex_data_def NULL, //func_project_load, //func_project_save }; //--------------------------------------------------------------------- // フィルタ構造体のポインタを渡す関数 //--------------------------------------------------------------------- EXTERN_C FILTER_DLL __declspec(dllexport) * __stdcall GetFilterTable( void ) { return &filter; } void load_joyhack ( ) { if ( (JHDrawLib::DrawJoyHack^)g_joyhack != nullptr ) { g_errmsg = ""; try { System::Text::Encoding ^encode = System::Text::Encoding::GetEncoding(932); if ( g_utf8 ) { encode = System::Text::Encoding::UTF8; } g_joyhack->load_data ( gcnew System::String(g_filename), encode ); } catch ( System::Exception ^e ) { g_errmsg = e->Message; } } } void file_Change(System::Object ^sender, System::IO::FileSystemEventArgs ^ev) { load_joyhack ( ); } void set_filename ( FILTER *fp ) //use g_filename { wcsncpy_s( g_exdata.filename, MAX_PATH, g_filename, MAX_PATH ); load_joyhack ( ); try { System::IO::FileInfo ^finfo = gcnew System::IO::FileInfo( gcnew System::String(g_filename) ); g_fswatch->Path = finfo->DirectoryName; g_fswatch->Filter = finfo->Name; g_fswatch->EnableRaisingEvents = fp->check[MY_CHECK_IMMEDIATE] ? true : false ; } catch (System::Exception ^e ) { g_fswatch->EnableRaisingEvents = false; } } void show_filedlg ( FILTER *fp ) { System::Windows::Forms::OpenFileDialog ^opdlg = gcnew System::Windows::Forms::OpenFileDialog(); opdlg->FileName = gcnew System::String(g_filename); opdlg->Filter = "JoyHack file (*.txt)|*.txt|All Files (*.*)|*.*"; opdlg->Title = "Load JoyHack file..."; // for Unicode... //if ( fp->exfunc->dlg_get_load_name // ( g_filename, "HackENT file (*.txt)\0*.txt\0All Files (*.*)\0*.*", g_filename ) ) if ( opdlg->ShowDialog() == System::Windows::Forms::DialogResult::OK ) { pin_ptr pin_file = PtrToStringChars(opdlg->FileName); wcsncpy_s( g_filename, MAX_PATH, (WCHAR*)pin_file, opdlg->FileName->Length ); set_filename( fp ); } } BOOL func_init( FILTER *fp ) { g_joyhack = nullptr; g_errmsg = ""; g_fswatch = gcnew System::IO::FileSystemWatcher(); g_fswatch->NotifyFilter = System::IO::NotifyFilters::LastWrite | System::IO::NotifyFilters::Size; g_fswatch->IncludeSubdirectories = false; g_fswatch->Changed += gcnew System::IO::FileSystemEventHandler( file_Change ); //show_filedlg( fp ); return TRUE; } BOOL func_exit ( FILTER *fp ) { if ( g_rgbpic != NULL ) { VirtualFree(g_rgbpic, g_rgbpicsize, MEM_DECOMMIT ); } return TRUE; } BOOL func_WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, void *editp, FILTER *fp ) { switch ( message ) { case WM_COMMAND: if ( wparam == MID_FILTER_BUTTON + MY_CHECK_ERRORSTR ) { if ( ! System::String::IsNullOrEmpty(g_errmsg) ) { System::Windows::Forms::Clipboard::SetText( g_errmsg ); } return TRUE; } if ( wparam == MID_FILTER_BUTTON + MY_CHECK_RELOAD ) { load_joyhack (); return TRUE; } if ( wparam == MID_FILTER_BUTTON + MY_CHECK_FILE ) { show_filedlg( fp ); return TRUE; } break; } return FALSE; } BOOL func_update ( FILTER *fp, int status ) { try { g_fswatch->EnableRaisingEvents = fp->check[MY_CHECK_IMMEDIATE] ? true : false ; } catch (System::Exception ^e ) { g_fswatch->EnableRaisingEvents = false; } g_utf8 = fp->check[MY_CHECK_UTF8] ? true : false ; if ( (JHDrawLib::DrawJoyHack^)g_joyhack != nullptr ) { g_joyhack->timeUserFix = fp->track[MY_TRACK_DELAY]; g_joyhack->defaultFontSize = fp->track[MY_TRACK_FONTSIZE]; g_joyhack->debug = fp->check[MY_CHECK_DEBUG] ? true : false ; g_joyhack->disable_cache = fp->check[MY_CHECK_CACHE] ? true : false ; if ( status == FILTER_UPDATE_STATUS_CHECK + 0 || fp->check[MY_CHECK_IMMEDIATE] ) { if ( fp->check[MY_CHECK_IMMEDIATE] ) { load_joyhack(); } } } return TRUE; } //--------------------------------------------------------------------- // フィルタ処理関数 //--------------------------------------------------------------------- BOOL func_proc( FILTER *fp,FILTER_PROC_INFO *fpip ) { // // fp->track[n] : トラックバーの数値 // fp->check[n] : チェックボックスの数値 // fpip->w : 実際の画像の横幅 // fpip->h : 実際の画像の縦幅 // fpip->max_w : 画像領域の横幅 // fpip->max_h : 画像領域の縦幅 // fpip->ycp_edit : 画像領域へのポインタ // fpip->ycp_temp : テンポラリ領域へのポインタ // fpip->ycp_edit[n].y : 画素(輝度 )データ ( 0 〜 4096 ) // fpip->ycp_edit[n].cb : 画素(色差(青))データ ( -2048 〜 2048 ) // fpip->ycp_edit[n].cr : 画素(色差(赤))データ ( -2048 〜 2048 ) // // 画素データは範囲外に出ていることがあります。 // また範囲内に収めなくてもかまいません。 // // 画像サイズを変えたいときは fpip->w や fpip->h を変えます。 // // テンポラリ領域に処理した画像を格納したいときは // fpip->ycp_edit と fpip->ycp_temp を入れ替えます。 // if ( wcsncmp( g_filename, L"", MAX_PATH ) == 0 ) { if ( wcsncmp( g_exdata.filename, L"", MAX_PATH ) != 0 ) { wcsncpy_s( g_filename, MAX_PATH, g_exdata.filename, MAX_PATH ); } else { return FALSE; } } if ( (JHDrawLib::DrawJoyHack^)g_joyhack == nullptr ) { g_joyhack = gcnew JHDrawLib::DrawJoyHack( fpip->w, fpip->h ); set_filename( fp ); func_update( fp, 0 ); } else if ( g_joyhack->width != fpip->w || g_joyhack->height != fpip-> h ) { g_joyhack->width = fpip->w; g_joyhack->height = fpip->h; set_filename( fp ); } FILE_INFO finfo; fp->exfunc->get_file_info( fpip->editp, &finfo ); double vrate = ( finfo.video_rate /1000.0 ) * ( fp->track[MY_TRACK_FPS] /30.0) ; double now = fpip->frame / vrate; int thisf = (int)(60*now); if ( g_rgbpic == NULL ) { g_rgbpicsize = sizeof(PIXEL) * fpip->max_w * fpip->max_h; g_rgbpic = (PIXEL*) VirtualAlloc(NULL, g_rgbpicsize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); } //PIXEL *rgbpic; //rgbpic = (PIXEL*) VirtualAlloc(NULL, sizeof(PIXEL) * fpip->max_w * fpip->max_h, // MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); fp->exfunc->yc2rgb( g_rgbpic, fpip->ycp_edit, fpip->max_w * fpip->max_h ); System::Drawing::Bitmap ^bmp0 = gcnew Bitmap(fpip->max_w, fpip->max_h, fpip->max_w * sizeof(PIXEL), System::Drawing::Imaging::PixelFormat::Format24bppRgb, (System::IntPtr)g_rgbpic ); System::Drawing::Graphics ^g = Graphics::FromImage(bmp0); if ( fp->check[1] /*debug*/ ) { g->DrawString( vrate.ToString() + gcnew System::String(" fps") , gcnew Font(FontFamily::GenericMonospace, 12 ), Brushes::Green, System::Drawing::RectangleF(0.0f, (float)fpip->h-16,(float)fpip->w,(float)fpip->h)); } if ( ! System::String::IsNullOrEmpty(g_errmsg) ) { g->DrawString( gcnew System::String("[Error] ") + g_errmsg, gcnew Font(FontFamily::GenericMonospace, 16 ), Brushes::Red, System::Drawing::RectangleF(0.0f,0.0f,(float)fpip->w,(float)fpip->h)); } else { //g_joyhack->drawENT ( g, gcnew JoyHack::Timecode(thisf) ); JoyHack::Timecode ^fixedtime = g_joyhack->getFixedTimecode(gcnew JoyHack::Timecode(thisf)); System::Collections::Generic::List ^phrlist; System::Int32 nowphrpos = g_joyhack->getDrawPhraseList(fixedtime, phrlist ); if ( phrlist != nullptr ) { for each ( JHDrawLib::DrawPhraseCond phrc in phrlist ) { if ( phrc.phr == nullptr ) { continue; } g_joyhack->drawPhraseUsingCache( g, phrc, fixedtime); } } if ( fp->check[1] /*debug*/ ) { g->DrawString( nowphrpos.ToString() + gcnew System::String(" ") + fixedtime->ToString() , gcnew Font(FontFamily::GenericMonospace, 20 ), Brushes::Blue, 10, 10); if ( g_joyhack->warning != nullptr ) { g->DrawString( g_joyhack->warning , gcnew Font(FontFamily::GenericMonospace, 15 ), Brushes::Yellow, 10, 30); } } } Imaging::BitmapData^ bdata; bdata = bmp0->LockBits( System::Drawing::Rectangle(0,0,fpip->max_w, fpip->max_h),Imaging::ImageLockMode::ReadOnly, Imaging::PixelFormat::Format24bppRgb); fp->exfunc->rgb2yc( fpip->ycp_edit, (PIXEL*)bdata->Scan0.ToPointer(), fpip->max_w * fpip->max_h ); bmp0->UnlockBits(bdata); //VirtualFree(rgbpic, sizeof(PIXEL) * fpip->max_w * fpip->max_h, MEM_DECOMMIT ); return TRUE; }