007-01  前へ←  ホームへ  →次へ  007-03

No.007 - 02  ピクセル反復子


ピクセル反復子(ピクセル・イテレータ)です。様々なビット深度を一括します。


・ビット深度の問題
前回、色数を決めているビット深度について記述しました。
昔のマシンは非常にスペックが低く、色数を少なくすることはマシン負荷をかけずにすむのでとても重宝されてきました。
現在でもネットでは多くのGIF画像があります。GIFは256色までしか扱えないかわりに非常にファイルサイズが小さくすむからです。
しかしフルカラーがあたりまえの現代、そういった仕様は互換性の点で大きな壁となっています。

ビット深度の異なる画像間で矩形コピーやなどを行う時、それぞれのビット毎に関数を作る必要があるのです。
1bit → 1bit、1bit → 4bit、1bit → 8bit、……… 8bit → 16bit、8bit → 24bit、……… 32bit → 32bit、
といった関数群を矩形コピーや、拡大縮小コピー、半透明コピーなどビット毎すべて別々に作る必要があります。

(矩形コピー関数内の描画部分でビット深度ごとに if else 使うとシャレにならないくらい遅い。1万回単位で繰り返す演算だから)

できっこないじゃん。てなことで商用でも 8bit 以下が扱えないアプリケーションもあるようです。

for(y=0;y<cy;y++){
        src_pix = get_pos(src_x, src_y+y);    // ここでライン座標上のポインタを得る
        dst_pix = get_pos(dst_x, dst_y+y;
        for(x=0;x<cx;x++){
               *d_pix = *s_pix;        // 1万回単位で繰り返される部分 640*480 フルカラーなら921600回
               d_pix++;
               s_pix++;
        }
}


ピクセルクラスの配列?
以前どこかのサイトで(もう閉鎖されてしまった白浜研究室というサイト(残念)だったと思うんですが)、
「ビット深度の違う画像を扱うには、templateを使ってピクセルクラスを作ってそれを配列にしたら簡単じゃない?」
ってことが書かれていました。

templateを使ってピクセル……なるほど!と筆者はいたく感銘を受け、考えました。
ピクセルクラスの配列という案は悪くない。
が、それではCreateDibSection()との互換がない。
これだと自前クラスの他にCreateDibSection()でビット深度操作する関数が必要になってしまう。
だったら!ってことで以下に続く。


解決、ピクセル反復子(ピクセル・イテレータ)
さてここでピクセル反復子という概念の登場です。
templateを使ってピクセル・ポインタ操作をします。

通常、画像のピクセル配列で、あるピクセルからその次のピクセルへアクセスするとき
演算用ピクセルポインタビット深度だけ進めます
24bit画像ならポインタを3バイト進め、8bit画像なら1バイト進めます。
1bit、4bit なら1バイト内でbit数だけ動かさなければならないこともあります。
このようにビット深度によって異なる「インクリメント」を template を使って処理します

関数内で、template<int bit> PIXEL_ITR を宣言し、
++ 演算子でビット深度だけポインタを進めるようにします。
PIXEL_ITR<1>なら1bit、
PIXEL_ITR<24>なら3バイト進めます。

これならビット深度毎に別々の関数をつくらずに済みます。


ピクセル反復子を使っても大変なトコ
templateを<int>で使う都合上、それを使う関数は呼び出し側でその「定数」を指定する必要があります。

例えば下記サンプルの矩形塗りつぶし関数のように
fill_pixput<1>()
fill_pixput<4>()
fill_pixput<8>()
fill_pixput<16>()
fill_pixput<24>()
fill_pixput<32>()
とひとつひとつ定数を指定して内部関数を呼び出してやる必要があります。
定数を指定して関数を呼ぶとtemplateなのでコンパイル時インライン的コードが展開されていきます。
(下記サンプルではさらにまたそこからアルファ値を定数指定する関数を呼んでいます)

めんどくさいようですが、一個一個全く別々に作るよりははるかに楽です。
もうちょっとカンタンなコードにならないかな、と思ったりしますが、逆にやったら複雑化して大変でした。
たぶんこの辺が妥協点です。


サンプル解説
下記サンプルソースは5つのファイルから成っています

ピクセル反復子や、パレット(色テーブル)クラスを定義するヘッダの gt_img_parts.h と、
定数を定義している resource_02.h と、
DIBクラスを定義している gt_img_02.h
リソーススクリプトの gt_img_02.rc
メインファイルの gt_img_02.cpp です。


GT_COL
RGBの超シンプルな色クラスです。既定でこういうの無かったので自作。


GT_COL_TABLE
GT_COL *m_cols の色クラスの配列をメインとするカラーテーブル・クラスです。
全体の配列数はint m_cols_len変数に入ってます。
その中で実際に使用している色の数はint m_using_cols_lenです。
make()関数で生成し、destroy()関数で破棄します。
get_col_index()関数は引数に指定された色の近似色を配列内より取得します。
近い色がなければ新しい色を追加します。

apply_palette_all() 関数でHDCにこのパレット設定(全て)を適用します。


・PIXEL_ITR
ピクセル反復子クラスです。
色を扱うPIXEL_ITR_BASEクラスと、アルファ値を扱うPIXEL_ALPHA_ITRクラスを継承してできています。
templateなので宣言時、<ビット深度, アルファ値の有無>を指定してやる必要があります。

宣言した直後、init()関数で初期化(メンバ変数に画像情報をセット)します。
実際にピクセルを指しているポインタはm_pbits メンバ変数にはいっており、
1バイトに満たない4ビット以下のピクセルはさらに m_bit_pos メンバ変数で、ビット位置を保持します。

ピクセルポインタは set_pos() でXY座標セットします。
++演算で一個ピクセルが進みます

set_bit_pos関数は4ビット以下のピクセルのビット位置をセットします。

set_col関数、
set_col_by_index関数は単純な色塗りです。

to_draw();関数は自身を引数のピクセルに描画します。直接コピーです。
to_no_blend_draw();関数は自身を引数のピクセルに半透明描画します。元の色は残りません。
to_blend_draw()関数は自身を引数のピクセルに半透明描画します。元の色との混ざった色になります。

get_red、get_green()、get_blue() は指しているピクセルの色を取得します。

・・・今回、ピクセル反復子クラスの使わない関数変数ありますが、後々の回で使います。




矩形塗りつぶしができるサンプルです。

メニューバーの色から色選択してください。


//反復子その他を定義するヘッダ
gt_img_parts.h

#ifndef _GT_IMG_PARTS_H_
#define _GT_IMG_PARTS_H_

// ====== GT_COL ==========================
class GT_COL {
    public :
    BYTE m_r, m_g, m_b;
    GT_COL(){ m_r=m_g=m_b=0; }
};
// ====== GT_COL_TABLE ==========================
class GT_COL_TABLE {
    public :
    GT_COL *m_cols;
    int m_cols_len;
    int m_using_cols_len;
    GT_COL_TABLE(){
        m_cols=NULL;
        m_cols_len=0;
        m_using_cols_len=0;
    }
    ~GT_COL_TABLE(){ destroy(); }
    make(int col_size){
        destroy();
        if (!col_size) return -1;
        m_cols = new GT_COL[col_size];
        m_cols_len = col_size;
        m_using_cols_len=0;
    }
    destroy(){
        if (m_cols) delete[] m_cols;
        m_cols = NULL;
        m_using_cols_len=0;
        m_cols_len = 0;
    };
    template <int bit> BYTE get_col_index(BYTE r, BYTE g, BYTE b);
    add_col(BYTE r, BYTE g, BYTE b);
    void set_col(BYTE index, BYTE r, BYTE g, BYTE b);


    apply_palette_all(HDC hdc); // HDCパレット設定(全て)
    set_pal_col(HDC hdc, BYTE index, BYTE r, BYTE g, BYTE b);// パレットに色設定
};
// 近似色をパレットから取得
template <int bit>
BYTE GT_COL_TABLE::get_col_index(BYTE r, BYTE g, BYTE b){
    GT_COL *pcol;
    if (!m_cols) return -1;
    int i, min_apx=255*255*3+1, apx, min_apx_index;
    min_apx_index=0;
    for(i=0;i<m_using_cols_len;i++){
        pcol=&m_cols[i];
        apx=(r-pcol->m_r)*(r-pcol->m_r)+(g-pcol->m_g)*(g-pcol->m_g)+(b-pcol->m_b)*(b-pcol->m_b);
        if (apx<min_apx){
            min_apx_index=i;
            min_apx=apx;
        }
    }
    i=1<<bit;
    if (bit && min_apx>(255*255*3/(i*i)) && m_using_cols_len<m_cols_len){
        min_apx_index = add_col(r, g, b);
    }
    return min_apx_index;
}
// パレットに追加
GT_COL_TABLE::add_col(BYTE r, BYTE g, BYTE b){
    GT_COL *pcol;
    int res_index;
    if (m_using_cols_len>=m_cols_len) return -1;
    pcol=&m_cols[m_using_cols_len];
    pcol->m_r=r;
    pcol->m_g=g;
    pcol->m_b=b;
    res_index=m_using_cols_len;
    m_using_cols_len++;
    return res_index;
}
// パレットに色設定
inline void GT_COL_TABLE::set_col(BYTE index, BYTE r, BYTE g, BYTE b){
    if (m_cols_len<=index) return ;
    GT_COL *pcol;
    pcol=&(m_cols[index]);
    pcol->m_r = r;
    pcol->m_g = g;
    pcol->m_b = b;
}

// パレットに色設定
GT_COL_TABLE::set_pal_col(HDC hdc, BYTE index, BYTE r, BYTE g, BYTE b){
    if (m_cols_len<=index) return -1;
    set_col(index, r, g, b);
    if (!hdc) return -1;

    RGBQUAD rgb;
    rgb.rgbRed      =r;
    rgb.rgbGreen    =g;
    rgb.rgbBlue     =b;
    rgb.rgbReserved =0;
    if (hdc) SetDIBColorTable(hdc, index, 1, &rgb);
    return 0;
}

// HDCパレット設定(全て)
GT_COL_TABLE::apply_palette_all(HDC hdc){
    if (!m_cols_len || !hdc) return -1;
    RGBQUAD *p_rgb, *rgb_table;
    rgb_table=new RGBQUAD[m_cols_len];
    for (int i=0;i<m_cols_len;i++){
        p_rgb=&(rgb_table[i]);
        p_rgb->rgbRed   =m_cols[i].m_r;
        p_rgb->rgbGreen =m_cols[i].m_g;
        p_rgb->rgbBlue  =m_cols[i].m_b;
        p_rgb->rgbReserved=0;
    }
    if (hdc) SetDIBColorTable(hdc, 0, m_cols_len, rgb_table);
    delete[] rgb_table;
    return 0;
}

// ====== 基底ピクセル・イテレータ ========================
template <int bit> class PIXEL_ITR_BASE {
    public :
    GT_COL_TABLE *m_p_col_table;
    int m_byte_width, m_height;
    BYTE *m_start_pbits;
    BYTE *m_pbits;
    BYTE m_bit_pos;

    init(char *start_pbits, int img_byte_width, int img_height, GT_COL_TABLE *p_col_table){
        m_start_pbits = start_pbits;
        m_byte_width  = img_byte_width;
        m_height = img_height;
        m_p_col_table = p_col_table;
        set_pos(0,0);
    };
    BYTE *get_pos_p(int ix, int iy){ return m_start_pbits+(m_height-iy-1)*m_byte_width + (ix*bit>>3); }
    set_pos(int x, int y){
        m_pbits = get_pos_p(x, y);
        set_bit_pos(x);
    }

    void set_bit_pos(int n){ set_bit_pos_static(*this, n); };
    static void set_bit_pos_static(PIXEL_ITR_BASE<1 > &pix, int n){ pix.m_bit_pos=n&7; };
    static void set_bit_pos_static(PIXEL_ITR_BASE<4 > &pix, int n){ pix.m_bit_pos=(n&1)*4; };
    static void set_bit_pos_static(PIXEL_ITR_BASE<8 > &pix, int n){};
    static void set_bit_pos_static(PIXEL_ITR_BASE<16> &pix, int n){};
    static void set_bit_pos_static(PIXEL_ITR_BASE<24> &pix, int n){};
    static void set_bit_pos_static(PIXEL_ITR_BASE<32> &pix, int n){};

    // カラーセット
    static void set_col_by_index(PIXEL_ITR_BASE<1>  &d_pix, BYTE col_index);
    static void set_col_by_index(PIXEL_ITR_BASE<4>  &d_pix, BYTE col_index);
    static void set_col_by_index(PIXEL_ITR_BASE<8>  &d_pix, BYTE col_index);
    static void set_col_by_index(PIXEL_ITR_BASE<16>  &d_pix, BYTE col_index);
    static void set_col_by_index(PIXEL_ITR_BASE<24>  &d_pix, BYTE col_index);
    static void set_col_by_index(PIXEL_ITR_BASE<32>  &d_pix, BYTE col_index);

    static void set_col_no_blend(PIXEL_ITR_BASE<1>  &d_pix, BYTE r, BYTE g, BYTE b, int rate);
    static void set_col_no_blend(PIXEL_ITR_BASE<4>  &d_pix, BYTE r, BYTE g, BYTE b, int rate);
    static void set_col_no_blend(PIXEL_ITR_BASE<8>  &d_pix, BYTE r, BYTE g, BYTE b, int rate);
    static void set_col_no_blend(PIXEL_ITR_BASE<16> &d_pix, BYTE r, BYTE g, BYTE b, int rate);
    static void set_col_no_blend(PIXEL_ITR_BASE<24> &d_pix, BYTE r, BYTE g, BYTE b, int rate);
    static void set_col_no_blend(PIXEL_ITR_BASE<32> &d_pix, BYTE r, BYTE g, BYTE b, int rate);

    static void set_col(PIXEL_ITR_BASE<1>  &d_pix, BYTE r, BYTE g, BYTE b, int rate);
    static void set_col(PIXEL_ITR_BASE<4>  &d_pix, BYTE r, BYTE g, BYTE b, int rate);
    static void set_col(PIXEL_ITR_BASE<8>  &d_pix, BYTE r, BYTE g, BYTE b, int rate);
    static void set_col(PIXEL_ITR_BASE<16> &d_pix, BYTE r, BYTE g, BYTE b, int rate);
    static void set_col(PIXEL_ITR_BASE<24> &d_pix, BYTE r, BYTE g, BYTE b, int rate);
    static void set_col(PIXEL_ITR_BASE<32> &d_pix, BYTE r, BYTE g, BYTE b, int rate);

    void to_draw(PIXEL_ITR_BASE<1> &d_pix);
    void to_draw(PIXEL_ITR_BASE<4> &d_pix);
    void to_draw(PIXEL_ITR_BASE<8> &d_pix);
    void to_draw(PIXEL_ITR_BASE<16> &d_pix);
    void to_draw(PIXEL_ITR_BASE<24> &d_pix);
    void to_draw(PIXEL_ITR_BASE<32> &d_pix);

    void virtual to_no_blend_draw(PIXEL_ITR_BASE<1> &d_pix, int rate);
    void virtual to_no_blend_draw(PIXEL_ITR_BASE<4> &d_pix, int rate);
    void virtual to_no_blend_draw(PIXEL_ITR_BASE<8> &d_pix, int rate);
    void virtual to_no_blend_draw(PIXEL_ITR_BASE<16> &d_pix, int rate);
    void virtual to_no_blend_draw(PIXEL_ITR_BASE<24> &d_pix, int rate);
    void virtual to_no_blend_draw(PIXEL_ITR_BASE<32> &d_pix, int rate);

    void virtual to_blend_draw(PIXEL_ITR_BASE<1> &d_pix, int rate);
    void virtual to_blend_draw(PIXEL_ITR_BASE<4> &d_pix, int rate);
    void virtual to_blend_draw(PIXEL_ITR_BASE<8> &d_pix, int rate);
    void virtual to_blend_draw(PIXEL_ITR_BASE<16> &d_pix, int rate);
    void virtual to_blend_draw(PIXEL_ITR_BASE<24> &d_pix, int rate);
    void virtual to_blend_draw(PIXEL_ITR_BASE<32> &d_pix, int rate);


    // 加算
    void virtual operator +=(int dx){ add(*this, dx); };
    static void add(PIXEL_ITR_BASE<1>  &pix, int dx){
        pix.m_pbits+=dx/8; pix.m_bit_pos+=dx%8; if (pix.m_bit_pos>=8) { pix.m_pbits++; pix.m_bit_pos=pix.m_bit_pos%8; } };
    static void add(PIXEL_ITR_BASE<4>  &pix, int dx){ pix.m_pbits+=dx/2; if (dx&1) increment(pix); };
    static void add(PIXEL_ITR_BASE<8>  &pix, int dx){ pix.m_pbits+=dx;  };
    static void add(PIXEL_ITR_BASE<16> &pix, int dx){ pix.m_pbits+=2*dx; };
    static void add(PIXEL_ITR_BASE<24> &pix, int dx){ pix.m_pbits+=3*dx; };
    static void add(PIXEL_ITR_BASE<32> &pix, int dx){ pix.m_pbits+=4*dx; };

    // インクリメント
    void virtual operator ++(){ increment(*this); };
    static void increment(PIXEL_ITR_BASE<1>  &pix){ if (pix.m_bit_pos<7) pix.m_bit_pos++; else { pix.m_pbits++; pix.m_bit_pos=0; } };
    static void increment(PIXEL_ITR_BASE<4>  &pix){ if (!pix.m_bit_pos)  pix.m_bit_pos=4; else { pix.m_pbits++; pix.m_bit_pos=0; } };
    static void increment(PIXEL_ITR_BASE<8>  &pix){ pix.m_pbits++;  };
    static void increment(PIXEL_ITR_BASE<16> &pix){ pix.m_pbits+=2; };
    static void increment(PIXEL_ITR_BASE<24> &pix){ pix.m_pbits+=3; };
    static void increment(PIXEL_ITR_BASE<32> &pix){ pix.m_pbits+=4; };

    // デクリメント
    void virtual operator --(){ decrement(*this); };
    static void decrement(PIXEL_ITR_BASE<1>  &pix){ if (pix.m_bit_pos>0) pix.m_bit_pos--; else { pix.m_pbits--; pix.m_bit_pos=7; } };
    static void decrement(PIXEL_ITR_BASE<4>  &pix){ if (pix.m_bit_pos)   pix.m_bit_pos=0; else { pix.m_pbits--; pix.m_bit_pos=4; } };
    static void decrement(PIXEL_ITR_BASE<8>  &pix){ pix.m_pbits--;  };
    static void decrement(PIXEL_ITR_BASE<16> &pix){ pix.m_pbits-=2; };
    static void decrement(PIXEL_ITR_BASE<24> &pix){ pix.m_pbits-=3; };
    static void decrement(PIXEL_ITR_BASE<32> &pix){ pix.m_pbits-=4; };

    // 色取得(パレット値)
    static get_index(PIXEL_ITR_BASE<1> &pix){ return (0x01 & ((*pix.m_pbits)>>(7-pix.m_bit_pos))); }
    static get_index(PIXEL_ITR_BASE<4> &pix){ return (0x0f & ((*pix.m_pbits)>>(4-pix.m_bit_pos))); }
    static get_index(PIXEL_ITR_BASE<8> &pix){ return *pix.m_pbits; }
    static get_index(PIXEL_ITR_BASE<16> &pix){ return 0; }
    static get_index(PIXEL_ITR_BASE<24> &pix){ return 0; }
    static get_index(PIXEL_ITR_BASE<32> &pix){ return 0; }

    // 色取得
    static get_red  (PIXEL_ITR_BASE<1> &pix){ return pix.m_p_col_table->m_cols[0x01 & ((*pix.m_pbits)>>(7-pix.m_bit_pos))].m_r; };
    static get_green(PIXEL_ITR_BASE<1> &pix){ return pix.m_p_col_table->m_cols[0x01 & ((*pix.m_pbits)>>(7-pix.m_bit_pos))].m_g; };
    static get_blue (PIXEL_ITR_BASE<1> &pix){ return pix.m_p_col_table->m_cols[0x01 & ((*pix.m_pbits)>>(7-pix.m_bit_pos))].m_b; };

    static get_red  (PIXEL_ITR_BASE<4> &pix){ return pix.m_p_col_table->m_cols[0x0f & ((*pix.m_pbits)>>(4-pix.m_bit_pos))].m_r; };
    static get_green(PIXEL_ITR_BASE<4> &pix){ return pix.m_p_col_table->m_cols[0x0f & ((*pix.m_pbits)>>(4-pix.m_bit_pos))].m_g; };
    static get_blue (PIXEL_ITR_BASE<4> &pix){ return pix.m_p_col_table->m_cols[0x0f & ((*pix.m_pbits)>>(4-pix.m_bit_pos))].m_b; };

    static get_red  (PIXEL_ITR_BASE<8> &pix){ return pix.m_p_col_table->m_cols[*pix.m_pbits].m_r; };
    static get_green(PIXEL_ITR_BASE<8> &pix){ return pix.m_p_col_table->m_cols[*pix.m_pbits].m_g; };
    static get_blue (PIXEL_ITR_BASE<8> &pix){ return pix.m_p_col_table->m_cols[*pix.m_pbits].m_b; };

    static get_red  (PIXEL_ITR_BASE<16> &pix){ return (((*(WORD*)pix.m_pbits) & 0x7c00)>>10)<<3; };
    static get_green(PIXEL_ITR_BASE<16> &pix){ return (((*(WORD*)pix.m_pbits) & 0x03e0)>>5) <<3; };
    static get_blue (PIXEL_ITR_BASE<16> &pix){ return  ((*(WORD*)pix.m_pbits) & 0x001f)     <<3; };

    static get_red  (PIXEL_ITR_BASE<24> &pix){ return pix.m_pbits[2]; };
    static get_green(PIXEL_ITR_BASE<24> &pix){ return pix.m_pbits[1]; };
    static get_blue (PIXEL_ITR_BASE<24> &pix){ return pix.m_pbits[0]; };

    static get_red  (PIXEL_ITR_BASE<32> &pix){ return pix.m_pbits[2]; };
    static get_green(PIXEL_ITR_BASE<32> &pix){ return pix.m_pbits[1]; };
    static get_blue (PIXEL_ITR_BASE<32> &pix){ return pix.m_pbits[0]; };

};
//==========PIXEL_ITR_BASE 色セット(パレット)========================================
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col_by_index(PIXEL_ITR_BASE<1> &d_pix, BYTE col_index){
    *d_pix.m_pbits = ((1 & col_index) << (7-d_pix.m_bit_pos))
                    | (*d_pix.m_pbits & ~(BYTE)(1 << (7-d_pix.m_bit_pos))) ;
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col_by_index(PIXEL_ITR_BASE<4> &d_pix, BYTE col_index){
    *d_pix.m_pbits = (col_index << (4-d_pix.m_bit_pos)) | (*d_pix.m_pbits & (0x0f << d_pix.m_bit_pos));
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col_by_index(PIXEL_ITR_BASE<8> &d_pix, BYTE col_index){
    *d_pix.m_pbits = col_index;
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col_by_index(PIXEL_ITR_BASE<16> &d_pix, BYTE col_index){
    GT_COL col;
    if (d_pix.m_p_col_table && d_pix.m_p_col_table->m_cols_len>col_index){
        col = d_pix.m_p_col_table->m_cols[col_index];
        set_col(d_pix, col.m_r, col.m_g, col.m_b, 255);
    }
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col_by_index(PIXEL_ITR_BASE<24> &d_pix, BYTE col_index){
    GT_COL col;
    if (d_pix.m_p_col_table && d_pix.m_p_col_table->m_cols_len>col_index){
        col = d_pix.m_p_col_table->m_cols[col_index];
        set_col(d_pix, col.m_r, col.m_g, col.m_b, 255);
    }
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col_by_index(PIXEL_ITR_BASE<32> &d_pix, BYTE col_index){
    GT_COL col;
    if (d_pix.m_p_col_table && d_pix.m_p_col_table->m_cols_len>col_index){
        col = d_pix.m_p_col_table->m_cols[col_index];
        set_col(d_pix, col.m_r, col.m_g, col.m_b, 255);
    }
}
//==========PIXEL_ITR_BASE 色セット(ブレンド)============================================
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col(PIXEL_ITR_BASE<1> &d_pix, BYTE r, BYTE g, BYTE b, int rate){
    BYTE col_index = d_pix.m_p_col_table->get_col_index<1>(r, g, b);
    *d_pix.m_pbits = ((1 & col_index) << (7-d_pix.m_bit_pos))
                    | (*d_pix.m_pbits & ~(BYTE)(1 << (7-d_pix.m_bit_pos))) ;
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col(PIXEL_ITR_BASE<4> &d_pix, BYTE r, BYTE g, BYTE b, int rate){
    r = (BYTE)((get_red  (d_pix) * (255-rate)/255)  + (r * rate/255));  // red
    g = (BYTE)((get_green(d_pix) * (255-rate)/255)  + (g * rate/255));  // green
    b = (BYTE)((get_blue (d_pix) * (255-rate)/255)  + (b * rate/255));  // blue

    BYTE col_index = d_pix.m_p_col_table->get_col_index<4>(r, g, b);
    *d_pix.m_pbits = (col_index << (4-d_pix.m_bit_pos)) | (*d_pix.m_pbits & (0x0f << d_pix.m_bit_pos));
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col(PIXEL_ITR_BASE<8> &d_pix, BYTE r, BYTE g, BYTE b, int rate){
    r = (BYTE)((get_red  (d_pix) * (255-rate)/255)  + (r * rate/255));  // red
    g = (BYTE)((get_green(d_pix) * (255-rate)/255)  + (g * rate/255));  // green
    b = (BYTE)((get_blue (d_pix) * (255-rate)/255)  + (b * rate/255));  // blue

    BYTE col_index = d_pix.m_p_col_table->get_col_index<8>(r, g, b);
    *d_pix.m_pbits = col_index;
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col(PIXEL_ITR_BASE<16> &d_pix, BYTE r, BYTE g, BYTE b, int rate){
    WORD *pw=(WORD*)d_pix.m_pbits;  // blue 8bit -> 5bit
    *pw=(WORD)(
            (((BYTE)(((get_red  (d_pix) * (255-rate)/255)  + (r* rate/255)))>>3)<<10)
        |   (((BYTE)(((get_green(d_pix) * (255-rate)/255)  + (g* rate/255)))>>3)<<5)
        |   ( (BYTE)(((get_blue (d_pix) * (255-rate)/255)  + (b* rate/255)))>>3)
    );
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col(PIXEL_ITR_BASE<24> &d_pix, BYTE r, BYTE g, BYTE b, int rate){
        d_pix.m_pbits[2]=(BYTE)((get_red  (d_pix) * (255-rate)/255)  + (r * rate/255)); // red
        d_pix.m_pbits[1]=(BYTE)((get_green(d_pix) * (255-rate)/255)  + (g * rate/255)); // green
        d_pix.m_pbits[0]=(BYTE)((get_blue (d_pix) * (255-rate)/255)  + (b * rate/255)); // blue
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col(PIXEL_ITR_BASE<32> &d_pix, BYTE r, BYTE g, BYTE b, int rate){
        d_pix.m_pbits[2]=(BYTE)((get_red  (d_pix) * (255-rate)/255)  + (r * rate/255)); // red
        d_pix.m_pbits[1]=(BYTE)((get_green(d_pix) * (255-rate)/255)  + (g * rate/255)); // green
        d_pix.m_pbits[0]=(BYTE)((get_blue (d_pix) * (255-rate)/255)  + (b * rate/255)); // blue
}
//==========PIXEL_ITR_BASE 色セット(ブレンド無し)============================================
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col_no_blend(PIXEL_ITR_BASE<1> &d_pix, BYTE r, BYTE g, BYTE b, int rate){
    BYTE col_index = d_pix.m_p_col_table->get_col_index<1>(r, g, b);
    *d_pix.m_pbits = ((1 & col_index) << (7-d_pix.m_bit_pos))
                    | (*d_pix.m_pbits & ~(BYTE)(1 << (7-d_pix.m_bit_pos))) ;
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col_no_blend(PIXEL_ITR_BASE<4> &d_pix, BYTE r, BYTE g, BYTE b, int rate){
    r = (BYTE)(r * rate/255);   // red
    g = (BYTE)(g * rate/255);   // green
    b = (BYTE)(b * rate/255);   // blue

    BYTE col_index = d_pix.m_p_col_table->get_col_index<4>(r, g, b);
    *d_pix.m_pbits = (col_index << (4-d_pix.m_bit_pos)) | (*d_pix.m_pbits & (0x0f << d_pix.m_bit_pos));
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col_no_blend(PIXEL_ITR_BASE<8> &d_pix, BYTE r, BYTE g, BYTE b, int rate){
    r = (BYTE)(r * rate/255);   // red
    g = (BYTE)(g * rate/255);   // green
    b = (BYTE)(b * rate/255);   // blue

    *d_pix.m_pbits = d_pix.m_p_col_table->get_col_index<8>(r, g, b);
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col_no_blend(PIXEL_ITR_BASE<16> &d_pix, BYTE r, BYTE g, BYTE b, int rate){
    WORD *pw=(WORD*)d_pix.m_pbits;  // blue 8bit -> 5bit
    *pw=(WORD)(
            (((BYTE)(r* rate/255)>>3)<<10)
        |   (((BYTE)(g* rate/255)>>3)<<5)
        |   ( (BYTE)(b* rate/255)>>3)
    );
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col_no_blend(PIXEL_ITR_BASE<24> &d_pix, BYTE r, BYTE g, BYTE b, int rate){
        d_pix.m_pbits[2]=(BYTE)(r * rate/255);  // red
        d_pix.m_pbits[1]=(BYTE)(g * rate/255);  // green
        d_pix.m_pbits[0]=(BYTE)(b * rate/255);  // blue
}
template <int bit> inline void PIXEL_ITR_BASE<bit>::set_col_no_blend(PIXEL_ITR_BASE<32> &d_pix, BYTE r, BYTE g, BYTE b, int rate){
        d_pix.m_pbits[2]=(BYTE)(r * rate/255);  // red
        d_pix.m_pbits[1]=(BYTE)(g * rate/255);  // green
        d_pix.m_pbits[0]=(BYTE)(b * rate/255);  // blue
}
//==========PIXEL_ITR_BASE 矩形コピー(半透明)ブレンドなし=========================================
// 1 bit <- n bit (半透明)ブレンドなし
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_no_blend_draw(PIXEL_ITR_BASE<1> &d_pix, int rate){
    BYTE r, g, b;
    r = (BYTE)(get_red  (*this) * rate/255);    // red
    g = (BYTE)(get_green(*this) * rate/255);    // green
    b = (BYTE)(get_blue (*this) * rate/255);    // blue

    *d_pix.m_pbits = d_pix.m_p_col_table->get_col_index<1>(r, g, b);
}
// 4 bit <- n bit (半透明)ブレンドなし
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_no_blend_draw(PIXEL_ITR_BASE<4> &d_pix, int rate){
    BYTE r, g, b;
    r = (BYTE)(get_red  (*this) * rate/255);    // red
    g = (BYTE)(get_green(*this) * rate/255);    // green
    b = (BYTE)(get_blue (*this) * rate/255);    // blue

    *d_pix.m_pbits = d_pix.m_p_col_table->get_col_index<4>(r, g, b);
}
// 8 bit <- n bit (半透明)ブレンドなし
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_no_blend_draw(PIXEL_ITR_BASE<8> &d_pix, int rate){
    BYTE r, g, b;
    r = (BYTE)(get_red  (*this) * rate/255);    // red
    g = (BYTE)(get_green(*this) * rate/255);    // green
    b = (BYTE)(get_blue (*this) * rate/255);    // blue

    *d_pix.m_pbits = d_pix.m_p_col_table->get_col_index<8>(r, g, b);
}
// n bit <- 16bit (半透明)ブレンドなし
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_no_blend_draw(PIXEL_ITR_BASE<16> &d_pix, int rate){
        WORD *pw=(WORD*)d_pix.m_pbits;  // blue 8bit -> 5bit
        *pw = ((((get_red(*this)  >>3)* rate/255)<<10) )
            | ((((get_green(*this)>>3)* rate/255)<<5) )
            | (  (get_blue(*this) >>3)* rate/255);
}
// n bit <- 24bit (半透明)ブレンドなし
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_no_blend_draw(PIXEL_ITR_BASE<24> &d_pix, int rate){
        d_pix.m_pbits[0]=get_blue(*this) * rate/255 ;
        d_pix.m_pbits[1]=get_green(*this)* rate/255 ;
        d_pix.m_pbits[2]=get_red(*this)  * rate/255 ;
}
// n bit <- 32bit (半透明)ブレンドなし
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_no_blend_draw(PIXEL_ITR_BASE<32> &d_pix, int rate){
        d_pix.m_pbits[0]=get_blue(*this)  * rate/255 ;
        d_pix.m_pbits[1]=get_green(*this) * rate/255 ;
        d_pix.m_pbits[2]=get_red(*this)   * rate/255 ;
}

//==========PIXEL_ITR_BASE 矩形コピー(半透明)ブレンドあり=========================================
// 1 bit <- n bit (半透明)ブレンドあり
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_blend_draw(PIXEL_ITR_BASE<1> &d_pix, int rate){
    BYTE r, g, b;
    r=get_blue (*this)* rate/255 + get_red  (d_pix)* (255-rate)/255;
    g=get_green(*this)* rate/255 + get_green(d_pix)* (255-rate)/255;
    b=get_red  (*this)* rate/255 + get_blue (d_pix)* (255-rate)/255;

    *d_pix.m_pbits = d_pix.m_p_col_table->get_col_index<1>(r, g, b);
}
// 4 bit <- n bit (半透明)ブレンドあり
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_blend_draw(PIXEL_ITR_BASE<4> &d_pix, int rate){
    BYTE r, g, b;
    r=get_blue (*this)* rate/255 + get_red  (d_pix)* (255-rate)/255;
    g=get_green(*this)* rate/255 + get_green(d_pix)* (255-rate)/255;
    b=get_red  (*this)* rate/255 + get_blue (d_pix)* (255-rate)/255;

    *d_pix.m_pbits = d_pix.m_p_col_table->get_col_index<4>(r, g, b);
}
// 8 bit <- n bit (半透明)ブレンドあり
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_blend_draw(PIXEL_ITR_BASE<8> &d_pix, int rate){
    BYTE r, g, b;
    r=get_blue (*this)* rate/255 + get_red  (d_pix)* (255-rate)/255;
    g=get_green(*this)* rate/255 + get_green(d_pix)* (255-rate)/255;
    b=get_red  (*this)* rate/255 + get_blue (d_pix)* (255-rate)/255;

    *d_pix.m_pbits = d_pix.m_p_col_table->get_col_index<8>(r, g, b);
}
// 16 bit <- n bit (半透明)ブレンドあり
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_blend_draw(PIXEL_ITR_BASE<16> &d_pix, int rate){
        WORD *pw=(WORD*)d_pix.m_pbits;  // blue 8bit -> 5bit
        *pw =( ((((get_red  (*this)>>3)* rate/255)<<10))+ (((get_red  (d_pix)>>3)* (255-rate)/255)<<10) )
            |( ((((get_green(*this)>>3)* rate/255)<<5) )+ (((get_green(d_pix)>>3)* (255-rate)/255)<<5)  )
            | (   (get_blue (*this)>>3)* rate/255)      +  ((get_blue (d_pix)>>3)* (255-rate)/255);
}
// 24 bit <- n bit (半透明)ブレンドあり
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_blend_draw(PIXEL_ITR_BASE<24> &d_pix, int rate){
        d_pix.m_pbits[0]=get_blue(*this) * rate/255 + d_pix.m_pbits[0]* (255-rate)/255;
        d_pix.m_pbits[1]=get_green(*this)* rate/255 + d_pix.m_pbits[1]* (255-rate)/255;
        d_pix.m_pbits[2]=get_red(*this)  * rate/255 + d_pix.m_pbits[2]* (255-rate)/255;
}
// 32 bit <- n bit (半透明)ブレンドあり
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_blend_draw(PIXEL_ITR_BASE<32> &d_pix, int rate){
        d_pix.m_pbits[0]=get_blue(*this) * rate/255 + d_pix.m_pbits[0]* (255-rate)/255;
        d_pix.m_pbits[1]=get_green(*this)* rate/255 + d_pix.m_pbits[1]* (255-rate)/255;
        d_pix.m_pbits[2]=get_red(*this)  * rate/255 + d_pix.m_pbits[2]* (255-rate)/255;
}
//==========PIXEL_ITR_BASE 矩形コピー(透明無し)=========================================
// 1 bit <- n bit 
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_draw(PIXEL_ITR_BASE<1> &d_pix){
    BYTE col_index = d_pix.m_p_col_table->get_col_index<1>(get_red(*this), get_green(*this), get_blue(*this));
    *d_pix.m_pbits = ((1 & col_index) << (7-d_pix.m_bit_pos))
                    | (*d_pix.m_pbits & ~(BYTE)(1 << (7-d_pix.m_bit_pos))) ;
}
// 4 bit <- n bit 
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_draw(PIXEL_ITR_BASE<4> &d_pix){
    BYTE col_index = d_pix.m_p_col_table->get_col_index<4>(get_red(*this), get_green(*this), get_blue(*this));
    *d_pix.m_pbits = (col_index << (4-d_pix.m_bit_pos)) | (*d_pix.m_pbits & (0x0f << d_pix.m_bit_pos));
}
// 8 bit <- n bit 
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_draw(PIXEL_ITR_BASE<8> &d_pix){
    *d_pix.m_pbits = d_pix.m_p_col_table->get_col_index<8>(get_red(*this), get_green(*this), get_blue(*this));
}
// 16 bit <- n bit 
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_draw(PIXEL_ITR_BASE<16> &d_pix){
        WORD *pw=(WORD*)(d_pix.m_pbits);    // blue 8bit -> 5bit
        *pw = (((get_red(*this) >>3)<<10) )
            | (((get_green(*this)>>3)<<5)  )
            |   (get_blue(*this)  >>3);
}
// 24 bit <- n bit 
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_draw(PIXEL_ITR_BASE<24> &d_pix){
        d_pix.m_pbits[0]=get_blue(*this);
        d_pix.m_pbits[1]=get_green(*this);
        d_pix.m_pbits[2]=get_red(*this);
}
// 32 bit <- n bit 
template <int bit> inline void PIXEL_ITR_BASE<bit>::to_draw(PIXEL_ITR_BASE<32> &d_pix){
        d_pix.m_pbits[0]=get_blue(*this);
        d_pix.m_pbits[1]=get_green(*this);
        d_pix.m_pbits[2]=get_red(*this);
        d_pix.m_pbits[3]=0;
}

// ====== ピクセル・イテレータ(アルファ値) ========================
template <int alpha> 
class PIXEL_ALPHA_ITR {
    public:
    int m_width, m_height;
    BYTE *m_palpha, *m_start_palpha;
    set_pos(int x, int y){
    }
    init(char *start_palpha, int img_width, int img_height){
        m_start_palpha = start_palpha;
        m_width = img_width;
        m_height = img_height;
    }
    static increment(PIXEL_ALPHA_ITR<0> &alpha_itr){};
    static increment(PIXEL_ALPHA_ITR<1> &alpha_itr){ alpha_itr.m_palpha++; };
    static decrement(PIXEL_ALPHA_ITR<0> &alpha_itr){};
    static decrement(PIXEL_ALPHA_ITR<1> &alpha_itr){ alpha_itr.m_palpha--; };
    static rate_calc(PIXEL_ALPHA_ITR<0> &alpha_itr, int &rate){};
    static rate_calc(PIXEL_ALPHA_ITR<1> &alpha_itr, int &rate){ rate=alpha_itr.m_palpha[0]*rate/255; };
};

// ====== ピクセル・イテレータ ========================
template <int bit, int alpha> 
class PIXEL_ITR : public PIXEL_ITR_BASE<bit>, public PIXEL_ALPHA_ITR<alpha> {
    public:
    set_pos(int x, int y){
        PIXEL_ITR_BASE<bit>::set_pos(x, y);
        PIXEL_ALPHA_ITR<alpha>::set_pos(x, y);
    };
    init(char *start_pbits, char *start_palpha, int img_byte_width, int img_width, int img_height, GT_COL_TABLE *p_col_table){
        PIXEL_ITR_BASE<bit>::init(start_pbits, img_byte_width, img_height, p_col_table);
        PIXEL_ALPHA_ITR<alpha>::init(start_palpha, img_width, img_height);
    };
    void operator ++(){
        PIXEL_ITR_BASE<bit>::increment(*this);
        PIXEL_ALPHA_ITR<alpha>::increment(*this);
    };
    void operator +=(int dx){ add(*this, dx); };

    BYTE get_index(){ PIXEL_ITR_BASE<bit>::get_index(*this); }
    void set_col(BYTE col_index){ PIXEL_ITR_BASE<bit>::set_col_by_index(*this, col_index); };
    void set_col(BYTE r, BYTE g, BYTE b, int rate){ PIXEL_ITR_BASE<bit>::set_col(*this, r, g, b, rate); };
    void set_col_no_blend(BYTE r, BYTE g, BYTE b, int rate){ PIXEL_ITR_BASE<bit>::set_col_no_blend(*this, r, g, b, rate); };
};

#endif // _GT_IMG_PARTS_H_



resource_02.h

#define IDM_MAKE_DIB_0      1000
#define IDM_MAKE_DIB_1      1001
#define IDM_MAKE_DIB_4      1004
#define IDM_MAKE_DIB_8      1008
#define IDM_MAKE_DIB_16     1016
#define IDM_MAKE_DIB_24     1024
#define IDM_MAKE_DIB_32     1032

#define IDM_OPEN            2000
#define IDM_LOAD_DIB        2001
#define IDM_SAVE_DIB        2002

#define IDM_COL             3000



gt_img_02.rc

#include "resource_02.h"

//リソーススクリプト
GT_DIB_MENU MENU {
    POPUP "DIB 作成" {
        MENUITEM "1 bit" , IDM_MAKE_DIB_1
        MENUITEM "4 bit" , IDM_MAKE_DIB_4
        MENUITEM "8 bit" , IDM_MAKE_DIB_8
        MENUITEM "16 bit", IDM_MAKE_DIB_16
        MENUITEM "24 bit", IDM_MAKE_DIB_24
        MENUITEM "32 bit", IDM_MAKE_DIB_32
    }
    MENUITEM "色",      IDM_COL
}


gt_img_02.h
// 矩形塗りつぶし

#include <stdio.h>
#include <windows.h>
#include "resource_02.h"
#include "gt_img_parts.h"

// ======== GT_DIB ==================================
class GT_DIB {
    public :
    GT_COL_TABLE m_col_table;
    unsigned long *m_col_mask;
    char *m_alpha;
    HDC m_hdc;
    HBITMAP m_hbmp;

    int m_width, m_height, m_byte_width, m_bit_count;
    BYTE *m_pbits;

    GT_DIB();
    ~GT_DIB();

    // 作成と破棄
    virtual create(int cx, int cy, int a_bit_count, int a_color_size=0);
    virtual destroy();

    // ピクセル描画
    set_pixel(int x, int y, DWORD col);
    DWORD get_pixel(int x, int y);

    // 矩形塗りつぶし
    fill(int x, int y, int cx, int cy, BYTE r, BYTE g, BYTE b, int rate);
    template <int d_bit> void fill_pixput(int x, int y, int cx, int cy, BYTE r, BYTE g, BYTE b, int rate);

    // アルファ値
    is_alpha(){ return (m_alpha!=NULL); }

    // カラー
    set_pal_col(BYTE index, BYTE r, BYTE g, BYTE b);
    apply_palette_all();

    // DC 適用
    apply_dc(HDC hdc);
    apply_dc(HWND hwnd);
};


//==========矩形操作==========
// 矩形塗りつぶしのインライン・テンプレート
template <int d_bit> inline void 
GT_DIB::fill_pixput(int x, int y, int cx, int cy, BYTE r, BYTE g, BYTE b, int rate){
    PIXEL_ITR<d_bit,0> d_pix;
    d_pix.init(m_pbits, m_alpha, m_byte_width, m_width, m_height, &m_col_table);
    if (rate<0) rate=0;
    if (rate>=255) rate=255;
    int ix, iy;
    BYTE col_index;
    if (d_bit<=8){  // (パレット版) 
        col_index=m_col_table.get_col_index<d_bit>(r*rate/255, g*rate/255, b*rate/255);
        for(iy=0;iy<cy;iy++){
            d_pix.set_pos(x, y+iy);
            for(ix=0;ix<cx;ix++){ d_pix.set_col(col_index); d_pix++; }
        }
    }
    else {  // (RGB版) 
        for(iy=0;iy<cy;iy++){
            d_pix.set_pos(x, y+iy);
            for(ix=0;ix<cx;ix++){ d_pix.set_col(r, g, b, rate); d_pix++; }
        }
    }
};
// 矩形塗りつぶし
GT_DIB::fill(int x, int y, int cx, int cy, BYTE r, BYTE g, BYTE b, int rate){
    if (!m_pbits) return -1;

    if (cx<0) { x+=cx; cx=-cx; };
    if (cy<0) { y+=cy; cy=-cy; };

    // マイナス座標の補正
    if (x<0) { cx+=x; x=0; };
    if (y<0) { cy+=y; y=0; };
    // 限界コピー幅の補正
    if ((x+cx)>=m_width) { cx=m_width -x;};
    if ((y+cy)>=m_height){ cy=m_height-y;};

    // コピー
    switch(m_bit_count){
    case 1 : fill_pixput<1> (x, y, cx, cy, r, g, b, rate);   break;
    case 4 : fill_pixput<4> (x, y, cx, cy, r, g, b, rate);   break;
    case 8 : fill_pixput<8> (x, y, cx, cy, r, g, b, rate);   break;
    case 16: fill_pixput<16>(x, y, cx, cy, r, g, b, rate);   break;
    case 24: fill_pixput<24>(x, y, cx, cy, r, g, b, rate);   break;
    case 32: fill_pixput<32>(x, y, cx, cy, r, g, b, rate);   break;
    }
    return 0;
}


// コンストラクタ
GT_DIB::GT_DIB(){
    m_col_mask =NULL;
    m_alpha =NULL;
    m_width = m_height = m_byte_width = m_bit_count =0;
    m_pbits =NULL;

    m_hdc = NULL;
    m_hbmp = NULL;
}
// デストラクタ
GT_DIB::~GT_DIB(){
    destroy();
}
// GT_DIB 破棄
GT_DIB::destroy(){
    if (m_hdc)      { DeleteDC(m_hdc);  m_hdc=NULL; }
    if (m_hbmp)     { DeleteObject(m_hbmp); m_hbmp=NULL; }
    m_width=0;
    m_height=0;
    m_byte_width=0;
    m_bit_count=0;
    m_pbits = NULL;
    if (m_col_mask) delete[] m_col_mask;
    m_col_mask = NULL;
    m_col_table.destroy();

    return 0;
};
// 1点ピクセル取得
DWORD GT_DIB::get_pixel(int x, int y){
    if (!m_pbits) return 0;
    if (x<0 || x>=m_width || y<0 || y>=m_height) return 0;
    BYTE *ppix;
    ppix=m_pbits+(m_height-y-1)*m_byte_width + (x*m_bit_count>>3);

    switch(m_bit_count){
    case 1: return 0x01 & (*ppix >> (7-(x&7)));
    case 4: return 0x0f & (*ppix >> ((x&1)?0:4));
    case 8: return *ppix ;
    case 16: return *(WORD*)ppix;
    case 24: return 0x00FFffFF & *(DWORD*)ppix;
    case 32: return *(DWORD*)ppix ;
    }
    return 0;
}
// 1点ピクセル書きこみ
GT_DIB::set_pixel(int x, int y, DWORD col){
    if (!m_pbits) return 0;
    if (x<0 || x>=m_width || y<0 || y>=m_height) return 0;
    BYTE *ppix;
    ppix=m_pbits+(m_height-y-1)*m_byte_width + (x*m_bit_count>>3);

    switch(m_bit_count){
    case 1: *ppix &= ~(1         <<(7-(x&7)));
            *ppix |= ((bool)col) <<(7-(x&7));
            break;
    case 4: *ppix &= 0x0f << ((x&1)?4:0);
            *ppix |= (0x0f & col)  << ((x&1)?0:4);
            break;
    case 8: *ppix = (BYTE)col;                          break;
    case 16: *(WORD*)ppix = (WORD)col;                  break;
    case 24: *(RGBTRIPLE*)ppix = *(RGBTRIPLE*)&col;     break;
    case 32: *(DWORD*)ppix = *(DWORD*)&col;             break;
    }
    return 0;
}

// 作成
GT_DIB::create(int cx, int cy, int a_bit_count, int a_color_size){
    BITMAPINFO *bmp_info;
    int i, palette_entry, info_size;
    destroy();  // 作成済みメモリを破棄する

    if (cx<=0 || cy<=0) return -1;
    if (a_bit_count!=1 && a_bit_count!=4 && a_bit_count!=8
        && a_bit_count!=16 && a_bit_count!=24 && a_bit_count!=32) return -1;

    palette_entry=1;
    if      (a_color_size!=0) palette_entry=a_color_size;
    else if (a_bit_count<=8)  palette_entry=1<<a_bit_count; // 8bit以下でパレット色数指定無しなら

    info_size=sizeof(BITMAPINFOHEADER) + (palette_entry-1)*sizeof(RGBQUAD)+1;
    bmp_info = (BITMAPINFO*)malloc(info_size);
    if (!bmp_info) return -1;
    ZeroMemory(bmp_info, info_size);

    // 適当な基本色
    RGBTRIPLE rgb[8]={
        {0,0,0},{255, 255, 255}, {0,0,255}, {255,0,0}, {0,255,0}, {255, 255,0}, {255,0,255},{0,255,255}
    };

    m_col_table.make(palette_entry);
    for(i=0;i<min(palette_entry, 8);i++){
        bmp_info->bmiColors[i].rgbBlue  = rgb[i].rgbtBlue;
        bmp_info->bmiColors[i].rgbGreen = rgb[i].rgbtGreen;
        bmp_info->bmiColors[i].rgbRed   = rgb[i].rgbtRed;
        bmp_info->bmiColors[i].rgbReserved = 0;
        m_col_table.add_col(rgb[i].rgbtRed, rgb[i].rgbtGreen, rgb[i].rgbtBlue);
    }

    /* BITMAPINFO構造体設定 */
    bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
    bmp_info->bmiHeader.biWidth=cx;
    bmp_info->bmiHeader.biHeight=cy;
    bmp_info->bmiHeader.biPlanes=1;
    bmp_info->bmiHeader.biBitCount=a_bit_count;
    bmp_info->bmiHeader.biCompression=BI_RGB;
    bmp_info->bmiHeader.biSizeImage=0;
    bmp_info->bmiHeader.biXPelsPerMeter=0;
    bmp_info->bmiHeader.biYPelsPerMeter=0;
    bmp_info->bmiHeader.biClrUsed=palette_entry;
    bmp_info->bmiHeader.biClrImportant=0;

    m_hbmp = CreateDIBSection(NULL, bmp_info, DIB_RGB_COLORS, (VOID**)&m_pbits, NULL, 0);
    if (!m_hbmp) {
        free(bmp_info);
        return -1;
    }
    m_width= cx;
    m_height=cy;
    m_bit_count=a_bit_count;

    /* バッファの1ラインの長さを計算 */
    m_byte_width=4*((m_width*m_bit_count+31)/32);
    ZeroMemory(m_pbits, m_byte_width*m_height);

    free(bmp_info);
    return 0;
}

// HDCパレット設定(全て)
GT_DIB::apply_palette_all(){
    return m_col_table.apply_palette_all(m_hdc);
}
// パレットに色設定
GT_DIB::set_pal_col(BYTE index, BYTE r, BYTE g, BYTE b){
    return m_col_table.set_pal_col(m_hdc, index, r, g, b);
}

// DC有効化
GT_DIB::apply_dc(HDC hdc){
    if (m_hdc) { DeleteDC(m_hdc);   m_hdc=NULL; }
    m_hdc = CreateCompatibleDC(hdc);
    SelectObject(m_hdc, m_hbmp);
    return 0;
}
// DC有効化(HWND hwnd) 
GT_DIB::apply_dc(HWND hwnd){
    if (m_hdc)      { DeleteDC(m_hdc);  m_hdc=NULL; }
    HDC hwnd_hdc = GetDC(hwnd);
    m_hdc = CreateCompatibleDC(hwnd_hdc);
    SelectObject(m_hdc, m_hbmp);
    ReleaseDC(hwnd, hwnd_hdc);
    return 0;
}




gt_img_02.cpp

#include "resource_02.h"
#include "gt_img_02.h"

GT_DIB gt_dib_1;
CHOOSECOLOR cc = {0};
COLORREF color = 0, col_costom[16];
int col_index = 0;
BYTE r=0, g=255, b=255;

static char filename[MAX_PATH];
POINT start_po, end_po;

// メニュー
on_command(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp){
    switch(LOWORD(wp)) {
    case IDM_MAKE_DIB_0:
    case IDM_MAKE_DIB_1:
    case IDM_MAKE_DIB_4:
    case IDM_MAKE_DIB_8:
    case IDM_MAKE_DIB_16:
    case IDM_MAKE_DIB_24:
    case IDM_MAKE_DIB_32:
        gt_dib_1.create(201, 151, LOWORD(wp)-IDM_MAKE_DIB_0, 0);
        gt_dib_1.apply_dc(hwnd);
        InvalidateRect(hwnd, NULL, 1);
        switch(gt_dib_1.m_bit_count) {
        case 1 : gt_dib_1.m_col_table.get_col_index<1>(r,g,b); break;
        case 4 : gt_dib_1.m_col_table.get_col_index<4>(r,g,b); break;
        case 8 : gt_dib_1.m_col_table.get_col_index<8>(r,g,b); break;
        }
        gt_dib_1.apply_palette_all();
        break;
    case IDM_COL:
        cc.lStructSize  = sizeof (CHOOSECOLOR);
        cc.hwndOwner    = hwnd;
        cc.rgbResult    = color;
        cc.lpCustColors = col_costom;
        cc.Flags    = CC_FULLOPEN | CC_RGBINIT;
        if (!ChooseColor(&cc)) break;
        color = cc.rgbResult;
        r = GetRValue(color);
        g = GetGValue(color);
        b = GetBValue(color);

        // パレット
        col_index = 0;
        switch(gt_dib_1.m_bit_count) {
        case 1 : gt_dib_1.m_col_table.get_col_index<1>(r,g,b); break;
        case 4 : gt_dib_1.m_col_table.get_col_index<4>(r,g,b); break;
        case 8 : gt_dib_1.m_col_table.get_col_index<8>(r,g,b); break;
        }
        gt_dib_1.apply_palette_all();
        break;
    }
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
    HDC hdc;
    PAINTSTRUCT ps;
    static POINT mou_po, po_array[4];
    static int mou_down=0;
    static char s[50];
    RECT rc;
    int y;
    HRGN hrgn, hrgn2;

    switch (msg) {
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        if (gt_dib_1.m_hdc){
            BitBlt( hdc, 20, 20, gt_dib_1.m_width, gt_dib_1.m_height, gt_dib_1.m_hdc, 0, 0, SRCCOPY);
        }
        sprintf(s, " ヨコ %d X タテ %d  %dビット",
                gt_dib_1.m_width, gt_dib_1.m_height, gt_dib_1.m_bit_count);
        GetClientRect(hwnd , &rc);
        rc.top=gt_dib_1.m_height+20;
        DrawText(hdc, s, -1, &rc, DT_WORDBREAK );

        EndPaint(hwnd, &ps);
        break;
    case WM_COMMAND:
        on_command(hwnd, msg, wp, lp);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_LBUTTONDOWN:
        if (!mou_down){
            GetCursorPos(&start_po);
            ScreenToClient(hwnd, &start_po);
            mou_down=1;
        }
        break;
    case WM_LBUTTONUP:
        if (mou_down){
            mou_down=0;
            GetCursorPos(&end_po);
            ScreenToClient(hwnd, &end_po);
            gt_dib_1.fill(start_po.x-20, start_po.y-20,
                    end_po.x-start_po.x, end_po.y-start_po.y, r, g, b, 255);
            InvalidateRect(hwnd, NULL, 1);
        }
        mou_down=0;
        break;
    case WM_MOUSEMOVE:
        if (mou_down){
            hdc=GetDC(hwnd);
            GetClientRect(hwnd , &rc);
            if (mou_down==2){
                po_array[0] = po_array[3] = start_po;
                po_array[1] = po_array[2] = mou_po;
                po_array[1].y=start_po.y;   po_array[3].y=mou_po.y;
                hrgn = CreatePolygonRgn(po_array , 4 , WINDING);
                SelectObject(hdc, hrgn);        
                PatBlt(hdc,  0, 0, rc.right, rc.bottom, PATINVERT);
                DeleteObject(hrgn);
            }
            mou_down=2;

            GetCursorPos(&mou_po);
            ScreenToClient(hwnd, &mou_po);
            po_array[0] = po_array[3] = start_po;
            po_array[1] = po_array[2] = mou_po;
            po_array[1].y=start_po.y;   po_array[3].y=mou_po.y;
            hrgn2 = CreatePolygonRgn(po_array , 4 , WINDING);
            SelectObject(hdc, hrgn2);       
            PatBlt(hdc,  0, 0, rc.right, rc.bottom, PATINVERT);
            DeleteObject(hrgn2);
            ReleaseDC(hwnd, hdc);
        }
        break;
    }
    return DefWindowProc(hwnd, msg, wp, lp);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,    PSTR lpCmdLine, int nCmdShow) {
    HWND hwnd;
    MSG msg;
    WNDCLASS winc;

    winc.style      = CS_HREDRAW | CS_VREDRAW;
    winc.lpfnWndProc    = WndProc;
    winc.cbClsExtra = winc.cbWndExtra   = 0;
    winc.hInstance      = hInstance;
    winc.hIcon      = LoadIcon(NULL, IDI_APPLICATION);
    winc.hCursor        = LoadCursor(NULL, IDC_ARROW);
    winc.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);
    winc.lpszMenuName   = TEXT("GT_DIB_MENU");
    winc.lpszClassName  = TEXT("GT_IMG");

    if (!RegisterClass(&winc)) return 1;

    hwnd = CreateWindow(
            TEXT("GT_IMG"), TEXT("ピクセル反復子"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 
            CW_USEDEFAULT, CW_USEDEFAULT, 300, 250, 
            NULL, NULL, hInstance, NULL
    );

    if (hwnd == NULL) return 1;

    while (GetMessage(&msg, NULL, 0, 0 )) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}


 007-01  前へ←  ホームへ  →次へ  007-03