home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Phoenix Heaven Sunny 2
/
APPARE2.BIN
/
oh_towns
/
art2
/
src.lzh
/
PIC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-19
|
29KB
|
1,057 lines
/*====================================================
ARTemis
(version 1.3)
FM-TOWNS 用ペイントツール
by 松内 良介 1994
====================================================*/
#if 0
pic.c : 「画像」
pic_init
pic_new(wid,ht)
pic_destroy(pic)
pic_dup(pic)
static void pic_updatePoint(PIC* pic,int x,int y)
static void pic_updateRect(PIC* pic, int x,int y,int wid,int ht)
pic_setPixelXy(pic,x,y,pixel) 1ピクセルの色を設定
pic_getPixelXy(pic,x,y,pixel) 1ピクセルの色を取得
void pic_grayPset(PIC* pic,int x,int y,int gray,PIXEL *pixel);
void pic_psetpen(PIC *pic,int x,int y,Pen pen,PIXEL *pixel);
void pic_grayhline(PIC *pic,int x1,int x2,int y,int gray,PIXEL *pixel);
void pic_clear(PIC *pic, PIXEL *pixel);
void pic_kosuriStart(PIC* pic,int x,int y,char* graypat,int wid,int ht);
void pic_kosuriDrag(PIC* pic,int x,int y,int r);
void pic_copy(PIC* picSrc, FRAME* frSrc, PIC* picDest, POINT* ptDest);
void pic_copyarea(PIC* picSrc, AREA areaSrc, PIC* picDest, POINT* ptDest);
void pic_paint(PIC *pic, int x,int y, PIXEL* pix);
void pic_blot(PIC *pic,int x,int y,PIXEL* pix,int branch,int depth)
void pic_diffusePen(PIC* pic,int x,int y,Pen pen);
void pic_sandPen(PIC* pic,int x,int y,Pen pen);
void pic_polygon(PIC* pic,POINT* points,int nPoint,PIXEL* pix);
void pic_fillarea(PIC* pic,AREA area,PIXEL* pix);
pic_beginUpDate(pic) 更新領域のクリア
pic_endUpDate(pic,frame) 更新終了;更新領域の取得
pic_loadTIFF_
pic_saveTIFF_
pic_getRectImage(pic,buf,frame)
void pic_getScrBitMap(PIC* pic,SCRBITMAP bm,int ofsx,int ofsy, FRAME *fr);
// 画像内の fr の領域を bm の ofsx, ofsy に転送する
pixel_setRgb(pixel, r,g,b)
pixel_getRgb(pixel, r,g,b)
#endif
#define MODULE_PIC
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winb.h>
#include <memory.h>
#include <te.h>
#include <fntb.h>
#include <gui.h>
#include <egb.h>
#include "art.h"
#include "pic.h"
#include "subgrp.h"
#include "guisub.h"
#include "pensel.h"
static char* tempBuf = NULL;
static uint _31_255[] =
{ 0,8,16,25, 33,41,49,58, 66,74,82,90, 99,107,115,123,
132,140,148,156, 165,173,181,189, 197,206,214,222,
230,239,247,255};
int pic_init(void)
{
return 0;
}
void pic_close(void)
{
}
PIC *pic_new(int pixelsize, int wid,int ht)
{
PIC *pic;
if ((pic = TL_calloc(1, sizeof(PIC))) == NULL)
return NULL;
if ((pic->buf = TL_calloc(1,wid*ht*pixelsize/8)) == NULL)
{ TL_free(pic); return NULL; }
memset(pic->buf, 0xff, wid*ht*pixelsize/8);
pic->wid = wid;
pic->ht = ht;
pic->pixelsize = pixelsize;
return pic;
}
PIC* pic_dup(PIC* pic)
{
PIC* newpic;
if ((newpic = TL_calloc(1,sizeof(PIC))) == NULL)
return NULL;
if ((newpic->buf = TL_calloc(1,pic->pixelsize*pic->wid*pic->ht/8)) == NULL)
{ TL_free(newpic); return NULL; }
memcpy(newpic->buf, pic->buf, pic->wid*pic->ht*pic->pixelsize/8);
newpic->wid = pic->wid;
newpic->ht = pic->ht;
newpic->pixelsize = pic->pixelsize;
return newpic;
}
void pic_destroy(PIC *pic)
{
TL_free(pic->buf);
TL_free(pic);
}
/*--------------------------------------------------------*/
/* PIC更新情報の更新 */
/*--------------------------------------------------------*/
static void pic_updatePoint(PIC* pic,int x,int y)
{
if (pic->update.lupx < 0)
{
pic->update.lupx = pic->update.rdwx = x;
pic->update.lupy = pic->update.rdwy = y;
}
else
{
if (x < pic->update.lupx)
pic->update.lupx = x;
else if (pic->update.rdwx < x)
pic->update.rdwx = x;
if (y < pic->update.lupy)
pic->update.lupy = y;
else if (pic->update.rdwy < y)
pic->update.rdwy = y;
}
}
static void pic_updateRect(PIC* pic, int x,int y,int wid,int ht)
{
// 内容変更領域を更新
int left,top,right,bottom;
left = _max(0,x);
right = _min(pic->wid-1,x+wid-1);
top = _max(0,y);
bottom = _min(pic->ht-1,y+ht-1);
if (pic->update.X < 0)
{
pic->update.X = left;
pic->update.X2 = right;
pic->update.Y = top;
pic->update.Y2 = bottom;
}
else
{
#define R (pic->update)
R.X = _min(R.X, left);
R.X2 = _max(R.X2, right);
R.Y = _min(R.Y, top);
R.Y2 = _max(R.Y2, bottom);
#undef R
}
}
/*--------------------------------------------------------*/
/* ピクセルの色の設定・取得 */
/*--------------------------------------------------------*/
void pic_setPixelXy(PIC *pic, int x, int y, PIXEL *pixel)
/* 1ピクセルの色を設定 */
{
if (x < 0 || pic->wid<=x || y < 0 || pic->ht<=y)
return;
if (pic->pixelsize == 16)
*(unsigned short*)&pic->buf[(pic->wid * y + x) * 2] = CODE32K(*pixel);
else
{
char *p = PICADDR(pic,x,y);
uint col = CODE16M(*pixel);
SETBYTE3(p,col);
}
pic_updatePoint(pic, x,y);
}
void pic_grayPset(PIC* pic,int x,int y,int gray,PIXEL* pixel)
{
if (x < 0 || pic->wid<=x || y < 0 || pic->ht<=y)
return;
if (pic->pixelsize == 16)
{
ushort* p = (ushort*)PICADDR(pic,x,y);
int col = CODE32K(*pixel);
int sr,sg,sb,dr,dg,db;
GETRGB31(*p, dr,dg,db);
GETRGB31(col, sr,sg,sb);
dr = (dr * (255-gray) + sr * gray) / 255;
dg = (dg * (255-gray) + sg * gray) / 255;
db = (db * (255-gray) + sb * gray) / 255;
SETRGB31(*p, dr,dg,db);
}
else
{
char* p = PICADDR(pic,x,y);
int sr,sg,sb,dr,dg,db;
sr=pixel->r,sg=pixel->g,sb=pixel->b;
dr=p[0],dg=p[1],db=p[2];
dr = (dr * (255-gray) + sr * gray) / 255;
dg = (dg * (255-gray) + sg * gray) / 255;
db = (db * (255-gray) + sb * gray) / 255;
p[0]=dr,p[1]=dg,p[2]=db;
}
pic_updatePoint(pic, x,y);
}
void pic_getPixelXy(PIC *pic, int x, int y, PIXEL *pixel)
/* 1ピクセルの色を取得 */
{
if (x < 0 || pic->wid<=x || y < 0 || pic->ht<=y)
return;
if (pic->pixelsize == 16)
{
int col = *(unsigned short*)&pic->buf[(pic->wid * y + x) * 2];
int r,g,b;
GETRGB31(col,r,g,b);
pixel->r = _31_255[r];
pixel->g = _31_255[g];
pixel->b = _31_255[b];
}
else
{
char *p = PICADDR(pic,x,y);
pixel->r = p[0];
pixel->g = p[1];
pixel->b = p[2];
}
}
/*--------------------------------------------------------*/
/* 濃度分布の描画 */
/*--------------------------------------------------------*/
void pic_psetpen(PIC *pic,int x,int y,Pen pen,PIXEL *pixel)
{
uint mix = pensel_getmix();
x -= pen->ofsx;
y -= pen->ofsy;
for (int i=0; i<pen->ht; i++)
{
int dy = y + i;
if (dy < 0 || pic->ht <= dy)
continue;
char *penp = pen->buf + pen->wid * i;
if (pic->pixelsize == 16)
{
char *dp = PICADDR(pic,x,dy);
int col = CODE32K(*pixel);
int sr,sg,sb,dr,dg,db;
GETRGB31(col,sr,sg,sb);
for (int j=0; j<pen->wid; j++,dp+=2,penp++)
{
if (*penp == 0 || x+j < 0 || pic->wid <= x+j)
continue;
uint mr = (mix * (*penp) + 127) / 255;
GETRGB31(WORD(dp),dr,dg,db);
dr = (dr * (255-mr) + sr * (uint)mr + 127)/255;
dg = (dg * (255-mr) + sg * (uint)mr + 127)/255;
db = (db * (255-mr) + sb * (uint)mr + 127)/255;
SETRGB31(WORD(dp),dr,dg,db);
}
}
else
{
char *dp = PICADDR(pic,x,dy);
int sr,sg,sb,dr,dg,db;
sr=pixel->r,sg=pixel->g,sb=pixel->b;
for (int j=0; j<pen->wid; j++,dp+=3,penp++)
{
if (*penp == 0 || x+j < 0 || pic->wid <= x+j)
continue;
uint mr = (mix * (*penp) + 127) / 255;
dr=dp[0],dg=dp[1],db=dp[2];
dr = (dr * (255-mr) + sr * (uint)mr + 127)/255;
dg = (dg * (255-mr) + sg * (uint)mr + 127)/255;
db = (db * (255-mr) + sb * (uint)mr + 127)/255;
dp[0]=dr,dp[1]=dg,dp[2]=db;
}
}
}
pic_updateRect(pic,x,y,pen->wid,pen->ht);
}
/*--------------------------------------------------------*/
/* 水平直線の描画 */
/*--------------------------------------------------------*/
void pic_grayhline(PIC *pic,int x1,int x2,int y,int gray,PIXEL *pixel)
{
if (x1 >= x2)
SWAP_INT(x1,x2)
if (y < 0 || pic->ht <= y)
return;
x1 = _max(0,x1);
x2 = _min(pic->wid-1,x2);
if (x2 < x1)
return;
if (pic->pixelsize == 16)
{
char *dp = PICADDR(pic,x1,y);
ushort col = CODE32K(*pixel);
if (gray >= 255)
{
for (int i=x1; i<=x2; i++,dp+=2)
WORD(dp) = col;
}
else if (gray > 0)
{
int sr,sg,sb,dr,dg,db;
int igray = 255 - gray;
GETRGB31(col, sr,sg,sb);
for (int i=x1; i<=x2; i++,dp+=2)
{
GETRGB31(WORD(dp), dr,dg,db);
dr = (dr * igray + sr * gray + 128) / 255;
dg = (dg * igray + sg * gray + 128) / 255;
db = (db * igray + sb * gray + 128) / 255;
SETRGB31(WORD(dp), dr,dg,db);
}
}
}
else if (pic->pixelsize == 24)
{
char *dp = PICADDR(pic,x1,y);
if (gray >= 255)
{
for (int i=x1; i<=x2; i++,dp+=3)
dp[0]=pixel->r,dp[1]=pixel->g,dp[2]=pixel->b;
}
else if (gray > 0)
{
int sr,sg,sb,dr,dg,db;
sr=pixel->r,sg=pixel->g,sb=pixel->b;
int igray = 255 - gray;
for (int i=x1; i<=x2; i++,dp+=3)
{
dr=dp[0],dg=dp[1],db=dp[2];
dr = (dr * igray + sr * (uint)gray + 127)/255;
dg = (dg * igray + sg * (uint)gray + 127)/255;
db = (db * igray + sb * (uint)gray + 127)/255;
dp[0]=dr,dp[1]=dg,dp[2]=db;
}
}
}
pic_updateRect(pic,x1,y,x2-x1+1,1);
}
/*--------------------------------------------------------*/
/* クリア */
/*--------------------------------------------------------*/
void pic_clear(PIC *pic, PIXEL *pixel)
{
int i;
for (i = 0; i < pic->ht; i++)
pic_grayhline(pic, 0, pic->wid-1, i, 255, pixel);
}
/*--------------------------------------------------------*/
/* こすり処理 */
/*--------------------------------------------------------*/
char *kosuri_graypat;
int kosuri_x, kosuri_y;
int kosuri_wid,kosuri_ht;
void pic_kosuriStart(PIC* pic,int x,int y,char* graypat,int wid,int ht)
// x,y : ペンの左上端の PIC 座標
// graypat : ペンの濃度デ-タ
// wid,ht : ペンの大きさ
{
kosuri_graypat = graypat;
kosuri_x = x;
kosuri_y = y;
kosuri_wid = wid;
kosuri_ht = ht;
if (tempBuf != NULL)
TL_free(tempBuf);
tempBuf = TL_calloc(1,pic->pixelsize*kosuri_wid*kosuri_ht/8);
}
void pic_kosuriDrag(PIC* pic,int x,int y,int r)
// x,y : ペンの左上端の PIC 座標
// r : こすり強さ (0~255)
{
if (tempBuf == NULL)
return;
int i,j;
// 前のペンの位置の色を tempBuf に格納
char *p = kosuri_graypat;
for (i=0; i<kosuri_ht; i++)
{
if (kosuri_y+i < 0)
continue;
else if (kosuri_y+i >= pic->ht)
break;
char *ptrpic;
ptrpic = pic->buf + PICOFFSET(pic,kosuri_x,kosuri_y+i);
char *ptrbuf;
ptrbuf = tempBuf + (kosuri_wid*i) * pic->pixelsize/8;
if (pic->pixelsize == 16)
{
for (j=0; j<kosuri_wid; j++,p++,ptrpic+=2,ptrbuf+=2)
{
if (kosuri_x+j < 0)
continue;
else if (kosuri_x+j >= pic->wid)
break;
if (*p == 0)
continue;
WORD(ptrbuf) = WORD(ptrpic);
}
}
else
{
for (j=0; j<kosuri_wid; j++,p++,ptrpic+=3,ptrbuf+=3)
{
if (kosuri_x+j < 0)
continue;
else if (kosuri_x+j >= pic->wid)
break;
if (*p == 0)
continue;
WORD(ptrbuf) = WORD(ptrpic);
BYTE(ptrbuf+2) = BYTE(ptrpic+2);
}
}
}
// 新しいペンの位置と色をまぜあわせる
p = kosuri_graypat;
for (i=0; i<kosuri_ht; i++)
{
if (y+i < 0)
continue;
else if (y+i >= pic->ht)
break;
char *ptrpic;
ptrpic = pic->buf + PICOFFSET(pic,x,y+i);
char *ptrbuf;
ptrbuf = tempBuf + (kosuri_wid*i) * pic->pixelsize/8;
if (pic->pixelsize == 16)
{
for (j=0; j<kosuri_wid; j++,p++,ptrpic+=2,ptrbuf+=2)
{
if (x+j < 0)
continue;
else if (x+j >= pic->wid)
break;
if (*p == 0)
continue;
unsigned int sc,dc, sr,sg,sb,dr,dg,db,tr,tg,tb;
sc = WORD(ptrbuf);
dc = WORD(ptrpic);
sr=(sc>>5)&31,sg=(sc>>10)&31,sb=sc&31;
dr=(dc>>5)&31,dg=(dc>>10)&31,db=dc&31;
tr = (sr*r+dr*(255-r)+127)/255;
tg = (sg*r+dg*(255-r)+127)/255;
tb = (sb*r+db*(255-r)+127)/255;
WORD(ptrpic) = (tg<<10)|(tr<<5)|tb;
tr = (sr*(255-r)+dr*r+127)/255;
tg = (sg*(255-r)+dg*r+127)/255;
tb = (sb*(255-r)+db*r+127)/255;
WORD(ptrbuf) = (tg<<10)|(tr<<5)|tb;
}
}
else
{
for (j=0; j<kosuri_wid; j++,p++,ptrpic+=3,ptrbuf+=3)
{
if (x+j < 0)
continue;
else if (x+j >= pic->wid)
break;
if (*p == 0)
continue;
unsigned int sr,sg,sb,dr,dg,db,tr,tg,tb;
sr=ptrbuf[0],sg=ptrbuf[1],sb=ptrbuf[2];
dr=ptrpic[0],dg=ptrpic[1],db=ptrpic[2];
tr = (sr*r+dr*(255-r)+127)/255;
tg = (sg*r+dg*(255-r)+127)/255;
tb = (sb*r+db*(255-r)+127)/255;
ptrpic[0]=tr,ptrpic[1]=tg,ptrpic[2]=tb;
tr = (sr*(255-r)+dr*r+127)/255;
tg = (sg*(255-r)+dg*r+127)/255;
tb = (sb*(255-r)+db*r+127)/255;
ptrbuf[0]=tr,ptrbuf[1]=tg,ptrbuf[2]=tb;
}
}
}
pic_updateRect(pic, x,y,kosuri_wid,kosuri_ht);
// 次のこすりドラッグ
kosuri_x = x;
kosuri_y = y;
}
/*--------------------------------------------------------*/
/* ペン先ぼかし */
/*--------------------------------------------------------*/
void pic_diffusePen(PIC* pic,int x,int y,Pen pen)
{
int picxbytes = pic->wid * pic->pixelsize / 8;
int picy = y - pen->ofsy;
for (int i=0; i<pen->ht; i++,picy++)
{
if (picy < 0 || pic->ht <= picy)
continue;
int picx = x - pen->ofsx;
char* penp = pen->buf + PENOFFSET(pen,0,i);
char* picp = pic->buf + PICOFFSET(pic,picx,picy);
if (pic->pixelsize == 16)
{
for (int j=0; j<pen->wid; j++,picx++,penp++,picp+=2)
{
if (*penp == 0 || picx < 0 || pic->wid <= picx)
continue;
#define DIF 6
uint r,g,b;
uint sum,rsum,gsum,bsum; sum=rsum=gsum=bsum=0;
GETRGB31(WORD(picp),r,g,b);
rsum+=r*DIF; gsum+=g*DIF; bsum+=b*DIF; sum+=DIF;
if (picy-1 >= 0)
{ GETRGB31(WORD(picp-picxbytes),r,g,b);
rsum+=r,gsum+=g,bsum+=b,sum++; }
if (picy+1 < pic->ht)
{ GETRGB31(WORD(picp+picxbytes),r,g,b);
rsum+=r,gsum+=g,bsum+=b,sum++; }
if (picx-1 >= 0)
{ GETRGB31(WORD(picp-2),r,g,b);
rsum+=r,gsum+=g,bsum+=b,sum++; }
if (picx+1 < pic->wid)
{ GETRGB31(WORD(picp+2),r,g,b);
rsum+=r,gsum+=g,bsum+=b,sum++; }
rsum = (rsum+sum/2) / sum;
gsum = (gsum+sum/2) / sum;
bsum = (bsum+sum/2) / sum;
SETRGB31(WORD(picp),rsum,gsum,bsum);
#undef DIF
}
}
else
{
for (int j=0; j<pen->wid; j++,picx++,penp++,picp+=3)
{
if (*penp == 0 || picx < 0 || pic->wid <= picx)
continue;
#define DIF 6
uint r,g,b;
uint sum,rsum,gsum,bsum; sum=rsum=gsum=bsum=0;
r=picp[0],g=picp[1],b=picp[2];
rsum+=r*DIF; gsum+=g*DIF; bsum+=b*DIF; sum+=DIF;
if (picy-1 >= 0)
{ GET3BYTE(picp-picxbytes,r,g,b);
rsum+=r,gsum+=g,bsum+=b,sum++; }
if (picy+1 < pic->ht)
{ GET3BYTE(picp+picxbytes,r,g,b);
rsum+=r,gsum+=g,bsum+=b,sum++; }
if (picx-1 >= 0)
{ GET3BYTE(picp-3,r,g,b);
rsum+=r,gsum+=g,bsum+=b,sum++; }
if (picx+1 < pic->wid)
{ GET3BYTE(picp+3,r,g,b);
rsum+=r,gsum+=g,bsum+=b,sum++; }
rsum = (rsum+sum/2) / sum;
gsum = (gsum+sum/2) / sum;
bsum = (bsum+sum/2) / sum;
picp[0]=rsum,picp[1]=gsum,picp[2]=bsum;
#undef DIF
}
}
}
pic_updateRect(pic, x-pen->ofsx, y-pen->ofsy, pen->wid, pen->ht);
}
void pic_sandPen(PIC* pic,int x,int y,Pen pen)
{
int picxbytes = pic->wid * pic->pixelsize / 8;
int picy = y - pen->ofsy;
for (int i=0; i<pen->ht; i++,picy++)
{
if (picy < 0 || pic->ht <= picy)
continue;
int picx = x - pen->ofsx;
char* penp = pen->buf + PENOFFSET(pen,0,i);
char* picp = pic->buf + PICOFFSET(pic,picx,picy);
if (pic->pixelsize == 16)
{
for (int j=0; j<pen->wid; j++,picx++,penp++,picp+=2)
{
if (*penp == 0 || picx < 0 || pic->wid <= picx)
continue;
#define DIF 6
int r,g,b;
GETRGB31(WORD(picp),r,g,b);
r = _min(31,_max(0, r + rand() % 3 - 1));
g = _min(31,_max(0, g + rand() % 3 - 1));
b = _min(31,_max(0, b + rand() % 3 - 1));
SETRGB31(WORD(picp),r,g,b);
#undef DIF
}
}
else
{
for (int j=0; j<pen->wid; j++,picx++,penp++,picp+=3)
{
if (*penp == 0 || picx < 0 || pic->wid <= picx)
continue;
int r,g,b;
r=picp[0],g=picp[1],b=picp[2];
r = _min(255,_max(0, r + (rand() % 13 - 6)));
g = _min(255,_max(0, g + (rand() % 13 - 6)));
b = _min(255,_max(0, b + (rand() % 13 - 6)));
picp[0]=r,picp[1]=g,picp[2]=b;
}
}
}
pic_updateRect(pic, x-pen->ofsx, y-pen->ofsy, pen->wid, pen->ht);
}
/*--------------------------------------------------------*/
/* 更新の開始・終了 */
/*--------------------------------------------------------*/
void pic_beginUpDate(PIC *pic)
{
pic->update.lupx = -1;
}
void pic_endUpDate(PIC *pic, FRAME *frame)
{
pic->update.WID = pic->update.X2 - pic->update.X + 1;
pic->update.HT = pic->update.Y2 - pic->update.Y + 1;
*frame = pic->update;
}
static PIC *_pic;
static TIFFINFO tiffinfo;
static int putimage(char *buf, int ofsy, int ht)
{
for (int i=0; i<ht; i++)
{
if (ofsy+i >= _pic->ht)
break;
char *dp = _pic->buf + PICOFFSET(_pic, 0, ofsy+i);
char *sp = buf + (tiffinfo.wid*tiffinfo.pixelsize/8)*i;
int wid = _min(_pic->wid, tiffinfo.wid);
int t = wid * _pic->pixelsize / 8;
memcpy(dp, sp, t);
}
return 0;
}
static int getimage(char *buf,int ofsy,int ht)
{
for (int i=0; i<ht; i++)
{
if (ofsy+i >= _pic->ht)
break;
char *dp = buf + (tiffinfo.wid*tiffinfo.pixelsize/8)*i;
char *sp = _pic->buf + PICOFFSET(_pic, 0, ofsy+i);
int wid = _min(_pic->wid, tiffinfo.wid);
int t = wid * _pic->pixelsize / 8;
memcpy(dp, sp, t);
}
return 0;
}
int pic_loadTIFF_(PIC *pic, char *fname)
/* PIC構造体内に TIFF ファイルの画像をロードする */
{
_pic = pic;
int ret;
if ((ret = RM_getTIFFinfo(fname, &tiffinfo)) != NOERR)
return ret;
ret = RM_loadTIFF(fname, putimage, (int(*)())0);
return ret;
}
int pic_saveTIFF_(PIC *pic, char *fname)
{
_pic = pic;
tiffinfo.wid = pic->wid;
tiffinfo.ht = pic->ht;
tiffinfo.pixelsize = pic->pixelsize;
int ret;
ret = RM_saveTIFF(fname, pic->pixelsize, pic->wid, pic->ht, TRUE,
getimage, (int(*)())0);
return ret;
}
void pic_getScrBitMap(PIC* pic,SCRBITMAP bm, int ofsx, int ofsy, FRAME *_fr,
int zoom)
// 画像内の fr(x,y,wid,ht) の領域を bm の ofsx, ofsy に転送する
// 画面イメージへの変換を行う
{
int i;
FRAME fr;
fr = *_fr;
if (ofsx < 0)
fr.X+=(-ofsx)/zoom, fr.WID-=(-ofsx)/zoom, ofsx=0;
if (ofsy < 0)
fr.Y+=(-ofsy)/zoom, fr.HT-=(-ofsy)/zoom, ofsy=0;
if (fr.WID <= 0 && fr.HT <= 0)
return;
int wid = _min(fr.WID, pic->wid - fr.X,
(bm->wid - ofsx + zoom-1) / zoom);
// ↑実際の転送ドット数
if (wid <= 0)
return;
int dcnt = _min(zoom, bm->wid - ofsx - (wid-1)*zoom);
// ↑SCRBITMAP側の右端のピクセルの横幅
int dxbytes = bm->wid * bm->pixelsize / 8;
// ↑SCRBITMAPの横バイト数
int dxcnt = (wid-1)*zoom + dcnt;
// ↑SCRBITMAP側の転送領域の横ピクセル数
for (i=0; i<fr.HT; i++)
{
int dy = ofsy + zoom * i;
int sy = fr.Y + i;
if (sy < 0 || pic->ht <= sy)
continue;
if (dy < 0 || bm->ht <= dy)
continue;
if (wid == 0)
break;
char *dp = bm->buf + BMOFFSET(bm, ofsx, dy);
char *dp0 = dp;
char *sp = pic->buf + PICOFFSET(pic, fr.X, sy);
if (zoom==1 && pic->pixelsize == 16 && bm->pixelsize == 16)
memcpy(dp,sp,wid * 2);
else if (pic->pixelsize == 16 && bm->pixelsize == 16)
{
int j;
if (zoom == 2)
for (j=0; j<wid-1; j++,sp+=2,dp+=4)
WORD(dp)=WORD(dp+2)=WORD(sp);
else if (zoom==3)
for (j=0; j<wid-1; j++,sp+=2,dp+=6)
WORD(dp)=WORD(dp+2)=WORD(dp+4)=WORD(sp);
else if (zoom==4)
for (j=0; j<wid-1; j++,sp+=2,dp+=8)
WORD(dp)=WORD(dp+2)=WORD(dp+4)=WORD(dp+6)=WORD(sp);
else if (zoom==5)
for (j=0; j<wid-1; j++,sp+=2,dp+=10)
WORD(dp)=WORD(dp+2)=WORD(dp+4)=WORD(dp+6)=
WORD(dp+8)=WORD(sp);
else if (zoom==6)
for (j=0; j<wid-1; j++,sp+=2,dp+=12)
WORD(dp)=WORD(dp+2)=WORD(dp+4)=WORD(dp+6)=
WORD(dp+8)=WORD(dp+10)=WORD(sp);
else if (zoom==7)
for (j=0; j<wid-1; j++,sp+=2,dp+=14)
WORD(dp)=WORD(dp+2)=WORD(dp+4)=WORD(dp+6)=
WORD(dp+8)=WORD(dp+10)=WORD(dp+12)=WORD(sp);
else if (zoom==8)
for (j=0; j<wid-1; j++,sp+=2,dp+=16)
WORD(dp)=WORD(dp+2)=WORD(dp+4)=WORD(dp+6)=
WORD(dp+8)=WORD(dp+10)=WORD(dp+12)=WORD(dp+14)=WORD(sp);
// SCRBITMAP 側の右端のドットだけ特別扱い
for (j=0; j<dcnt; j++,dp+=2)
WORD(dp)=WORD(sp);
}
else if (pic->pixelsize == 16 && bm->pixelsize == 24)
{
for (int j=0; j<wid-1; j++,sp+=2)
{
int r,g,b;
GETRGB31(WORD(sp),r,g,b);
r=_31_255[r]; g=_31_255[g], b=_31_255[b];
for (int k=0; k<zoom; k++,dp+=3)
dp[0]=r,dp[1]=g,dp[2]=b;
}
int r,g,b;
GETRGB31(WORD(sp),r,g,b);
r=_31_255[r]; g=_31_255[g], b=_31_255[b];
for (int k=0; k<dcnt; k++,dp+=3)
dp[0]=r,dp[1]=g,dp[2]=b;
}
else if (pic->pixelsize == 24 && bm->pixelsize == 16)
{
for (int j=0; j<wid-1; j++,sp+=3)
{
int r,g,b;
r=sp[0],g=sp[1],b=sp[2];
r>>=3,g>>=3,b>>=3;
for (int k=0; k<zoom; k++,dp+=2)
SETRGB31(WORD(dp), r,g,b);
}
int r,g,b;
r=sp[0],g=sp[1],b=sp[2];
r>>=3,g>>=3,b>>=3;
for (int k=0; k<dcnt; k++,dp+=2)
SETRGB31(WORD(dp), r,g,b);
}
else if (pic->pixelsize == 24 && bm->pixelsize == 24)
{
for (int j=0; j<wid-1; j++,sp+=3)
{
for (int k=0; k<zoom; k++,dp+=3)
dp[0]=sp[0],dp[1]=sp[1],dp[2]=sp[2];
}
for (int k=0; k<dcnt; k++,dp+=3)
dp[0]=sp[0],dp[1]=sp[1],dp[2]=sp[2];
}
// 縦方向にひきのばす
int t = dxcnt * bm->pixelsize / 8;
for (int j=1; j < zoom && dy+j < bm->ht; j++)
memcpy(dp0+dxbytes*j, dp0, t);
}
}
/*--------------------------------------------------------*/
/* ピクセル値 */
/*--------------------------------------------------------*/
void pixel_setRgb(PIXEL *pixel, int r, int g, int b)
{
pixel->r = (r < 0 ? 0 : r > 255 ? 255 : r);
pixel->g = (g < 0 ? 0 : g > 255 ? 255 : g);
pixel->b = (b < 0 ? 0 : b > 255 ? 255 : b);
}
void pixel_getRgb(PIXEL *pixel, int *r, int *g, int *b)
{
*r = pixel->r;
*g = pixel->g;
*b = pixel->b;
}
void pic_copy(PIC* picSrc, FRAME* frSrc, PIC* picDest, POINT* ptDest)
// frSrc:(x,y,wid,ht)
// update 管理を忘れないこと!
{
int i;
if (frSrc->Y >= ptDest->y)
{
for (i=0; i<frSrc->HT; i++)
{
int sy = frSrc->Y+i;
int dy = ptDest->y+i;
if (sy < 0 || dy < 0)
continue;
if (sy >= picSrc->ht || dy >= picDest->ht)
break;
char *sp = picSrc->buf + PICOFFSET(picSrc,frSrc->X,frSrc->Y+i);
char *dp = picDest->buf + PICOFFSET(picDest,ptDest->x,ptDest->y+i);
int wid = _max(0,_min(frSrc->WID,
picSrc->wid - frSrc->X,
picDest->wid - ptDest->x));
if (wid == 0)
break;
if (picSrc->pixelsize == picDest->pixelsize)
memcpy(dp, sp, wid * picSrc->pixelsize / 8);
else if (picSrc->pixelsize == 16 && picDest->pixelsize == 24)
{
for (int j=0; j<wid; j++,dp+=3,sp+=2)
{ int r,g,b; GETRGB31(WORD(sp), r,g,b);
dp[0]=_31_255[r],dp[1]=_31_255[g],dp[2]=_31_255[b]; }
}
else if (picSrc->pixelsize == 24 && picDest->pixelsize == 16)
{
for (int j=0; j<wid; j++,dp+=2,sp+=3)
SETRGB31(WORD(dp),sp[0]>>3,sp[1]>>3,sp[2]>>3);
}
}
}
else
{
for (i=0; i<frSrc->HT; i++)
{
int sy = frSrc->Y+frSrc->HT-1-i;
int dy = ptDest->y+frSrc->HT-1-i;
if (sy < 0 || dy < 0)
break;
if (sy >= picSrc->ht || dy >= picDest->ht)
continue;
char *sp = picSrc->buf + PICOFFSET(picSrc,frSrc->X,frSrc->Y+i);
char *dp = picDest->buf + PICOFFSET(picDest,ptDest->x,ptDest->y+i);
int wid = _max(0,_min(frSrc->WID,
picSrc->wid - frSrc->X,
picDest->wid - ptDest->x));
if (wid == 0)
break;
if (picSrc->pixelsize == picDest->pixelsize)
memcpy(dp, sp, wid * picSrc->pixelsize / 8);
else if (picSrc->pixelsize == 16 && picDest->pixelsize == 24)
{
for (int j=0; j<wid; j++,dp+=3,sp+=2)
{ int r,g,b; GETRGB31(WORD(sp), r,g,b);
dp[0]=_31_255[r],dp[1]=_31_255[g],dp[2]=_31_255[b]; }
}
else if (picSrc->pixelsize == 24 && picDest->pixelsize == 16)
{
for (int j=0; j<wid; j++,dp+=2,sp+=3)
SETRGB31(WORD(dp),sp[0]>>3,sp[1]>>3,sp[2]>>3);
}
}
}
pic_updateRect(picDest, ptDest->x, ptDest->y, frSrc->WID, frSrc->HT);
}
void pic_paint(PIC *pic, int x,int y, PIXEL* pix)
{
PIXEL pixBack;
#define ISBACK(pix) \
((pix).r==pixBack.r && (pix).g==pixBack.g && (pix).b==pixBack.b)
pic_getPixelXy(pic,x,y,&pixBack);
if (ISBACK(*pix))
return;
int mix = pensel_getmix();
void hline(int x1,int x2,int y)
{
pic_grayhline(pic,x1,x2,y,mix,pix);
}
BOOL shouldPaint(int x,int y)
{
PIXEL pix;
pic_getPixelXy(pic,x,y,&pix);
if (ISBACK(pix))
return TRUE;
else
return FALSE;
}
int srchleft(int x,int y)
{
int sx1;
PIXEL pix;
for (sx1=x; sx1 > 0; sx1--)
{
pic_getPixelXy(pic,sx1-1,y,&pix);
if (!ISBACK(pix))
break;
}
return sx1;
}
int srchright(int x,int y)
{
int sx2;
PIXEL pix;
for (sx2=x; sx2 < pic->wid-1; sx2++)
{
pic_getPixelXy(pic,sx2+1,y,&pix);
if (!ISBACK(pix))
break;
}
return sx2;
}
do_paint(x,y,pic->wid,pic->ht,hline,shouldPaint,srchleft,srchright);
}
void pic_blot(PIC *pic,int x,int y,int branch,int depth,PIXEL* pix)
{
uint mix = pensel_getmix();
void pset(int x,int y,int gray)
{
pic_grayPset(pic,x,y,(gray*mix+127)/255,pix);
}
do_blot(x,y,branch,depth,pset);
}
void pic_polygon(PIC* pic,POINT* points,int nPoint,PIXEL* pix)
{
int mix = pensel_getmix();
void hline(int x1,int x2,int y)
{
pic_grayhline(pic,x1,x2,y,mix,pix);
}
do_polygon(points,nPoint,hline);
}
void pic_copyarea(PIC* picSrc, AREA areaSrc, PIC* picDest, POINT* ptDest)
{
void hline(int x1,int x2,int y)
{
char *sp = PICADDR(picSrc,x1,y);
char *dp = PICADDR(picDest,
ptDest->x + (x1 - areaSrc->x), ptDest->y + (y - areaSrc->y));
int wid = _max(0,_min( x2-x1+1,
picSrc->wid - areaSrc->x,
picDest->wid - ptDest->x));
if (wid == 0)
return;
if (picSrc->pixelsize == picDest->pixelsize)
memcpy(dp, sp, wid * picSrc->pixelsize / 8);
else if (picSrc->pixelsize == 16 && picDest->pixelsize == 24)
{
for (int j=0; j<wid; j++,dp+=3,sp+=2)
{ int r,g,b; GETRGB31(WORD(sp), r,g,b);
dp[0]=_31_255[r],dp[1]=_31_255[g],dp[2]=_31_255[b]; }
}
else if (picSrc->pixelsize == 24 && picDest->pixelsize == 16)
{
for (int j=0; j<wid; j++,dp+=2,sp+=3)
SETRGB31(WORD(dp),sp[0]>>3,sp[1]>>3,sp[2]>>3);
}
}
if (areaSrc->y >= ptDest->y)
{
for (int i=0; i<areaSrc->ht; i++)
{
int sy = areaSrc->y + i;
int dy = ptDest->y + i;
if (sy < 0 || dy < 0)
continue;
if (sy >= picSrc->ht || dy >= picDest->ht)
break;
area_forEachSect(areaSrc,sy,hline);
}
}
else
{
for (int i=0; i<areaSrc->ht; i++)
{
int sy = areaSrc->y + areaSrc->ht - 1 - i;
int dy = ptDest->y + areaSrc->ht - 1 - i;
if (sy < 0 || dy < 0)
break;
if (sy >= picSrc->ht || dy >= picDest->ht)
continue;
area_forEachSect(areaSrc,sy,hline);
}
}
pic_updateRect(picDest, ptDest->x, ptDest->y, areaSrc->wid, areaSrc->ht);
}
void pic_fillarea(PIC* pic,AREA area,PIXEL* pix)
{
int mix = pensel_getmix();
void hline(int x1,int x2,int y)
{
pic_grayhline(pic,x1,x2,y,mix,pix);
}
for (int i=0; i<area->ht; i++)
{
int sy = area->y + i;
if (sy < 0)
continue;
if (sy >= pic->ht)
break;
area_forEachSect(area, sy, hline);
}
pic_updateRect(pic, area->x, area->y, area->wid, area->ht);
}