/*
*
*雲
*/

#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MYWNDCLASS "MYWNDCLASS"
#define CAPTION  "雲"

#define WIDTH 500
#define HEIGHT 500

#define RADIAN 3.141592/180.O
#define RADIUS 200


/*ピクセル配列を元にスクリーンへ反映させる*/
void draw_pixel_screen(HDC hdc, int pixels[], int width, int height, int palette[])
{
    LPBITMAPINFO lpDIB;
    LPBYTE lpBMP;
    HBITMAP hBMP;
    HDC hdcMem;
    int i, val;

    lpDIB = (LPBITMAPINFO) GlobalAlloc(GPTR, sizeof(BITMAPINFO)); /*DIB用メモリ確保*/

    /*DIBSection用BITMAPINFO構造体設定*/
    lpDIB->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
    lpDIB->bmiHeader.biWidth=width;
    lpDIB->bmiHeader.biHeight=height;
    lpDIB->bmiHeader.biPlanes=1;
    lpDIB->bmiHeader.biBitCount=24;
    lpDIB->bmiHeader.biCompression=BI_RGB;
    lpDIB->bmiHeader.biSizeImage=0;
    lpDIB->bmiHeader.biXPelsPerMeter=0;
    lpDIB->bmiHeader.biYPelsPerMeter=0;
    lpDIB->bmiHeader.biClrUsed=0;
    lpDIB->bmiHeader.biClrImportant=0;

    hBMP =CreateDIBSection(hdc, lpDIB,DIB_RGB_COLORS, &lpBMP, NULL, 0);
    hdcMem = CreateCompatibleDC(hdc);/*メモリDCを作成*/
    SelectObject(hdcMem, hBMP); /*メモリDCにDIBSectionを作成*/
    /*ビットマップへ@ピクセル値を格納する*/
    for (i=0; i<width *height; i++){
        val =pixels[i];
        lpBMP[i*3]=GetBValue(palette[val]);
        lpBMP[i*3+1]=GetGValue(palette[val]);
        lpBMP[i*3+2]=GetRValue(palette[val]);//lpBMP[i*3+1]はi番目のピクセルの緑値を格納する
    }

    /*ビットマップからスクリーンへ一括転送*/
    BitBlt(hdc, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY);
    
    DeleteDC(hdcMem);
    DeleteObject(hBMP);
    GlobalFree(lpDIB);
}

int random(int val)
{
    double ret;

    ret= (1.0/(RAND_MAX+1.0))*(rand()+0.5);
    return ((int) (ret*val));
}

void do_graphics(HWND hWnd, HDC hdc)
{
#define pos(x,y) ((x)+(y)*WIDTH) //ピクセルの位置の定義
#define PALMAX 256
    int col;
    int pixels[WIDTH*HEIGHT];//pixels[i]は,i番目のpixelのRGB値を持つ
    int bs, i, j, x, y;
    int nx, ny;
    DWORD palette[PALMAX];

    srand(GetTickCount());

    /*パレットの設定*/
    //色は256*256*256のうち256個しか使用しない。使用する色を定めているというわけである
    for (i=0; i<PALMAX; i++){
        palette[i]=RGB(i,255,128+i/3);
    }

    bs=100;       //全画面は、ブロックサイズbs (HEIGHT/bs)*(WIDTH/bs)個のブロックに分かれている

    do{
        for(y=0; y<HEIGHT/bs; y++){
            for(x=0; x<WIDTH/bs; x++){
                /*色の決定*/
                if (bs==100){
                    col=random(PALMAX);
                }else{
                    /*上*/
                    nx=x*bs;
                    if(y-1<0)
                        ny=HEIGHT/bs-1;
                    else
                        ny=(y-1)*bs;
                    col=pixels[pos(nx,ny)];

                    /*右*/
                    if(x+1>=WIDTH/bs)
                        nx=0;
                    else
                        nx=(x+1)*bs;
                    ny=y*bs;
                    col +=pixels[pos(nx,ny)];

                    /*下*/
                    nx=x*bs;
                    if(y+1>=HEIGHT/bs)
                        ny=0;
                    else
                        ny=(y+1)*bs;
                    col+=pixels[pos(nx,ny)];

                    /*左*/
                    if(x-1<0)
                        nx=WIDTH/bs -1;
                    else
                        nx=(x-1)*bs;
                    ny=y*bs;
                    col+=pixels[pos(nx,ny)];

                    col/=4;//上下左右の色値(0<i<255)の平均をとる。

                }
                printf("col %d\n", col);
                /*ブロックの塗りつぶし*/
                for(j=y*bs; j<y*bs+bs;j++){
                    for(i=x*bs; i<x*bs+bs; i++){
                        pixels[pos(i,j)]=col;
                    }//1ブロックあたりbs*bs個のピクセルがある。ブロック内は同じ色colでぬる。
                }

            }
        }
        bs/=2;
    }while(bs>0);//ブロックサイズが0になったら終了
    
    draw_pixel_screen(hdc, pixels, WIDTH, HEIGHT, palette);
}

//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;

    switch (uMsg) {
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        do_graphics(hWnd, hdc);
        EndPaint(hWnd, &ps);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

//メイン関数
int WINAPI WinMain(
HINSTANCE hInstance, // 現在のインスタンスのハンドル
HINSTANCE hPrevInstance, //    以前のインスタンスのハンドル
LPSTR lpCmdLine,    // コマンドライン
int nCmdShow     // 表示状態
)
{
    MSG msg;
    WNDCLASSEX wc;
    HWND hWnd;

    ZeroMemory(&wc, sizeof(wc));
    wc.cbSize    =sizeof(WNDCLASSEX);   //構造体のサイズを指定 将来の互換性のために必要
    wc.lpfnWndProc  = (WNDPROC)WndProc;  //ウィンドウプロシージャの指定
    wc.hInstance   = hInstance;   //WinMain()の引数にあるインスタンスのハンドル(インスタンス(アプリケーションプログラムクラスの実体)を識別するための整数値)
    wc.hCursor   = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); //マウスカーソルのリソースの指定
    wc.hbrBackground = GetStockObject(BLACK_BRUSH);    //ウィンドウの背景色の指定
    wc.lpszClassName   =MYWNDCLASS;  //クラス名 適当な文字列を指定しておけばよい
    RegisterClassEx(&wc);  //ウィンドウクラスの登録

    hWnd= CreateWindowEx(0,
        MYWNDCLASS,
        CAPTION,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,//ウィンドウの出現位置がどうでもよいときはこうする、そうでない場合はx,y座標を記す
        WIDTH, HEIGHT,
        NULL,
        NULL,
        hInstance,
        NULL);  //CreateWindowEx()はウィンドウを作成する(出現はまだ)関数、ウィンドウのキャプションやウィンドウを出現させる位置やサイズを指定する
    ShowWindow(hWnd, nCmdShow);  //ウィンドウの描画 ShowWindow()でウィンドウの表示状態を設定、引数はウィンドウのハンドル、表示状態
    UpdateWindow(hWnd);//ウィンドウの描画 WM_PAINTメッセージをウィンドウへ送る ウィンドウプロシージャが当該メッセージを受け取って初めて、画面上にウィンドウが描画される

    while(GetMessage(&msg, NULL, 0, 0)){//メッセージループ GetMessage()はめっせーじきゅーからメッセージを取得するための関数 メッセージが取得できるまでブロックする 
                                        //終了メッセージWM_QUITを受け取ると0を返しwhileるーぷを抜ける
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

int main(void)
{
    do_graphics(NULL, NULL);

    return 0;
}

タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2009年03月17日 13:10