home *** CD-ROM | disk | FTP | other *** search
/ Phoenix Heaven Sunny 2 / APPARE2.BIN / oh_towns / art2 / src.lzh / PIC.C < prev    next >
C/C++ Source or Header  |  1995-06-19  |  29KB  |  1,057 lines

  1. /*====================================================
  2.                       ARTemis
  3.                    (version 1.3)
  4.              FM-TOWNS 用ペイントツール
  5.  
  6.                  by 松内 良介 1994
  7. ====================================================*/
  8. #if 0
  9.     pic.c : 「画像」
  10.  
  11.     pic_init
  12.     
  13.     pic_new(wid,ht)
  14.     pic_destroy(pic)
  15.     pic_dup(pic)
  16.  
  17.     static void pic_updatePoint(PIC* pic,int x,int y)
  18.     static void pic_updateRect(PIC* pic, int x,int y,int wid,int ht)
  19.  
  20.     pic_setPixelXy(pic,x,y,pixel)    1ピクセルの色を設定
  21.     pic_getPixelXy(pic,x,y,pixel)    1ピクセルの色を取得
  22. void pic_grayPset(PIC* pic,int x,int y,int gray,PIXEL *pixel);
  23. void pic_psetpen(PIC *pic,int x,int y,Pen pen,PIXEL *pixel);
  24. void pic_grayhline(PIC *pic,int x1,int x2,int y,int gray,PIXEL *pixel);
  25. void pic_clear(PIC *pic, PIXEL *pixel);
  26. void pic_kosuriStart(PIC* pic,int x,int y,char* graypat,int wid,int ht);
  27. void pic_kosuriDrag(PIC* pic,int x,int y,int r);
  28.  
  29.     void pic_copy(PIC* picSrc, FRAME* frSrc, PIC* picDest, POINT* ptDest);
  30.     void pic_copyarea(PIC* picSrc, AREA areaSrc, PIC* picDest, POINT* ptDest);
  31.     void pic_paint(PIC *pic, int x,int y, PIXEL* pix);
  32.     void pic_blot(PIC *pic,int x,int y,PIXEL* pix,int branch,int depth)
  33.     void pic_diffusePen(PIC* pic,int x,int y,Pen pen);
  34.     void pic_sandPen(PIC* pic,int x,int y,Pen pen);
  35.     void pic_polygon(PIC* pic,POINT* points,int nPoint,PIXEL* pix);
  36.     void pic_fillarea(PIC* pic,AREA area,PIXEL* pix);
  37.  
  38.     pic_beginUpDate(pic)        更新領域のクリア
  39.     pic_endUpDate(pic,frame)    更新終了;更新領域の取得
  40.  
  41.     pic_loadTIFF_
  42.     pic_saveTIFF_
  43.     pic_getRectImage(pic,buf,frame)
  44.     void pic_getScrBitMap(PIC* pic,SCRBITMAP bm,int ofsx,int ofsy, FRAME *fr);
  45.         // 画像内の fr の領域を bm の ofsx, ofsy に転送する
  46.  
  47.     pixel_setRgb(pixel, r,g,b)
  48.     pixel_getRgb(pixel, r,g,b)
  49. #endif
  50.  
  51. #define    MODULE_PIC
  52.  
  53. #include <stdio.h>
  54. #include <stdlib.h>
  55. #include <string.h>
  56. #include <winb.h>
  57. #include <memory.h>
  58. #include <te.h>
  59. #include <fntb.h>
  60. #include <gui.h>
  61. #include <egb.h>
  62.  
  63. #include "art.h"
  64. #include "pic.h"
  65. #include "subgrp.h"
  66. #include "guisub.h"
  67. #include "pensel.h"
  68.  
  69. static char* tempBuf = NULL;
  70.  
  71.             static uint _31_255[] =
  72.                 {  0,8,16,25, 33,41,49,58, 66,74,82,90, 99,107,115,123,
  73.                    132,140,148,156, 165,173,181,189, 197,206,214,222, 
  74.                    230,239,247,255};
  75.  
  76. int        pic_init(void)
  77. {
  78.     return 0;
  79. }
  80.  
  81. void    pic_close(void)
  82. {
  83. }
  84.  
  85. PIC        *pic_new(int pixelsize, int wid,int ht)
  86. {
  87.     PIC *pic;
  88.     if ((pic = TL_calloc(1, sizeof(PIC))) == NULL)
  89.         return NULL;
  90.     if ((pic->buf = TL_calloc(1,wid*ht*pixelsize/8)) == NULL)
  91.         { TL_free(pic);  return NULL; }
  92.     memset(pic->buf, 0xff, wid*ht*pixelsize/8);
  93.     pic->wid  = wid;
  94.     pic->ht = ht;
  95.     pic->pixelsize = pixelsize;
  96.     return pic;
  97. }
  98.  
  99. PIC* pic_dup(PIC* pic)
  100. {
  101.     PIC* newpic;
  102.     if ((newpic = TL_calloc(1,sizeof(PIC))) == NULL)
  103.         return NULL;
  104.     if ((newpic->buf = TL_calloc(1,pic->pixelsize*pic->wid*pic->ht/8)) == NULL)
  105.         { TL_free(newpic);  return NULL; }
  106.     memcpy(newpic->buf, pic->buf, pic->wid*pic->ht*pic->pixelsize/8);
  107.     newpic->wid = pic->wid;
  108.     newpic->ht = pic->ht;
  109.     newpic->pixelsize = pic->pixelsize;
  110.     return newpic;
  111. }
  112.  
  113. void    pic_destroy(PIC *pic)
  114. {
  115.     TL_free(pic->buf);
  116.     TL_free(pic);
  117. }
  118.  
  119. /*--------------------------------------------------------*/
  120. /*                   PIC更新情報の更新                    */
  121. /*--------------------------------------------------------*/
  122.  
  123. static void pic_updatePoint(PIC* pic,int x,int y)
  124. {
  125.     if (pic->update.lupx < 0)
  126.     {
  127.         pic->update.lupx = pic->update.rdwx = x;
  128.         pic->update.lupy = pic->update.rdwy = y;
  129.     }
  130.     else
  131.     {
  132.         if (x < pic->update.lupx)
  133.             pic->update.lupx = x;
  134.         else if (pic->update.rdwx < x)
  135.             pic->update.rdwx = x;
  136.         if (y < pic->update.lupy)
  137.             pic->update.lupy = y;
  138.         else if (pic->update.rdwy < y)
  139.             pic->update.rdwy = y;
  140.     }
  141. }
  142.  
  143. static void pic_updateRect(PIC* pic, int x,int y,int wid,int ht)
  144. {
  145.   // 内容変更領域を更新
  146.     int left,top,right,bottom;
  147.     left = _max(0,x);
  148.     right = _min(pic->wid-1,x+wid-1);
  149.     top = _max(0,y);
  150.     bottom = _min(pic->ht-1,y+ht-1);
  151.     if (pic->update.X < 0)
  152.     {
  153.         pic->update.X = left;
  154.         pic->update.X2 = right;
  155.         pic->update.Y = top;
  156.         pic->update.Y2 = bottom;
  157.     }
  158.     else
  159.     {
  160.         #define R    (pic->update)
  161.         R.X = _min(R.X, left);
  162.         R.X2 = _max(R.X2, right);
  163.         R.Y = _min(R.Y, top);
  164.         R.Y2 = _max(R.Y2, bottom);
  165.         #undef R
  166.     }
  167. }
  168.  
  169. /*--------------------------------------------------------*/
  170. /*                ピクセルの色の設定・取得                */
  171. /*--------------------------------------------------------*/
  172.  
  173. void    pic_setPixelXy(PIC *pic, int x, int y, PIXEL *pixel)
  174. /* 1ピクセルの色を設定 */
  175. {
  176.     if (x < 0 || pic->wid<=x || y < 0 || pic->ht<=y)
  177.         return;
  178.     if (pic->pixelsize == 16)
  179.         *(unsigned short*)&pic->buf[(pic->wid * y + x) * 2] = CODE32K(*pixel);
  180.     else
  181.     {
  182.         char *p = PICADDR(pic,x,y);
  183.         uint col = CODE16M(*pixel);
  184.         SETBYTE3(p,col);
  185.     }
  186.     pic_updatePoint(pic, x,y);
  187. }
  188.  
  189. void pic_grayPset(PIC* pic,int x,int y,int gray,PIXEL* pixel)
  190. {
  191.     if (x < 0 || pic->wid<=x || y < 0 || pic->ht<=y)
  192.         return;
  193.     if (pic->pixelsize == 16)
  194.     {
  195.         ushort* p = (ushort*)PICADDR(pic,x,y);
  196.         int col = CODE32K(*pixel);
  197.         int sr,sg,sb,dr,dg,db;
  198.         GETRGB31(*p, dr,dg,db);
  199.         GETRGB31(col, sr,sg,sb);
  200.         dr = (dr * (255-gray) + sr * gray) / 255;
  201.         dg = (dg * (255-gray) + sg * gray) / 255;
  202.         db = (db * (255-gray) + sb * gray) / 255;
  203.         SETRGB31(*p, dr,dg,db);
  204.     }
  205.     else
  206.     {
  207.         char* p = PICADDR(pic,x,y);
  208.         int sr,sg,sb,dr,dg,db;
  209.         sr=pixel->r,sg=pixel->g,sb=pixel->b;
  210.         dr=p[0],dg=p[1],db=p[2];
  211.         dr = (dr * (255-gray) + sr * gray) / 255;
  212.         dg = (dg * (255-gray) + sg * gray) / 255;
  213.         db = (db * (255-gray) + sb * gray) / 255;
  214.         p[0]=dr,p[1]=dg,p[2]=db;
  215.     }
  216.     pic_updatePoint(pic, x,y);
  217. }
  218.  
  219. void    pic_getPixelXy(PIC *pic, int x, int y, PIXEL *pixel)
  220. /* 1ピクセルの色を取得 */
  221. {
  222.     if (x < 0 || pic->wid<=x || y < 0 || pic->ht<=y)
  223.         return;
  224.     if (pic->pixelsize == 16)
  225.     {
  226.         int col = *(unsigned short*)&pic->buf[(pic->wid * y + x) * 2];
  227.         int r,g,b;
  228.         GETRGB31(col,r,g,b);
  229.         pixel->r = _31_255[r];
  230.         pixel->g = _31_255[g];
  231.         pixel->b = _31_255[b];
  232.     }
  233.     else
  234.     {
  235.         char *p = PICADDR(pic,x,y);
  236.         pixel->r = p[0];
  237.         pixel->g = p[1];
  238.         pixel->b = p[2];
  239.     }
  240. }
  241.  
  242. /*--------------------------------------------------------*/
  243. /*                     濃度分布の描画                     */
  244. /*--------------------------------------------------------*/
  245.  
  246. void pic_psetpen(PIC *pic,int x,int y,Pen pen,PIXEL *pixel)
  247. {
  248.     uint mix = pensel_getmix();
  249.     x -= pen->ofsx;
  250.     y -= pen->ofsy;
  251.     for (int i=0; i<pen->ht; i++)
  252.     {
  253.         int dy = y + i;
  254.         if (dy < 0 || pic->ht <= dy)
  255.             continue;
  256.         char *penp = pen->buf + pen->wid * i;
  257.         if (pic->pixelsize == 16)
  258.         {
  259.             char *dp = PICADDR(pic,x,dy);
  260.             int col = CODE32K(*pixel);
  261.             int sr,sg,sb,dr,dg,db;
  262.             GETRGB31(col,sr,sg,sb);
  263.             for (int j=0; j<pen->wid; j++,dp+=2,penp++)
  264.             {
  265.                 if (*penp == 0 || x+j < 0 || pic->wid <= x+j)
  266.                     continue;
  267.                 uint mr = (mix * (*penp) + 127) / 255;
  268.                 GETRGB31(WORD(dp),dr,dg,db);
  269.                 dr = (dr * (255-mr) + sr * (uint)mr + 127)/255;
  270.                 dg = (dg * (255-mr) + sg * (uint)mr + 127)/255;
  271.                 db = (db * (255-mr) + sb * (uint)mr + 127)/255;
  272.                 SETRGB31(WORD(dp),dr,dg,db);
  273.             }
  274.         }
  275.         else
  276.         {
  277.             char *dp = PICADDR(pic,x,dy);
  278.             int sr,sg,sb,dr,dg,db;
  279.             sr=pixel->r,sg=pixel->g,sb=pixel->b;
  280.             for (int j=0; j<pen->wid; j++,dp+=3,penp++)
  281.             {
  282.                 if (*penp == 0 || x+j < 0 || pic->wid <= x+j)
  283.                     continue;
  284.                 uint mr = (mix * (*penp) + 127) / 255;
  285.                 dr=dp[0],dg=dp[1],db=dp[2];
  286.                 dr = (dr * (255-mr) + sr * (uint)mr + 127)/255;
  287.                 dg = (dg * (255-mr) + sg * (uint)mr + 127)/255;
  288.                 db = (db * (255-mr) + sb * (uint)mr + 127)/255;
  289.                 dp[0]=dr,dp[1]=dg,dp[2]=db;
  290.             }
  291.         }
  292.     }
  293.     pic_updateRect(pic,x,y,pen->wid,pen->ht);
  294. }
  295.  
  296. /*--------------------------------------------------------*/
  297. /*                     水平直線の描画                     */
  298. /*--------------------------------------------------------*/
  299.  
  300. void pic_grayhline(PIC *pic,int x1,int x2,int y,int gray,PIXEL *pixel)
  301. {
  302.     if (x1 >= x2)
  303.         SWAP_INT(x1,x2)
  304.     if (y < 0 || pic->ht <= y)
  305.         return;
  306.     x1 = _max(0,x1);
  307.     x2 = _min(pic->wid-1,x2);
  308.     if (x2 < x1)
  309.         return;
  310.     if (pic->pixelsize == 16)
  311.     {
  312.         char *dp = PICADDR(pic,x1,y);
  313.         ushort col = CODE32K(*pixel);
  314.         if (gray >= 255)
  315.         {
  316.             for (int i=x1; i<=x2; i++,dp+=2)
  317.                 WORD(dp) = col;
  318.         }
  319.         else if (gray > 0)
  320.         {
  321.             int sr,sg,sb,dr,dg,db;
  322.             int igray = 255 - gray;
  323.             GETRGB31(col, sr,sg,sb);
  324.             for (int i=x1; i<=x2; i++,dp+=2)
  325.             {
  326.                 GETRGB31(WORD(dp), dr,dg,db);
  327.                 dr = (dr * igray + sr * gray + 128) / 255;
  328.                 dg = (dg * igray + sg * gray + 128) / 255;
  329.                 db = (db * igray + sb * gray + 128) / 255;
  330.                 SETRGB31(WORD(dp), dr,dg,db);
  331.             }
  332.         }
  333.     }
  334.     else if (pic->pixelsize == 24)
  335.     {
  336.         char *dp = PICADDR(pic,x1,y);
  337.         if (gray >= 255)
  338.         {
  339.             for (int i=x1; i<=x2; i++,dp+=3)
  340.                 dp[0]=pixel->r,dp[1]=pixel->g,dp[2]=pixel->b;
  341.         }
  342.         else if (gray > 0)
  343.         {
  344.             int sr,sg,sb,dr,dg,db;
  345.             sr=pixel->r,sg=pixel->g,sb=pixel->b;
  346.             int igray = 255 - gray;
  347.             for (int i=x1; i<=x2; i++,dp+=3)
  348.             {
  349.                 dr=dp[0],dg=dp[1],db=dp[2];
  350.                 dr = (dr * igray + sr * (uint)gray + 127)/255;
  351.                 dg = (dg * igray + sg * (uint)gray + 127)/255;
  352.                 db = (db * igray + sb * (uint)gray + 127)/255;
  353.                 dp[0]=dr,dp[1]=dg,dp[2]=db;
  354.             }
  355.         }
  356.     }
  357.     pic_updateRect(pic,x1,y,x2-x1+1,1);
  358. }
  359.  
  360. /*--------------------------------------------------------*/
  361. /*                         クリア                         */
  362. /*--------------------------------------------------------*/
  363.  
  364. void    pic_clear(PIC *pic, PIXEL *pixel)
  365. {
  366.     int i;
  367.     for (i = 0; i < pic->ht; i++)
  368.         pic_grayhline(pic, 0, pic->wid-1, i, 255, pixel);
  369. }
  370.  
  371. /*--------------------------------------------------------*/
  372. /*                       こすり処理                       */
  373. /*--------------------------------------------------------*/
  374.  
  375. char *kosuri_graypat;
  376. int kosuri_x, kosuri_y;
  377. int kosuri_wid,kosuri_ht;
  378.  
  379. void pic_kosuriStart(PIC* pic,int x,int y,char* graypat,int wid,int ht)
  380. // x,y : ペンの左上端の PIC 座標
  381. // graypat : ペンの濃度デ-タ
  382. // wid,ht : ペンの大きさ
  383. {
  384.     kosuri_graypat = graypat;
  385.     kosuri_x = x;
  386.     kosuri_y = y;
  387.     kosuri_wid = wid;
  388.     kosuri_ht = ht;
  389.     if (tempBuf != NULL)
  390.         TL_free(tempBuf);
  391.     tempBuf = TL_calloc(1,pic->pixelsize*kosuri_wid*kosuri_ht/8);
  392. }
  393.  
  394. void pic_kosuriDrag(PIC* pic,int x,int y,int r)
  395. // x,y : ペンの左上端の PIC 座標
  396. // r : こすり強さ (0~255)
  397. {
  398.     if (tempBuf == NULL)
  399.         return;
  400.     int i,j;
  401.   // 前のペンの位置の色を tempBuf に格納
  402.     char *p = kosuri_graypat;
  403.     for (i=0; i<kosuri_ht; i++)
  404.     {
  405.         if (kosuri_y+i < 0)
  406.             continue;
  407.         else if (kosuri_y+i >= pic->ht)
  408.             break;
  409.         char *ptrpic;
  410.         ptrpic = pic->buf + PICOFFSET(pic,kosuri_x,kosuri_y+i);
  411.         char *ptrbuf;
  412.         ptrbuf = tempBuf + (kosuri_wid*i) * pic->pixelsize/8;
  413.         if (pic->pixelsize == 16)
  414.         {
  415.             for (j=0; j<kosuri_wid; j++,p++,ptrpic+=2,ptrbuf+=2)
  416.             {
  417.                 if (kosuri_x+j < 0)
  418.                     continue;
  419.                 else if (kosuri_x+j >= pic->wid)
  420.                     break;
  421.                 if (*p == 0)
  422.                     continue;
  423.                 WORD(ptrbuf) = WORD(ptrpic);
  424.             }
  425.         }
  426.         else
  427.         {
  428.             for (j=0; j<kosuri_wid; j++,p++,ptrpic+=3,ptrbuf+=3)
  429.             {
  430.                 if (kosuri_x+j < 0)
  431.                     continue;
  432.                 else if (kosuri_x+j >= pic->wid)
  433.                     break;
  434.                 if (*p == 0)
  435.                     continue;
  436.                 WORD(ptrbuf) = WORD(ptrpic);
  437.                 BYTE(ptrbuf+2) = BYTE(ptrpic+2);
  438.             }
  439.         }
  440.     }
  441.   // 新しいペンの位置と色をまぜあわせる
  442.     p = kosuri_graypat;
  443.     for (i=0; i<kosuri_ht; i++)
  444.     {
  445.         if (y+i < 0)
  446.             continue;
  447.         else if (y+i >= pic->ht)
  448.             break;
  449.         char *ptrpic;
  450.         ptrpic = pic->buf + PICOFFSET(pic,x,y+i);
  451.         char *ptrbuf;
  452.         ptrbuf = tempBuf + (kosuri_wid*i) * pic->pixelsize/8;
  453.         if (pic->pixelsize == 16)
  454.         {
  455.             for (j=0; j<kosuri_wid; j++,p++,ptrpic+=2,ptrbuf+=2)
  456.             {
  457.                 if (x+j < 0)
  458.                     continue;
  459.                 else if (x+j >= pic->wid)
  460.                     break;
  461.                 if (*p == 0)
  462.                     continue;
  463.                 unsigned int sc,dc, sr,sg,sb,dr,dg,db,tr,tg,tb;
  464.                 sc = WORD(ptrbuf);
  465.                 dc = WORD(ptrpic);
  466.                 sr=(sc>>5)&31,sg=(sc>>10)&31,sb=sc&31;
  467.                 dr=(dc>>5)&31,dg=(dc>>10)&31,db=dc&31;
  468.                 tr = (sr*r+dr*(255-r)+127)/255;
  469.                 tg = (sg*r+dg*(255-r)+127)/255;
  470.                 tb = (sb*r+db*(255-r)+127)/255;
  471.                 WORD(ptrpic) = (tg<<10)|(tr<<5)|tb;
  472.                 tr = (sr*(255-r)+dr*r+127)/255;
  473.                 tg = (sg*(255-r)+dg*r+127)/255;
  474.                 tb = (sb*(255-r)+db*r+127)/255;
  475.                 WORD(ptrbuf) = (tg<<10)|(tr<<5)|tb;
  476.             }
  477.         }
  478.         else
  479.         {
  480.             for (j=0; j<kosuri_wid; j++,p++,ptrpic+=3,ptrbuf+=3)
  481.             {
  482.                 if (x+j < 0)
  483.                     continue;
  484.                 else if (x+j >= pic->wid)
  485.                     break;
  486.                 if (*p == 0)
  487.                     continue;
  488.                 unsigned int sr,sg,sb,dr,dg,db,tr,tg,tb;
  489.                 sr=ptrbuf[0],sg=ptrbuf[1],sb=ptrbuf[2];
  490.                 dr=ptrpic[0],dg=ptrpic[1],db=ptrpic[2];
  491.                 tr = (sr*r+dr*(255-r)+127)/255;
  492.                 tg = (sg*r+dg*(255-r)+127)/255;
  493.                 tb = (sb*r+db*(255-r)+127)/255;
  494.                 ptrpic[0]=tr,ptrpic[1]=tg,ptrpic[2]=tb;
  495.                 tr = (sr*(255-r)+dr*r+127)/255;
  496.                 tg = (sg*(255-r)+dg*r+127)/255;
  497.                 tb = (sb*(255-r)+db*r+127)/255;
  498.                 ptrbuf[0]=tr,ptrbuf[1]=tg,ptrbuf[2]=tb;
  499.             }
  500.         }
  501.     }
  502.     pic_updateRect(pic, x,y,kosuri_wid,kosuri_ht);
  503.   // 次のこすりドラッグ
  504.     kosuri_x = x;
  505.     kosuri_y = y;
  506. }
  507.  
  508. /*--------------------------------------------------------*/
  509. /*                      ペン先ぼかし                      */
  510. /*--------------------------------------------------------*/
  511.  
  512. void pic_diffusePen(PIC* pic,int x,int y,Pen pen)
  513. {
  514.     int picxbytes = pic->wid * pic->pixelsize / 8;
  515.     int picy = y - pen->ofsy;
  516.     for (int i=0; i<pen->ht; i++,picy++)
  517.     {
  518.         if (picy < 0 || pic->ht <= picy)
  519.             continue;
  520.         int picx = x - pen->ofsx;
  521.         char* penp = pen->buf + PENOFFSET(pen,0,i);
  522.         char* picp = pic->buf + PICOFFSET(pic,picx,picy);
  523.         if (pic->pixelsize == 16)
  524.         {
  525.             for (int j=0; j<pen->wid; j++,picx++,penp++,picp+=2)
  526.             {
  527.                 if (*penp == 0 || picx < 0 || pic->wid <= picx)
  528.                     continue;
  529.                 #define DIF 6
  530.                 uint r,g,b;
  531.                 uint sum,rsum,gsum,bsum;  sum=rsum=gsum=bsum=0;
  532.                 GETRGB31(WORD(picp),r,g,b);
  533.                 rsum+=r*DIF;  gsum+=g*DIF;  bsum+=b*DIF;  sum+=DIF;
  534.                 if (picy-1 >= 0)
  535.                   { GETRGB31(WORD(picp-picxbytes),r,g,b);
  536.                     rsum+=r,gsum+=g,bsum+=b,sum++; }
  537.                 if (picy+1 < pic->ht)
  538.                   { GETRGB31(WORD(picp+picxbytes),r,g,b);
  539.                     rsum+=r,gsum+=g,bsum+=b,sum++; }
  540.                 if (picx-1 >= 0)
  541.                   { GETRGB31(WORD(picp-2),r,g,b);
  542.                     rsum+=r,gsum+=g,bsum+=b,sum++; }
  543.                 if (picx+1 < pic->wid)
  544.                   { GETRGB31(WORD(picp+2),r,g,b);
  545.                     rsum+=r,gsum+=g,bsum+=b,sum++; }
  546.                 rsum = (rsum+sum/2) / sum;
  547.                 gsum = (gsum+sum/2) / sum;
  548.                 bsum = (bsum+sum/2) / sum;
  549.                 SETRGB31(WORD(picp),rsum,gsum,bsum);
  550.                 #undef DIF
  551.             }
  552.         }
  553.         else
  554.         {
  555.             for (int j=0; j<pen->wid; j++,picx++,penp++,picp+=3)
  556.             {
  557.                 if (*penp == 0 || picx < 0 || pic->wid <= picx)
  558.                     continue;
  559.                 #define DIF 6
  560.                 uint r,g,b;
  561.                 uint sum,rsum,gsum,bsum;  sum=rsum=gsum=bsum=0;
  562.                 r=picp[0],g=picp[1],b=picp[2];
  563.                 rsum+=r*DIF;  gsum+=g*DIF;  bsum+=b*DIF;  sum+=DIF;
  564.                 if (picy-1 >= 0)
  565.                   { GET3BYTE(picp-picxbytes,r,g,b);
  566.                     rsum+=r,gsum+=g,bsum+=b,sum++; }
  567.                 if (picy+1 < pic->ht)
  568.                   { GET3BYTE(picp+picxbytes,r,g,b);
  569.                     rsum+=r,gsum+=g,bsum+=b,sum++; }
  570.                 if (picx-1 >= 0)
  571.                   { GET3BYTE(picp-3,r,g,b);
  572.                     rsum+=r,gsum+=g,bsum+=b,sum++; }
  573.                 if (picx+1 < pic->wid)
  574.                   { GET3BYTE(picp+3,r,g,b);
  575.                     rsum+=r,gsum+=g,bsum+=b,sum++; }
  576.                 rsum = (rsum+sum/2) / sum;
  577.                 gsum = (gsum+sum/2) / sum;
  578.                 bsum = (bsum+sum/2) / sum;
  579.                 picp[0]=rsum,picp[1]=gsum,picp[2]=bsum;
  580.                 #undef DIF
  581.             }
  582.         }
  583.     }
  584.     pic_updateRect(pic, x-pen->ofsx, y-pen->ofsy, pen->wid, pen->ht);
  585. }
  586.  
  587. void pic_sandPen(PIC* pic,int x,int y,Pen pen)
  588. {
  589.     int picxbytes = pic->wid * pic->pixelsize / 8;
  590.     int picy = y - pen->ofsy;
  591.     for (int i=0; i<pen->ht; i++,picy++)
  592.     {
  593.         if (picy < 0 || pic->ht <= picy)
  594.             continue;
  595.         int picx = x - pen->ofsx;
  596.         char* penp = pen->buf + PENOFFSET(pen,0,i);
  597.         char* picp = pic->buf + PICOFFSET(pic,picx,picy);
  598.         if (pic->pixelsize == 16)
  599.         {
  600.             for (int j=0; j<pen->wid; j++,picx++,penp++,picp+=2)
  601.             {
  602.                 if (*penp == 0 || picx < 0 || pic->wid <= picx)
  603.                     continue;
  604.                 #define DIF 6
  605.                 int r,g,b;
  606.                 GETRGB31(WORD(picp),r,g,b);
  607.                 r = _min(31,_max(0, r + rand() % 3 - 1));
  608.                 g = _min(31,_max(0, g + rand() % 3 - 1));
  609.                 b = _min(31,_max(0, b + rand() % 3 - 1));
  610.                 SETRGB31(WORD(picp),r,g,b);
  611.                 #undef DIF
  612.             }
  613.         }
  614.         else
  615.         {
  616.             for (int j=0; j<pen->wid; j++,picx++,penp++,picp+=3)
  617.             {
  618.                 if (*penp == 0 || picx < 0 || pic->wid <= picx)
  619.                     continue;
  620.                 int r,g,b;
  621.                 r=picp[0],g=picp[1],b=picp[2];
  622.                 r = _min(255,_max(0, r + (rand() % 13 - 6)));
  623.                 g = _min(255,_max(0, g + (rand() % 13 - 6)));
  624.                 b = _min(255,_max(0, b + (rand() % 13 - 6)));
  625.                 picp[0]=r,picp[1]=g,picp[2]=b;
  626.             }
  627.         }
  628.     }
  629.     pic_updateRect(pic, x-pen->ofsx, y-pen->ofsy, pen->wid, pen->ht);
  630. }
  631.  
  632. /*--------------------------------------------------------*/
  633. /*                    更新の開始・終了                    */
  634. /*--------------------------------------------------------*/
  635.  
  636. void    pic_beginUpDate(PIC *pic)
  637. {
  638.     pic->update.lupx = -1;
  639. }
  640.  
  641. void    pic_endUpDate(PIC *pic, FRAME *frame)
  642. {
  643.     pic->update.WID = pic->update.X2 - pic->update.X + 1;
  644.     pic->update.HT  = pic->update.Y2 - pic->update.Y + 1;
  645.     *frame = pic->update;
  646. }
  647.  
  648.     static PIC *_pic;
  649.     static TIFFINFO tiffinfo;
  650.  
  651.     static int putimage(char *buf, int ofsy, int ht)
  652.     {
  653.         for (int i=0; i<ht; i++)
  654.         {
  655.             if (ofsy+i >= _pic->ht)
  656.                 break;
  657.             char *dp = _pic->buf + PICOFFSET(_pic, 0, ofsy+i);
  658.             char *sp = buf + (tiffinfo.wid*tiffinfo.pixelsize/8)*i;
  659.             int wid = _min(_pic->wid, tiffinfo.wid);
  660.             int t = wid * _pic->pixelsize / 8;
  661.             memcpy(dp, sp, t);
  662.         }
  663.         return 0;
  664.     }
  665.  
  666.     static int getimage(char *buf,int ofsy,int ht)
  667.     {
  668.         for (int i=0; i<ht; i++)
  669.         {
  670.             if (ofsy+i >= _pic->ht)
  671.                 break;
  672.             char *dp = buf + (tiffinfo.wid*tiffinfo.pixelsize/8)*i;
  673.             char *sp = _pic->buf + PICOFFSET(_pic, 0, ofsy+i);
  674.             int wid = _min(_pic->wid, tiffinfo.wid);
  675.             int t = wid * _pic->pixelsize / 8;
  676.             memcpy(dp, sp, t);
  677.         }
  678.         return 0;
  679.     }
  680.  
  681. int pic_loadTIFF_(PIC *pic, char *fname)
  682. /* PIC構造体内に TIFF ファイルの画像をロードする */
  683. {
  684.     _pic = pic;
  685.     int ret;
  686.     if ((ret = RM_getTIFFinfo(fname, &tiffinfo)) != NOERR)
  687.         return ret;
  688.     ret = RM_loadTIFF(fname, putimage, (int(*)())0);
  689.     return ret;
  690. }
  691.  
  692. int pic_saveTIFF_(PIC *pic, char *fname)
  693. {
  694.     _pic = pic;
  695.     tiffinfo.wid = pic->wid;
  696.     tiffinfo.ht = pic->ht;
  697.     tiffinfo.pixelsize = pic->pixelsize;
  698.     int ret;
  699.     ret = RM_saveTIFF(fname, pic->pixelsize, pic->wid, pic->ht, TRUE,
  700.                       getimage, (int(*)())0);
  701.     return ret;
  702. }
  703.  
  704. void pic_getScrBitMap(PIC* pic,SCRBITMAP bm, int ofsx, int ofsy, FRAME *_fr,
  705.                       int zoom)
  706.     // 画像内の fr(x,y,wid,ht) の領域を bm の ofsx, ofsy に転送する
  707.     // 画面イメージへの変換を行う
  708. {
  709.     int i;
  710.     FRAME fr;
  711.     fr = *_fr;
  712.     if (ofsx < 0)
  713.         fr.X+=(-ofsx)/zoom, fr.WID-=(-ofsx)/zoom, ofsx=0;
  714.     if (ofsy < 0)
  715.         fr.Y+=(-ofsy)/zoom, fr.HT-=(-ofsy)/zoom, ofsy=0;
  716.     if (fr.WID <= 0 && fr.HT <= 0)
  717.         return;
  718.     int wid = _min(fr.WID, pic->wid - fr.X,
  719.               (bm->wid - ofsx + zoom-1) / zoom);
  720.         // ↑実際の転送ドット数
  721.     if (wid <= 0)
  722.         return;
  723.     int dcnt = _min(zoom, bm->wid - ofsx - (wid-1)*zoom);
  724.         // ↑SCRBITMAP側の右端のピクセルの横幅
  725.     int dxbytes = bm->wid * bm->pixelsize / 8;
  726.         // ↑SCRBITMAPの横バイト数
  727.     int dxcnt = (wid-1)*zoom + dcnt;
  728.         // ↑SCRBITMAP側の転送領域の横ピクセル数
  729.     for (i=0; i<fr.HT; i++)
  730.     {
  731.         int dy = ofsy + zoom * i;
  732.         int sy = fr.Y + i;
  733.         if (sy < 0 || pic->ht <= sy)
  734.             continue;
  735.         if (dy < 0 || bm->ht <= dy)
  736.             continue;
  737.         if (wid == 0)
  738.             break;
  739.         char *dp = bm->buf + BMOFFSET(bm, ofsx, dy);
  740.         char *dp0 = dp;
  741.         char *sp = pic->buf + PICOFFSET(pic, fr.X, sy);
  742.         if (zoom==1 && pic->pixelsize == 16 && bm->pixelsize == 16)
  743.             memcpy(dp,sp,wid * 2);
  744.         else if (pic->pixelsize == 16 && bm->pixelsize == 16)
  745.         {
  746.             int j;
  747.             if (zoom == 2)
  748.                 for (j=0; j<wid-1; j++,sp+=2,dp+=4)
  749.                     WORD(dp)=WORD(dp+2)=WORD(sp);
  750.             else if (zoom==3)
  751.                 for (j=0; j<wid-1; j++,sp+=2,dp+=6)
  752.                     WORD(dp)=WORD(dp+2)=WORD(dp+4)=WORD(sp);
  753.             else if (zoom==4)
  754.                 for (j=0; j<wid-1; j++,sp+=2,dp+=8)
  755.                     WORD(dp)=WORD(dp+2)=WORD(dp+4)=WORD(dp+6)=WORD(sp);
  756.             else if (zoom==5)
  757.                 for (j=0; j<wid-1; j++,sp+=2,dp+=10)
  758.                     WORD(dp)=WORD(dp+2)=WORD(dp+4)=WORD(dp+6)=
  759.                     WORD(dp+8)=WORD(sp);
  760.             else if (zoom==6)
  761.                 for (j=0; j<wid-1; j++,sp+=2,dp+=12)
  762.                     WORD(dp)=WORD(dp+2)=WORD(dp+4)=WORD(dp+6)=
  763.                     WORD(dp+8)=WORD(dp+10)=WORD(sp);
  764.             else if (zoom==7)
  765.                 for (j=0; j<wid-1; j++,sp+=2,dp+=14)
  766.                     WORD(dp)=WORD(dp+2)=WORD(dp+4)=WORD(dp+6)=
  767.                     WORD(dp+8)=WORD(dp+10)=WORD(dp+12)=WORD(sp);
  768.             else if (zoom==8)
  769.                 for (j=0; j<wid-1; j++,sp+=2,dp+=16)
  770.                     WORD(dp)=WORD(dp+2)=WORD(dp+4)=WORD(dp+6)=
  771.                     WORD(dp+8)=WORD(dp+10)=WORD(dp+12)=WORD(dp+14)=WORD(sp);
  772.             // SCRBITMAP 側の右端のドットだけ特別扱い
  773.             for (j=0; j<dcnt; j++,dp+=2)
  774.                 WORD(dp)=WORD(sp);
  775.         }
  776.         else if (pic->pixelsize == 16 && bm->pixelsize == 24)
  777.         {
  778.             for (int j=0; j<wid-1; j++,sp+=2)
  779.             {
  780.                 int r,g,b;
  781.                 GETRGB31(WORD(sp),r,g,b);
  782.                 r=_31_255[r]; g=_31_255[g], b=_31_255[b];
  783.                 for (int k=0; k<zoom; k++,dp+=3)
  784.                     dp[0]=r,dp[1]=g,dp[2]=b;
  785.             }
  786.             int r,g,b;
  787.             GETRGB31(WORD(sp),r,g,b);
  788.             r=_31_255[r]; g=_31_255[g], b=_31_255[b];
  789.             for (int k=0; k<dcnt; k++,dp+=3)
  790.                 dp[0]=r,dp[1]=g,dp[2]=b;
  791.         }
  792.         else if (pic->pixelsize == 24 && bm->pixelsize == 16)
  793.         {
  794.             for (int j=0; j<wid-1; j++,sp+=3)
  795.             {
  796.                 int r,g,b;
  797.                 r=sp[0],g=sp[1],b=sp[2];
  798.                 r>>=3,g>>=3,b>>=3;
  799.                 for (int k=0; k<zoom; k++,dp+=2)
  800.                     SETRGB31(WORD(dp), r,g,b);
  801.             }
  802.             int r,g,b;
  803.             r=sp[0],g=sp[1],b=sp[2];
  804.             r>>=3,g>>=3,b>>=3;
  805.             for (int k=0; k<dcnt; k++,dp+=2)
  806.                 SETRGB31(WORD(dp), r,g,b);
  807.         }
  808.         else if (pic->pixelsize == 24 && bm->pixelsize == 24)
  809.         {
  810.             for (int j=0; j<wid-1; j++,sp+=3)
  811.             {
  812.                 for (int k=0; k<zoom; k++,dp+=3)
  813.                     dp[0]=sp[0],dp[1]=sp[1],dp[2]=sp[2];
  814.             }
  815.             for (int k=0; k<dcnt; k++,dp+=3)
  816.                 dp[0]=sp[0],dp[1]=sp[1],dp[2]=sp[2];
  817.         }
  818.         // 縦方向にひきのばす
  819.         int t = dxcnt * bm->pixelsize / 8;
  820.         for (int j=1; j < zoom && dy+j < bm->ht; j++)
  821.             memcpy(dp0+dxbytes*j, dp0, t);
  822.     }
  823. }
  824.  
  825. /*--------------------------------------------------------*/
  826. /*                       ピクセル値                       */
  827. /*--------------------------------------------------------*/
  828.  
  829. void pixel_setRgb(PIXEL *pixel, int r, int g, int b)
  830. {
  831.     pixel->r = (r < 0 ? 0 : r > 255 ? 255 : r);
  832.     pixel->g = (g < 0 ? 0 : g > 255 ? 255 : g);
  833.     pixel->b = (b < 0 ? 0 : b > 255 ? 255 : b);
  834. }
  835.  
  836. void pixel_getRgb(PIXEL *pixel, int *r, int *g, int *b)
  837. {
  838.     *r = pixel->r;
  839.     *g = pixel->g;
  840.     *b = pixel->b;
  841. }
  842.  
  843. void pic_copy(PIC* picSrc, FRAME* frSrc, PIC* picDest, POINT* ptDest)
  844.     // frSrc:(x,y,wid,ht)
  845.     // update 管理を忘れないこと!
  846. {
  847.     int i;
  848.     if (frSrc->Y >= ptDest->y)
  849.     {
  850.         for (i=0; i<frSrc->HT; i++)
  851.         {
  852.             int sy = frSrc->Y+i;
  853.             int dy = ptDest->y+i;
  854.             if (sy < 0 || dy < 0)
  855.                 continue;
  856.             if (sy >= picSrc->ht || dy >= picDest->ht)
  857.                 break;
  858.             char *sp = picSrc->buf + PICOFFSET(picSrc,frSrc->X,frSrc->Y+i);
  859.             char *dp = picDest->buf + PICOFFSET(picDest,ptDest->x,ptDest->y+i);
  860.             int wid = _max(0,_min(frSrc->WID,
  861.                            picSrc->wid - frSrc->X,
  862.                            picDest->wid - ptDest->x));
  863.             if (wid == 0)
  864.                 break;
  865.             if (picSrc->pixelsize == picDest->pixelsize)
  866.                 memcpy(dp, sp, wid * picSrc->pixelsize / 8);
  867.             else if (picSrc->pixelsize == 16 && picDest->pixelsize == 24)
  868.             {
  869.                 for (int j=0; j<wid; j++,dp+=3,sp+=2)
  870.                   { int r,g,b;  GETRGB31(WORD(sp), r,g,b);
  871.                     dp[0]=_31_255[r],dp[1]=_31_255[g],dp[2]=_31_255[b]; }
  872.             }
  873.             else if (picSrc->pixelsize == 24 && picDest->pixelsize == 16)
  874.             {
  875.                 for (int j=0; j<wid; j++,dp+=2,sp+=3)
  876.                     SETRGB31(WORD(dp),sp[0]>>3,sp[1]>>3,sp[2]>>3);
  877.             }
  878.         }
  879.     }
  880.     else
  881.     {
  882.         for (i=0; i<frSrc->HT; i++)
  883.         {
  884.             int sy = frSrc->Y+frSrc->HT-1-i;
  885.             int dy = ptDest->y+frSrc->HT-1-i;
  886.             if (sy < 0 || dy < 0)
  887.                 break;
  888.             if (sy >= picSrc->ht || dy >= picDest->ht)
  889.                 continue;
  890.             char *sp = picSrc->buf + PICOFFSET(picSrc,frSrc->X,frSrc->Y+i);
  891.             char *dp = picDest->buf + PICOFFSET(picDest,ptDest->x,ptDest->y+i);
  892.             int wid = _max(0,_min(frSrc->WID,
  893.                            picSrc->wid - frSrc->X,
  894.                            picDest->wid - ptDest->x));
  895.             if (wid == 0)
  896.                 break;
  897.             if (picSrc->pixelsize == picDest->pixelsize)
  898.                 memcpy(dp, sp, wid * picSrc->pixelsize / 8);
  899.             else if (picSrc->pixelsize == 16 && picDest->pixelsize == 24)
  900.             {
  901.                 for (int j=0; j<wid; j++,dp+=3,sp+=2)
  902.                   { int r,g,b;  GETRGB31(WORD(sp), r,g,b);
  903.                     dp[0]=_31_255[r],dp[1]=_31_255[g],dp[2]=_31_255[b]; }
  904.             }
  905.             else if (picSrc->pixelsize == 24 && picDest->pixelsize == 16)
  906.             {
  907.                 for (int j=0; j<wid; j++,dp+=2,sp+=3)
  908.                     SETRGB31(WORD(dp),sp[0]>>3,sp[1]>>3,sp[2]>>3);
  909.             }
  910.         }
  911.     }
  912.     pic_updateRect(picDest, ptDest->x, ptDest->y, frSrc->WID, frSrc->HT);
  913. }
  914.  
  915. void pic_paint(PIC *pic, int x,int y, PIXEL* pix)
  916. {
  917.     PIXEL pixBack;
  918.     #define ISBACK(pix)    \
  919.         ((pix).r==pixBack.r && (pix).g==pixBack.g && (pix).b==pixBack.b)
  920.     pic_getPixelXy(pic,x,y,&pixBack);
  921.     if (ISBACK(*pix))
  922.         return;
  923.     int mix = pensel_getmix();
  924.     void hline(int x1,int x2,int y)
  925.     {
  926.         pic_grayhline(pic,x1,x2,y,mix,pix);
  927.     }
  928.     BOOL shouldPaint(int x,int y)
  929.     {
  930.         PIXEL pix;
  931.         pic_getPixelXy(pic,x,y,&pix);
  932.         if (ISBACK(pix))
  933.             return TRUE;
  934.         else
  935.             return FALSE;
  936.     }
  937.     int srchleft(int x,int y)
  938.     {
  939.         int sx1;
  940.         PIXEL pix;
  941.         for (sx1=x; sx1 > 0; sx1--)
  942.         {
  943.             pic_getPixelXy(pic,sx1-1,y,&pix);
  944.             if (!ISBACK(pix))
  945.                 break;
  946.         }
  947.         return sx1;
  948.     }
  949.     int srchright(int x,int y)
  950.     {
  951.         int sx2;
  952.         PIXEL pix;
  953.         for (sx2=x; sx2 < pic->wid-1; sx2++)
  954.         {
  955.             pic_getPixelXy(pic,sx2+1,y,&pix);
  956.             if (!ISBACK(pix))
  957.                 break;
  958.         }
  959.         return sx2;
  960.     }
  961.     do_paint(x,y,pic->wid,pic->ht,hline,shouldPaint,srchleft,srchright);
  962. }
  963.  
  964. void pic_blot(PIC *pic,int x,int y,int branch,int depth,PIXEL* pix)
  965. {
  966.     uint mix = pensel_getmix();
  967.     void pset(int x,int y,int gray)
  968.     {
  969.         pic_grayPset(pic,x,y,(gray*mix+127)/255,pix);
  970.     }
  971.     do_blot(x,y,branch,depth,pset);
  972. }
  973.  
  974. void pic_polygon(PIC* pic,POINT* points,int nPoint,PIXEL* pix)
  975. {
  976.     int mix = pensel_getmix();
  977.     void hline(int x1,int x2,int y)
  978.     {
  979.         pic_grayhline(pic,x1,x2,y,mix,pix);
  980.     }
  981.     do_polygon(points,nPoint,hline);
  982. }
  983.  
  984. void pic_copyarea(PIC* picSrc, AREA areaSrc, PIC* picDest, POINT* ptDest)
  985. {
  986.     void hline(int x1,int x2,int y)
  987.     {
  988.         char *sp = PICADDR(picSrc,x1,y);
  989.         char *dp = PICADDR(picDest,
  990.             ptDest->x + (x1 - areaSrc->x), ptDest->y + (y - areaSrc->y));
  991.         int wid = _max(0,_min( x2-x1+1,
  992.                        picSrc->wid - areaSrc->x,
  993.                        picDest->wid - ptDest->x));
  994.         if (wid == 0)
  995.             return;
  996.         if (picSrc->pixelsize == picDest->pixelsize)
  997.             memcpy(dp, sp, wid * picSrc->pixelsize / 8);
  998.         else if (picSrc->pixelsize == 16 && picDest->pixelsize == 24)
  999.         {
  1000.             for (int j=0; j<wid; j++,dp+=3,sp+=2)
  1001.               { int r,g,b;  GETRGB31(WORD(sp), r,g,b);
  1002.                 dp[0]=_31_255[r],dp[1]=_31_255[g],dp[2]=_31_255[b]; }
  1003.         }
  1004.         else if (picSrc->pixelsize == 24 && picDest->pixelsize == 16)
  1005.         {
  1006.             for (int j=0; j<wid; j++,dp+=2,sp+=3)
  1007.                 SETRGB31(WORD(dp),sp[0]>>3,sp[1]>>3,sp[2]>>3);
  1008.         }
  1009.     }
  1010.     if (areaSrc->y >= ptDest->y)
  1011.     {
  1012.         for (int i=0; i<areaSrc->ht; i++)
  1013.         {
  1014.             int sy = areaSrc->y + i;
  1015.             int dy = ptDest->y + i;
  1016.             if (sy < 0 || dy < 0)
  1017.                 continue;
  1018.             if (sy >= picSrc->ht || dy >= picDest->ht)
  1019.                 break;
  1020.             area_forEachSect(areaSrc,sy,hline);
  1021.         }
  1022.     }
  1023.     else
  1024.     {
  1025.         for (int i=0; i<areaSrc->ht; i++)
  1026.         {
  1027.             int sy = areaSrc->y + areaSrc->ht - 1 - i;
  1028.             int dy = ptDest->y + areaSrc->ht - 1 - i;
  1029.             if (sy < 0 || dy < 0)
  1030.                 break;
  1031.             if (sy >= picSrc->ht || dy >= picDest->ht)
  1032.                 continue;
  1033.             area_forEachSect(areaSrc,sy,hline);
  1034.         }
  1035.     }
  1036.     pic_updateRect(picDest, ptDest->x, ptDest->y, areaSrc->wid, areaSrc->ht);
  1037. }
  1038.  
  1039. void pic_fillarea(PIC* pic,AREA area,PIXEL* pix)
  1040. {
  1041.     int mix = pensel_getmix();
  1042.     void hline(int x1,int x2,int y)
  1043.     {
  1044.         pic_grayhline(pic,x1,x2,y,mix,pix);
  1045.     }
  1046.     for (int i=0; i<area->ht; i++)
  1047.     {
  1048.         int sy = area->y + i;
  1049.         if (sy < 0)
  1050.             continue;
  1051.         if (sy >= pic->ht)
  1052.             break;
  1053.         area_forEachSect(area, sy, hline);
  1054.     }
  1055.     pic_updateRect(pic, area->x, area->y, area->wid, area->ht);
  1056. }
  1057.