![]() |
||||||||
|
|
||||||||
|
|
AA動画の作り方 元ネタ動画 youtube↓ http://jp.youtube.com/watch?v=77c1GR1itEM 前置き 皆様アクセスありがとうございます。 動画の方いかがだったでしょうか? え?すごいのはプログラムじゃなくてPCの性能だって? その通り PCのスペックは CPU: Core2Quad Q6700 メモリ: DDRII 8GB (XP時は4GB) HDD: 1TB VGA: GeForce8800GTX フフフ、素晴らしいスペックでしょう。 もちろん ((((うp主は貧乏ですorz 家のパソコンで実行できないので、 プログラムを書いては大学まで実行しに 通いました^^; はぁ、自分のPCもこれ位ハイスペックだったらな・・(ブツブツ ・・・と、くだらない話はさておき、 AA動画の作り方を紹介します。 アスキーアート動画の作り方 プログラム言語はC言語を使用しますが、 Cにあまり詳しくない人でもコンパイル環境さえあれば 簡単に出来るのでよければ作ってみてください。 ・C言語がコンパイル出来る環境がある ・DXライブラリをインストールしている という環境の元、下をお読みください。 まず、流れとして
という、4つの工程をふみます。 動画の中では、一旦AAデータファイルを生成していましたが、 bmpファイルから一度に表示できるように プログラムを変更したので工程が少なくなりました。 ただプログラムでやってる作業は動画で言ってる様に そこまでは単純じゃありませんが、 コードは完成してるのでコピペでOKです。 1 変換したい動画を用意する。 まず、変換したい動画がないと始まりません。 youtubeやニコニコ動画から持ってくるのでしたら
こちらのソフトを使用すると ダウンロードと同時にAVIに変換してくれます。 使い方の説明は全く要らないほど操作が簡単です。 見ればわかります。 2 動画をAVIに変換する。 既に持っているmpegであったり、mp4であったりする動画は superという動画変換ソフトで変換すると良いです。
かなりの形式に対応するので、何でも変換出来ます。 3 AVIを静止画bmpファイルに変換する。 AVI2JPGというソフトを使うと
いとも簡単に変換出来てしまいます。 この時、「変換前の動画の名前がbmpのファイル名になる」ことに 注意してください。 プログラム中でファイル名を指定する必要があるので、 ファイル名は注意してください。 プログラムコードのデフォルトでは「raki.avi」である事としています。 ![]() トンでもない量のファイルが出来るので、容量には気をつけて。 スペックの低いPCだと長い動画ならいつまでたっても終わらないかも・・。 プロジェクトがあるフォルダにimage0というフォルダをつくり、 そこに画像を入れてください。 4 bmpファイルをCで読み込んで表示する。 いよいよC言語を使った実装です。 こちらに私が使ったプログラムコードを提示しますので、 よければお使いください。 プログラムコードはこのページの一番下にあります。 画像再生と同時に流したい曲を「raki.ogg」で プロジェクトのあるフォルダに保存してください。 ファイル形式はwavかmp3かoggが使えます。 ファイル名を変えた時は、読み込み時のファイル文字列も 変更してください。 ここまできちんと準備できていれば、 下のコードをコピペしてコンパイル、実行すれば AAで動画が再生されます。 ![]() 左がAAの画像。右が極端に拡大した画像です。 キーボードの十字キー「上キー」と「下キー」で 拡大縮小が出来るようになっています。 F12キーを押せばいつでも最初から見直すことが出来ます。 Escボタンで終了します。 |
|||||||
連続したbmpを読み込み、適切な文字に置き換え、AAを生成し、連続で表示するプログラム #include "DxLib.h"
#define MAX 1000
#define GAMEN_YOKO 1024
#define GAMEN_TATE 768
#define IMAGE1
#ifdef IMAGE0
#define BMP_YOKO 1024
#define BMP_TATE 576
#endif
#ifdef IMAGE1
#define BMP_YOKO 512
#define BMP_TATE 384
#endif
#ifdef IMAGE2
#define BMP_YOKO 400
#define BMP_TATE 300
#endif
#ifdef IMAGE3
#define BMP_YOKO 320
#define BMP_TATE 240
#endif
#define HEAD 54
#define TOTAL ((BMP_YOKO*BMP_TATE)*3+HEAD)
unsigned char data[TOTAL];
typedef struct{
unsigned char col[3];
}img_t;
#define TATEHI 3
#define YOKOHI 2
char img_AA[MAX][BMP_TATE/TATEHI+1][BMP_YOKO/YOKOHI+1];
int img_AAcol[MAX][BMP_TATE/TATEHI+1][BMP_YOKO/YOKOHI+1];
img_t img[MAX][BMP_TATE][BMP_YOKO];
int sound;
#define BARANCE 6
#define CONTRAST 1.3
//画像のコントラストを調整する。確定した15階調の幅を広げたり、
//白方向、黒方向にずらしたり出来ます。
//コントラストはCONTRAST
//輝度はBARANCE変数を変更して下さい。
void change_contrast(double *col){
*col-=BARANCE;
*col*=CONTRAST;
if(*col<-7)*col=-7;
if(*col>7)*col=7;
*col+=BARANCE;
*col-=2;
}
//読み取った色情報からAAになる文字に変換する関数です。
//input配列にいれてある文字は左に行くほど濃く、右に行くほど薄い文字です。
//色はTATEHI、YOKOHIの範囲の色を全て足して、平均をとって決定します。
//1ピクセルが1文字に対応するわけではないので、お間違いなく。
void convert_AA(int cnt){
double sum;
int i,j,x,y;
int AAcolor[3];
double col;
char input[15]={'H','D','E','J','L','I','c','(','ワ','*','+',':','-','.',' '};
for(y=0;y<BMP_TATE-TATEHI;y+=TATEHI){
for(x=0;x<BMP_YOKO-YOKOHI;x+=YOKOHI){
sum=0;
AAcolor[0]=AAcolor[1]=AAcolor[2]=0;
for(i=0;i<TATEHI;i++){
for(j=0;j<YOKOHI;j++){
sum+= img[cnt][y+i][x+j].col[0]
+img[cnt][y+i][x+j].col[1]+img[cnt][y+i][x+j].col[2];
AAcolor[0]+=img[cnt][y+i][x+j].col[0];
AAcolor[1]+=img[cnt][y+i][x+j].col[1];
AAcolor[2]+=img[cnt][y+i][x+j].col[2];
}
}
sum/=TATEHI*YOKOHI;
sum/=3.0;
col=sum/17.0;
for(i=0;i<3;i++)
AAcolor[i]/=TATEHI*YOKOHI;
img_AAcol[cnt][y/TATEHI][x/YOKOHI]=GetColor(AAcolor[2],AAcolor[1],AAcolor[0]);
change_contrast(&col);
if(col<0)col=0;
if(col>14)col=14;
img_AA[cnt][y/TATEHI][x/YOKOHI]=input[(int)col];
}
}
}
//bmpファイルを読む関数です。
//ファイル名が違う場合はダブルコーテーション内をいじってください
//配列に0を埋めている作業は、ファイル名が00000001になるようにするためです。
void bmp_read(int cnt){
int i;
char name[64];
FILE *fp;
sprintf(name,"image0/raki %7d.bmp",cnt+1);
for(i=12;name[i]!='\0';i++){
if(name[i]==' ')
name[i]='0';
}
fp = fopen( name , "rb" );
if( fp == NULL ){
printfDx( "%sが見つかりません。",name);
return;
}
fread( data, 1, TOTAL, fp );
fclose(fp);
}
//ロード中の画面を表示します。
void load(){
int x,y,c,t=0;
static int cnt=1;
for(cnt=0;cnt<MAX;cnt++){
DrawBox(0,0,GAMEN_YOKO*cnt/MAX,50,GetColor(255,255,255),TRUE);
bmp_read(cnt);
t=HEAD;
for(y=BMP_TATE-1;y>=0;y--){
for(x=0;x<BMP_YOKO;x++){
for(c=0;c<3;c++){
img[cnt][y][x].col[c]=data[t];
t++;
}
}
}
convert_AA(cnt);
}
}
char Key[256],oldKey[256];
//今押したかどうかを判定する関数です。
void check_key(){
int i;
for(i=0;i<256;i++){
if(oldKey[i]==0 && Key[i]==1)
Key[i]=2;
oldKey[i]=Key[i];
}
}
//表示文字列サイズを変更する関数です。
void change_size(int *size){
if(Key[KEY_INPUT_UP]==2){
*size+=5;
SetFontSize(*size);
}
if(Key[KEY_INPUT_DOWN]==2){
*size-=5;
SetFontSize(*size);
}
}
void play_music(){
PlaySoundMem(sound,DX_PLAYTYPE_BACK);
}
//AAを描画します。
//グラボによって、GOSAを0にした方がきれいになる場合と1の方がキレイな場合があるので
//1でキレイに見えなかったら0にしてください。
#define GOSA 1
void draw_AA(int size, int cnt){
int x,y;
DrawBox(0,0,GAMEN_YOKO,GAMEN_TATE,GetColor(255,255,255),TRUE);
for(y=0;y<BMP_TATE/TATEHI;y++){
for(x=0;x<BMP_YOKO/YOKOHI;x++){
DrawFormatString(x*(size*3/5-GOSA)-(BMP_YOKO/YOKOHI)/2*(size-5)/2,
y*(size-GOSA)-(BMP_TATE/TATEHI)/2*(size-5)/2,
img_AAcol[cnt][y][x],"%c",img_AA[cnt][y][x]);
}
}
}
void stop_music(){
StopSoundMem(sound);
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow ){
int cnt=0,size=5;
SetGraphMode( GAMEN_YOKO , GAMEN_TATE , 16 ) ;
//上のイフ文のコメントアウトを解除し、下をコメントアウトすると全画面になります。
// if(DxLib_Init() == -1 ) return -1;
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1;
load();
sound=LoadSoundMem("raki.ogg");
SetDrawScreen( DX_SCREEN_BACK );
SetFontSize(size);
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key )){
check_key();
change_size(&size);
if(cnt==0)
play_music();
draw_AA(size,cnt);
cnt++;
if(Key[KEY_INPUT_F12]==1 || cnt>=MAX){
cnt=0;
stop_music();
}
//WaitTimer(???); //<-時間がずれる場合はここで時間調整してください。
if(Key[KEY_INPUT_ESCAPE]==1)break;
ScreenFlip();
}
DxLib_End();
return 0;
}
#define MAX 1000 の値は、静止画のある枚数です。 #define GAMEN_YOKO 1024 #define GAMEN_TATE 768 は生成したい、画面サイズです。 #define IMAGE1 は読み込むbmpファイルのサイズです。 デフォルトでは512になっています。 #define TATEHI 3 #define YOKOHI 2 はたてと横の比率です。 raki.oggは再生する任意のファイルに変更してください。 |