| 1 |
#include "CPixelbit.h" |
| 2 |
|
| 3 |
// 関数宣言 |
| 4 |
void Dialog(char *, ...); |
| 5 |
|
| 6 |
#ifdef ENABLE_RECT_BOUNDARY |
| 7 |
|
| 8 |
/* |
| 9 |
* 描画制限領域の初期化 |
| 10 |
*/ |
| 11 |
void CPixelbit::ResetBoundary(){ |
| 12 |
m_BoundLeft = m_BoundTop = 0; |
| 13 |
m_BoundRight = m_Width; |
| 14 |
m_BoundBottom = m_Height; |
| 15 |
} |
| 16 |
|
| 17 |
/* |
| 18 |
* 描画制限領域の設定 |
| 19 |
*/ |
| 20 |
void CPixelbit::SetBoundary( |
| 21 |
int x, int y, // 座標 |
| 22 |
int w, int h // サイズ |
| 23 |
){ |
| 24 |
m_BoundLeft = x; |
| 25 |
m_BoundTop = y; |
| 26 |
m_BoundRight = x+w; |
| 27 |
m_BoundBottom = y+h; |
| 28 |
if(m_BoundLeft<0) m_BoundLeft = 0; |
| 29 |
if(m_BoundTop<0) m_BoundTop = 0; |
| 30 |
if(m_BoundRight>m_Width) m_BoundRight = m_Width; |
| 31 |
if(m_BoundBottom>m_Height) m_BoundBottom = m_Height; |
| 32 |
} |
| 33 |
|
| 34 |
#endif // ENABLE_RECT_BOUNDARY |
| 35 |
|
| 36 |
/* |
| 37 |
* アルファチャネルを指定値でリセット |
| 38 |
*/ |
| 39 |
void CPixelbit::ResetAlphaChannel( |
| 40 |
BYTE alpha // アルファ値 |
| 41 |
){ |
| 42 |
int i; |
| 43 |
for(i = 0; i<m_Height; i++){ |
| 44 |
PDWORD line = m_PixelAdr+m_Width*i, stop = line+m_Width; |
| 45 |
for(; line<stop; line++) *((PBYTE)line+3) = alpha; |
| 46 |
} |
| 47 |
} |
| 48 |
|
| 49 |
/* |
| 50 |
* コピー時の矩形範囲を画像内に補正 |
| 51 |
* |
| 52 |
* 戻り値: コピー範囲があれば TRUE を返す |
| 53 |
*/ |
| 54 |
BOOL CPixelbit::FixLocation( |
| 55 |
CPixelbit *dest, // コピー先画像 |
| 56 |
int *dx, int *dy, // コピー先座標 |
| 57 |
int *sx, int *sy, // コピー元座標 |
| 58 |
int *w, int *h // コピーサイズ |
| 59 |
){ |
| 60 |
#ifdef ENABLE_RECT_BOUNDARY |
| 61 |
#define BOUNDLEFT dest->m_BoundLeft |
| 62 |
#define BOUNDTOP dest->m_BoundTop |
| 63 |
#else |
| 64 |
#define BOUNDLEFT 0 |
| 65 |
#define BOUNDTOP 0 |
| 66 |
#endif |
| 67 |
if(*dx<=BOUNDLEFT-m_Width || *dy<=BOUNDTOP-m_Height |
| 68 |
|| *dx>=dest->m_BoundRight || *dy>=dest->m_BoundBottom) return FALSE; |
| 69 |
int delta; |
| 70 |
if((delta = BOUNDLEFT-*dx)>0){ |
| 71 |
*w -= delta; *sx += delta; |
| 72 |
*dx = BOUNDLEFT; |
| 73 |
} |
| 74 |
if((delta = BOUNDTOP-*dy)>0){ |
| 75 |
*h -= delta; *sy += delta; |
| 76 |
*dy = BOUNDTOP; |
| 77 |
} |
| 78 |
if((delta = *dx+*w-dest->m_BoundRight)>0) *w -= delta; |
| 79 |
if((delta = *dy+*h-dest->m_BoundBottom)>0) *h -= delta; |
| 80 |
return *w>0 && *h>0; |
| 81 |
} |
| 82 |
|
| 83 |
/* |
| 84 |
* 指定デバイスコンテキストに描画 |
| 85 |
* |
| 86 |
* 戻り値: 成功したら TRUE を返す |
| 87 |
*/ |
| 88 |
BOOL CPixelbit::WindowStamp( |
| 89 |
HDC hdc, // デバイスコンテキスト |
| 90 |
int dx, int dy, // コピー先座標 |
| 91 |
int sx, int sy, // コピー元座標 |
| 92 |
int w, int h // コピーサイズ |
| 93 |
){ |
| 94 |
return m_ColorKey==0xffffffff ? SetDIBitsToDevice(hdc, dx, dy, w, h, |
| 95 |
sx, m_Height-sy-h, 0, m_Height, m_PixelAdr, &m_BmpInfo, DIB_RGB_COLORS) |
| 96 |
: ms_TransBlt(hdc, dx, dy, w, h, GetHDC(), sx, sy, w, h, m_ColorKey); |
| 97 |
} |
| 98 |
|
| 99 |
/* |
| 100 |
* 矩形範囲のコピー |
| 101 |
* |
| 102 |
* 戻り値: 成功したら TRUE を返す |
| 103 |
*/ |
| 104 |
BOOL CPixelbit::PlainStamp( |
| 105 |
CPixelbit *dest, // コピー先画像 |
| 106 |
int dx, int dy, // コピー先座標 |
| 107 |
int sx, int sy, // コピー元座標 |
| 108 |
int w, int h // コピーサイズ |
| 109 |
){ |
| 110 |
if(!FixLocation(dest, &dx, &dy, &sx, &sy, &w, &h)) return FALSE; |
| 111 |
return m_ColorKey==0xffffffff ? SetDIBitsToDevice(dest->m_BmpHdc, dx, dy, w, h, |
| 112 |
sx, m_Height-sy-h, 0, m_Height, m_PixelAdr, &m_BmpInfo, DIB_RGB_COLORS) |
| 113 |
: ms_TransBlt(dest->m_BmpHdc, dx, dy, w, h, GetHDC(), sx, sy, w, h, m_ColorKey); |
| 114 |
} |
| 115 |
|
| 116 |
/* |
| 117 |
* 矩形範囲のコピー |
| 118 |
* |
| 119 |
* 戻り値: 成功したら TRUE を返す |
| 120 |
*/ |
| 121 |
BOOL CPixelbit::PlainStamp32( |
| 122 |
CPixelbit *dest, // コピー先画像 |
| 123 |
int dx, int dy, // コピー先座標 |
| 124 |
int sx, int sy, // コピー元座標 |
| 125 |
int w, int h // コピーサイズ |
| 126 |
){ |
| 127 |
int i; |
| 128 |
if(!FixLocation(dest, &dx, &dy, &sx, &sy, &w, &h)) return FALSE; |
| 129 |
for(i = 0; i<h; i++){ |
| 130 |
PDWORD line1 = m_PixelAdr+m_Width*(i+sy)+sx, stop = line1+w; |
| 131 |
PDWORD line2 = dest->m_PixelAdr+dest->m_Width*(i+dy)+dx; |
| 132 |
while(line1<stop) *line2++ = *line1++; |
| 133 |
} |
| 134 |
return TRUE; |
| 135 |
} |
| 136 |
|
| 137 |
/* |
| 138 |
* アルファブレンドコピー |
| 139 |
* |
| 140 |
* 戻り値: 成功したら TRUE を返す |
| 141 |
*/ |
| 142 |
BOOL CPixelbit::AlphaBlendStamp( |
| 143 |
CPixelbit *dest, // コピー先画像 |
| 144 |
int dx, int dy, // コピー先座標 |
| 145 |
int sx, int sy, // コピー元座標 |
| 146 |
int w, int h // コピーサイズ |
| 147 |
){ |
| 148 |
int i; |
| 149 |
if(!FixLocation(dest, &dx, &dy, &sx, &sy, &w, &h)) return FALSE; |
| 150 |
for(i = 0; i<h; i++){ |
| 151 |
PDWORD line1 = m_PixelAdr+m_Width*(i+sy)+sx, stop = line1+w; |
| 152 |
PDWORD line2 = dest->m_PixelAdr+dest->m_Width*(i+dy)+dx; |
| 153 |
while(line1<stop){ |
| 154 |
int alpha, r1, g1, b1, r2, g2, b2; |
| 155 |
SplitColorA(*line1, &alpha, &r1, &g1, &b1); |
| 156 |
SplitColor(*line2, &r2, &g2, &b2); |
| 157 |
int beta = 255-alpha; |
| 158 |
PBYTE c = (PBYTE)line2; |
| 159 |
*c = (b1*alpha+b2*beta)/255; c++; |
| 160 |
*c = (g1*alpha+g2*beta)/255; c++; |
| 161 |
*c = (r1*alpha+r2*beta)/255; |
| 162 |
line1++; line2++; |
| 163 |
} |
| 164 |
} |
| 165 |
return TRUE; |
| 166 |
} |
| 167 |
|
| 168 |
/* |
| 169 |
* 伸縮コピー |
| 170 |
* |
| 171 |
* 戻り値: 成功したら TRUE を返す |
| 172 |
*/ |
| 173 |
BOOL CPixelbit::StretchStamp( |
| 174 |
CPixelbit *dest, // コピー先画像 |
| 175 |
int dx, int dy, // コピー先座標 |
| 176 |
int dw, int dh, // コピー先サイズ |
| 177 |
int sx, int sy, // コピー元座標 |
| 178 |
int sw, int sh, // コピー元サイズ |
| 179 |
int halftone // 伸縮モード |
| 180 |
){ |
| 181 |
SetStretchBltMode(dest->m_BmpHdc, halftone ? HALFTONE : COLORONCOLOR); |
| 182 |
return StretchBlt(dest->m_BmpHdc, dx, dy, dw, dh, m_BmpHdc, sx, sy, sw, sh, SRCCOPY); |
| 183 |
} |
| 184 |
|
| 185 |
/* |
| 186 |
* バイリニア伸縮コピー (範囲チェックなし) |
| 187 |
* |
| 188 |
* 戻り値: 成功したら TRUE を返す |
| 189 |
*/ |
| 190 |
BOOL CPixelbit::BilinearStamp( |
| 191 |
CPixelbit *dest, // コピー先画像 |
| 192 |
int dx, int dy, // コピー先座標 |
| 193 |
int dw, int dh, // コピー先サイズ |
| 194 |
int sx, int sy, // コピー元座標 |
| 195 |
int sw, int sh // コピー元サイズ |
| 196 |
){ |
| 197 |
if(dw==sw && dh==sh) return PlainStamp(dest, dx, dy, sx, sy, sw, sh); |
| 198 |
bool first = true; |
| 199 |
int a1, r1, g1, b1, a2, r2, g2, b2; |
| 200 |
DWORD x, y, fx, fy, tx, ty, tw, th; |
| 201 |
CPixelbit temp, *from, *to; |
| 202 |
if(sw*dh<dw*sh) goto VERTICAL; |
| 203 |
HORIZONTAL: |
| 204 |
if(dw!=sw){ |
| 205 |
tw = dw; |
| 206 |
if(first || dh==sh){ |
| 207 |
from = this; fx = sx; fy = sy; |
| 208 |
}else{ |
| 209 |
from = &temp; fx = fy = 0; |
| 210 |
} |
| 211 |
if(!first || dh==sh){ |
| 212 |
to = dest; tx = dx; ty = dy; th = dh; |
| 213 |
}else{ |
| 214 |
to = &temp; tx = ty = 0; th = sh; |
| 215 |
temp.Clear(tw, th); |
| 216 |
} |
| 217 |
if(dw<sw){ |
| 218 |
DWORD div = sw/tw, mod = sw%tw; |
| 219 |
double ratio = (double)tw/sw; |
| 220 |
for(y = 0; y<th; y++){ |
| 221 |
DWORD alpha = 0; |
| 222 |
PDWORD line1 = from->m_PixelAdr+from->m_Width*(y+fy)+fx; |
| 223 |
PBYTE line2 = (PBYTE)(to->m_PixelAdr+to->m_Width*(y+ty)+tx); |
| 224 |
for(x = 0; x<tw; x++){ |
| 225 |
DWORD i = div, j = mod; |
| 226 |
double asum = 0.0, rsum = 0.0, gsum = 0.0, bsum = 0.0; |
| 227 |
if(alpha){ |
| 228 |
double beta = (double)(tw-alpha)/tw; |
| 229 |
SplitColorA(*line1++, &a1, &r1, &g1, &b1); |
| 230 |
asum += a1*beta; rsum += r1*beta; |
| 231 |
gsum += g1*beta; bsum += b1*beta; |
| 232 |
i--; |
| 233 |
} |
| 234 |
do{ |
| 235 |
if(!i){ |
| 236 |
if((alpha += mod)<tw) break; |
| 237 |
alpha -= tw; |
| 238 |
} |
| 239 |
SplitColorA(*line1++, &a1, &r1, &g1, &b1); |
| 240 |
asum += a1; rsum += r1; gsum += g1; bsum += b1; |
| 241 |
} while(i--); |
| 242 |
if(alpha){ |
| 243 |
double beta = (double)alpha/tw; |
| 244 |
SplitColorA(*line1, &a1, &r1, &g1, &b1); |
| 245 |
asum += a1*beta; rsum += r1*beta; |
| 246 |
gsum += g1*beta; bsum += b1*beta; |
| 247 |
} |
| 248 |
*line2++ = (BYTE)(ratio*bsum+0.5); |
| 249 |
*line2++ = (BYTE)(ratio*gsum+0.5); |
| 250 |
*line2++ = (BYTE)(ratio*rsum+0.5); |
| 251 |
*line2++ = (BYTE)(ratio*asum+0.5); |
| 252 |
} |
| 253 |
} |
| 254 |
}else{ |
| 255 |
DWORD round = tw/2; |
| 256 |
for(y = 0; y<th; y++){ |
| 257 |
DWORD alpha = (tw+sw)/2; |
| 258 |
PDWORD begin = from->m_PixelAdr+from->m_Width*(y+fy)+fx; |
| 259 |
PDWORD line1 = begin-1, end = line1+sw; |
| 260 |
PBYTE line2 = (PBYTE)(to->m_PixelAdr+to->m_Width*(y+ty)+tx); |
| 261 |
for(x = 0; x<tw; x++){ |
| 262 |
SplitColorA(*(line1<begin ? begin : line1), &a1, &r1, &g1, &b1); |
| 263 |
SplitColorA(*(line1<end ? line1+1 : end), &a2, &r2, &g2, &b2); |
| 264 |
DWORD beta = tw-alpha; |
| 265 |
*line2++ = (BYTE)((b1*beta+b2*alpha+round)/tw); |
| 266 |
*line2++ = (BYTE)((g1*beta+g2*alpha+round)/tw); |
| 267 |
*line2++ = (BYTE)((r1*beta+r2*alpha+round)/tw); |
| 268 |
*line2++ = (BYTE)((a1*beta+a2*alpha+round)/tw); |
| 269 |
if((alpha += sw)>=tw){ |
| 270 |
line1++; |
| 271 |
alpha -= tw; |
| 272 |
} |
| 273 |
} |
| 274 |
} |
| 275 |
} |
| 276 |
} |
| 277 |
if(!first) return TRUE; |
| 278 |
first = false; |
| 279 |
VERTICAL: |
| 280 |
if(dh!=sh){ |
| 281 |
th = dh; |
| 282 |
if(first || dw==sw){ |
| 283 |
from = this; fx = sx; fy = sy; |
| 284 |
}else{ |
| 285 |
from = &temp; fx = fy = 0; |
| 286 |
} |
| 287 |
if(!first || dw==sw){ |
| 288 |
to = dest; tx = dx; ty = dy; tw = dw; |
| 289 |
}else{ |
| 290 |
to = &temp; tx = ty = 0; tw = sw; |
| 291 |
temp.Clear(tw, th); |
| 292 |
} |
| 293 |
if(dh<sh){ |
| 294 |
DWORD div = sh/th, mod = sh%th; |
| 295 |
double ratio = (double)th/sh; |
| 296 |
for(x = 0; x<tw; x++){ |
| 297 |
DWORD alpha = 0; |
| 298 |
PDWORD line1 = from->m_PixelAdr+from->m_Width*fy+x+fx; |
| 299 |
PBYTE line2 = (PBYTE)(to->m_PixelAdr+to->m_Width*ty+x+tx); |
| 300 |
for(y = 0; y<th; y++){ |
| 301 |
DWORD i = div, j = mod; |
| 302 |
double asum = 0.0, rsum = 0.0, gsum = 0.0, bsum = 0.0; |
| 303 |
if(alpha){ |
| 304 |
double beta = (double)(th-alpha)/th; |
| 305 |
SplitColorA(*line1, &a1, &r1, &g1, &b1); |
| 306 |
line1 += from->m_Width; |
| 307 |
asum += a1*beta; rsum += r1*beta; |
| 308 |
gsum += g1*beta; bsum += b1*beta; |
| 309 |
i--; |
| 310 |
} |
| 311 |
do{ |
| 312 |
if(!i){ |
| 313 |
if((alpha += mod)<th) break; |
| 314 |
alpha -= th; |
| 315 |
} |
| 316 |
SplitColorA(*line1, &a1, &r1, &g1, &b1); |
| 317 |
line1 += from->m_Width; |
| 318 |
asum += a1; rsum += r1; gsum += g1; bsum += b1; |
| 319 |
} while(i--); |
| 320 |
if(alpha){ |
| 321 |
double beta = (double)alpha/th; |
| 322 |
SplitColorA(*line1, &a1, &r1, &g1, &b1); |
| 323 |
asum += a1*beta; rsum += r1*beta; |
| 324 |
gsum += g1*beta; bsum += b1*beta; |
| 325 |
} |
| 326 |
*line2++ = (BYTE)(ratio*bsum+0.5); |
| 327 |
*line2++ = (BYTE)(ratio*gsum+0.5); |
| 328 |
*line2++ = (BYTE)(ratio*rsum+0.5); |
| 329 |
*line2 = (BYTE)(ratio*asum+0.5); |
| 330 |
line2 += (to->m_Width<<2)-3; |
| 331 |
} |
| 332 |
} |
| 333 |
}else{ |
| 334 |
DWORD round = th/2; |
| 335 |
for(x = 0; x<tw; x++){ |
| 336 |
DWORD alpha = (th+sh)/2; |
| 337 |
PDWORD begin = from->m_PixelAdr+from->m_Width*fy+x+fx; |
| 338 |
PDWORD line1 = begin-from->m_Width, end = line1+from->m_Width*sh; |
| 339 |
PBYTE line2 = (PBYTE)(to->m_PixelAdr+to->m_Width*ty+x+tx); |
| 340 |
for(y = 0; y<th; y++){ |
| 341 |
SplitColorA(*(line1<begin ? begin : line1), &a1, &r1, &g1, &b1); |
| 342 |
SplitColorA(*(line1<end ? line1+from->m_Width : end), &a2, &r2, &g2, &b2); |
| 343 |
DWORD beta = th-alpha; |
| 344 |
*line2++ = (BYTE)((b1*beta+b2*alpha+round)/th); |
| 345 |
*line2++ = (BYTE)((g1*beta+g2*alpha+round)/th); |
| 346 |
*line2++ = (BYTE)((r1*beta+r2*alpha+round)/th); |
| 347 |
*line2 = (BYTE)((a1*beta+a2*alpha+round)/th); |
| 348 |
line2 += (to->m_Width<<2)-3; |
| 349 |
if((alpha += sh)>=th){ |
| 350 |
line1 += from->m_Width; |
| 351 |
alpha -= th; |
| 352 |
} |
| 353 |
} |
| 354 |
} |
| 355 |
} |
| 356 |
} |
| 357 |
if(!first) return TRUE; |
| 358 |
first = false; |
| 359 |
goto HORIZONTAL; |
| 360 |
} |
| 361 |
|
| 362 |
/* |
| 363 |
* 最近点伸縮コピー (範囲チェックなし) |
| 364 |
* |
| 365 |
* 戻り値: 成功したら TRUE を返す |
| 366 |
*/ |
| 367 |
BOOL CPixelbit::NearestStamp( |
| 368 |
CPixelbit *dest, // コピー先画像 |
| 369 |
int dx, int dy, // コピー先座標 |
| 370 |
int dw, int dh, // コピー先サイズ |
| 371 |
int sx, int sy, // コピー元座標 |
| 372 |
int sw, int sh // コピー元サイズ |
| 373 |
){ |
| 374 |
if(dw==sw && dh==sh) return PlainStamp(dest, dx, dy, sx, sy, sw, sh); |
| 375 |
int wdiv = sw/dw, wmod = sw%dw, wrm = (sw/2)%dw; |
| 376 |
int hdiv = sh/dh, hmod = sh%dh, alpha = (sh/2)%dh, i; |
| 377 |
PDWORD line0 = m_PixelAdr+m_Width*(sy+sh/(dh*2))+sx+sw/(dw*2); |
| 378 |
for(i = 0; i<dh; i++){ |
| 379 |
int beta = wrm; |
| 380 |
PDWORD line2 = dest->m_PixelAdr+dest->m_Width*(i+dy)+dx; |
| 381 |
PDWORD line1 = line0, stop = line2+dw; |
| 382 |
while(line2<stop){ |
| 383 |
*line2++ = *line1; |
| 384 |
line1 += wdiv+((beta += wmod)>=dw ? ((beta -= dw), 1) : 0); |
| 385 |
} |
| 386 |
line0 += m_Width*(hdiv+((alpha += hmod)>=dh ? ((alpha -= dh), 1) : 0)); |
| 387 |
} |
| 388 |
return TRUE; |
| 389 |
} |