#include <stdio.h>
#include <windows.h>
#include "resource_01.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);
};
// 近似色をパレットから取得
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_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);
// アルファ値
is_alpha(){ return (m_alpha!=NULL); }
// カラー
void set_pal_col(BYTE index, BYTE r, BYTE g, BYTE b);
apply_palette_all();
// DC 適用
apply_dc(HDC hdc);
apply_dc(HWND hwnd);
};
// コンストラクタ
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(){
m_width=0;
m_height=0;
m_byte_width=0;
m_bit_count=0;
if (m_col_mask) delete[] m_col_mask;
m_col_mask = NULL;
m_col_table.destroy();
if (m_hdc) { DeleteDC(m_hdc); m_hdc=NULL; }
if (m_hbmp) { DeleteObject(m_hbmp); m_hbmp=NULL; }
m_pbits = NULL;
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(){
if (!m_col_table.m_cols_len) return -1;
RGBQUAD *p_rgb, *rgb_table;
rgb_table=new RGBQUAD[m_col_table.m_cols_len];
for (int i=0;i<m_col_table.m_cols_len;i++){
p_rgb=&(rgb_table[i]);
p_rgb->rgbRed =m_col_table.m_cols[i].m_r;
p_rgb->rgbGreen =m_col_table.m_cols[i].m_g;
p_rgb->rgbBlue =m_col_table.m_cols[i].m_b;
p_rgb->rgbReserved=0;
}
if (m_hdc) SetDIBColorTable(m_hdc, 0, m_col_table.m_cols_len, rgb_table);
delete[] rgb_table;
return 0;
}
// パレットに色設定
inline void GT_DIB::set_pal_col(BYTE index, BYTE r, BYTE g, BYTE b){
if (m_col_table.m_cols_len<=index) return ;
m_col_table.set_col(index, r, g, b);
RGBQUAD rgb;
rgb.rgbRed =r;
rgb.rgbGreen =g;
rgb.rgbBlue =b;
rgb.rgbReserved =0;
if (m_hdc) SetDIBColorTable(m_hdc, index, 1, &rgb);
}
// 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_DIB gt_dib;
DWORD col=0xffffff;
// メニュー
on_command(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp){
static CHOOSECOLOR cc = {0};
static DWORD col_costom[8] = {0};
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.create(200, 150, LOWORD(wp)-IDM_MAKE_DIB_0, 0);
gt_dib.apply_dc(hwnd);
InvalidateRect(hwnd, NULL, 0);
break;
case IDM_COL_1: col= 0; break;
case IDM_COL_2: col= (gt_dib.m_bit_count<=8)? 1 : 0xffffff; break;
case IDM_COL_3: col= (gt_dib.m_bit_count<=8)? 2 : 0x0000ff; break;
case IDM_COL_4: col= (gt_dib.m_bit_count<=8)? 3 : 0xff0000; break;
case IDM_COL_5: col= (gt_dib.m_bit_count<=8)? 4 : 0x00ff00; break;
case IDM_COL_6: col= (gt_dib.m_bit_count<=8)? 5 : 0xffff00; break;
}
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
HDC hdc;
PAINTSTRUCT ps;
POINT po;
static int mou_down=0;
static char s[50];
switch (msg) {
case WM_PAINT:
if (gt_dib.m_hdc){
hdc = BeginPaint(hwnd, &ps);
BitBlt( hdc, 0, 0, gt_dib.m_width, gt_dib.m_height, gt_dib.m_hdc, 0, 0, SRCCOPY);
sprintf(s, "ヨコ %d X タテ %d", gt_dib.m_width, gt_dib.m_height);
TextOut(hdc, 0, gt_dib.m_height, s, strlen(s));
EndPaint(hwnd, &ps);
}
break;
case WM_COMMAND:
on_command(hwnd, msg, wp, lp);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_LBUTTONDOWN:
mou_down=1;
break;
case WM_LBUTTONUP:
mou_down=0;
break;
case WM_MOUSEMOVE:
if (mou_down){
GetCursorPos(&po);
ScreenToClient(hwnd, &po);
gt_dib.set_pixel(po.x, po.y, col);
InvalidateRect(hwnd, NULL, 0);
}
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, 250, 250,
NULL, NULL, hInstance, NULL
);
if (hwnd == NULL) return 1;
while (GetMessage(&msg, NULL, 0, 0 )) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
|