home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / gimpressionist / repaint.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-13  |  25.5 KB  |  884 lines

  1. #ifdef HAVE_CONFIG_H
  2. #include "config.h"
  3. #else
  4. #define HAVE_DIRENT_H
  5. #define HAVE_UNISTD_H
  6. #endif
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #ifdef HAVE_UNISTD_H
  12. #include <unistd.h>
  13. #endif
  14. #include <time.h>
  15.  
  16. #include <gtk/gtk.h>
  17.  
  18. #include <libgimp/gimp.h>
  19.  
  20. #include "gimpressionist.h"
  21. #include "ppmtool.h"
  22.  
  23. #include <libgimp/stdplugins-intl.h>
  24.  
  25. gimpressionist_vals_t runningvals;
  26.  
  27. void prepbrush(struct ppm *p)
  28. {
  29.   int x, y;
  30.   int rowstride = p->width * 3;
  31.  
  32.   for(y = 0; y< p->height; y++) {
  33.     for(x = 0; x < p->width; x++) {
  34.       p->col[y*rowstride+x*3+1] = 0;
  35.     }
  36.   }
  37.  
  38.   for(y = 1; y< p->height; y++) {
  39.     for(x = 1; x < p->width; x++) {
  40.       int v = p->col[y*rowstride+x*3] - p->col[(y-1)*rowstride+(x-1)*3];
  41.       if(v < 0) v = 0;
  42.       p->col[y*rowstride+x*3+1] = v;
  43.     }
  44.   }
  45. }
  46.  
  47. double sumbrush(struct ppm *p)
  48. {
  49.   double sum = 0;
  50.   int i;
  51.  
  52.   for(i = 0; i < p->width*3*p->height; i += 3)
  53.     sum += p->col[i];
  54.   return sum;
  55. }
  56.  
  57. int gethue(guchar *rgb)
  58. {
  59.   double h, v, temp, diff;
  60.   if((rgb[0] == rgb[1]) && (rgb[0] == rgb[2])) /* Gray */
  61.     return 0;
  62.   v = (rgb[0] > rgb[1] ? rgb[0] : rgb[1]);     /* v = st<F8>rste verdi */
  63.   if(rgb[2] > v) v = rgb[2];
  64.   temp = (rgb[0] > rgb[1] ? rgb[1] : rgb[0] ); /* temp = minste */
  65.   if(rgb[2] < temp) temp = rgb[2];
  66.   diff = v - temp;
  67.  
  68.   if(v == rgb[0])
  69.     h = ((double)rgb[1] - rgb[2]) / diff;
  70.   else if(v == rgb[1])
  71.     h = ((double)rgb[2] - rgb[0]) / diff + 2;
  72.   else /* v == rgb[2] */
  73.     h = ((double)rgb[0] - rgb[1]) / diff + 4;
  74.   if(h < 0) h += 6;
  75.   return h * 255.0 / 6.0;
  76. }
  77.  
  78. int bestbrush(struct ppm *p, struct ppm *a, int tx, int ty,
  79.           struct ppm *brushes, int numbrush, double *brushsum,
  80.           int start, int step)
  81. {
  82.   double dev, thissum;
  83.   double bestdev = 0.0;
  84.   double r, g, b;
  85.   int best = -1;
  86.   int x, y, h;
  87.   long i;
  88.   GList *brlist = NULL;
  89.  
  90.   for(i = start; i < numbrush; i += step) {
  91.     struct ppm *brush = &brushes[i];
  92.     /* thissum = 0.0; */
  93.     thissum = brushsum[i];
  94.  
  95.     r = g = b = 0.0;
  96.     for(y = 0; y < brush->height; y++) {
  97.       guchar *row = p->col + (ty+y)*p->width*3;
  98.       for(x = 0; x < brush->width; x++) {
  99.     int k = (tx+x)*3;
  100.     double v;
  101.     if((h = brush->col[(y*brush->width*3)+x*3])) {
  102.       /* thissum += h; */
  103.       v = h / 255.0;
  104.       r += row[k+0] * v;
  105.       g += row[k+1] * v;
  106.       b += row[k+2] * v;
  107.     }
  108.       }
  109.     }
  110.     r = r * 255.0 / thissum;
  111.     g = g * 255.0 / thissum;
  112.     b = b * 255.0 / thissum;
  113.  
  114.     dev = 0.0;
  115.     for(y = 0; y < brush->height; y++) {
  116.       guchar *row = p->col + (ty+y)*p->width*3;
  117.       for(x = 0; x < brush->width; x++) {
  118.     int k = (tx+x)*3;
  119.     double v;
  120.     if((h = brush->col[(y*brush->width*3)+x*3])) {
  121.       v = h / 255.0;
  122.       dev += abs(row[k+0] - r) * v;
  123.       dev += abs(row[k+1] - g) * v;
  124.       dev += abs(row[k+2] - b) * v;
  125.       if(img_has_alpha)
  126.         dev += a->col[(ty+y)*a->width*3+(tx+x)*3] * v;
  127.     }
  128.       }
  129.     }
  130.     dev /= thissum;
  131.  
  132.     if((best == -1) || (dev < bestdev)) {
  133.       if(brlist)
  134.     g_list_free(brlist);
  135.       brlist = NULL;
  136.     }
  137.     
  138.     if(dev <= bestdev || best < 0) {
  139.       best = i;
  140.       bestdev = dev;
  141.       brlist = g_list_append(brlist, (void *)i);
  142.     }
  143.     if(dev < runningvals.devthresh) break;
  144.   }
  145.  
  146.   if(!brlist) {
  147.     fprintf(stderr, "What!? No brushes?!\n");
  148.     return 0;
  149.   }
  150.  
  151.   i = RAND_FUNC() % g_list_length(brlist);
  152.   best = (long)((g_list_nth(brlist,i))->data);
  153.   g_list_free(brlist);
  154.  
  155.   return best;
  156. }
  157.  
  158. void applybrush(struct ppm *brush,
  159.         struct ppm *shadow,
  160.         struct ppm *p, struct ppm *a,
  161.         int tx, int ty, int r, int g, int b)
  162. {
  163.   struct ppm tmp;
  164.   struct ppm atmp;
  165.   double v, h;
  166.   int x, y;
  167.   double edgedarken = 1.0 - runningvals.generaldarkedge;
  168.   double relief = runningvals.brushrelief / 100.0;
  169.   int shadowdepth = pcvals.generalshadowdepth;
  170.   int shadowblur = pcvals.generalshadowblur;
  171.  
  172.   /*
  173.   if((tx < 0) || (ty < 0)) {
  174.     fprintf(stderr, "applybrush: Huh!? tx=%d ty=%d\n",tx,ty);
  175.     return;
  176.   }
  177.   */
  178.  
  179.   memcpy(&tmp, p, sizeof(struct ppm));
  180.   if(img_has_alpha) memcpy(&atmp, a, sizeof(struct ppm));
  181.  
  182.   if(shadow) {
  183.     int sx = tx + shadowdepth - shadowblur*2;
  184.     int sy = ty + shadowdepth - shadowblur*2;
  185.     for(y = 0; y < shadow->height; y++) {
  186.       guchar *row, *arow = NULL;
  187.       if((sy + y) < 0) continue;
  188.       if((sy + y) >= tmp.height) break;
  189.       row = tmp.col + (sy+y) * tmp.width * 3;
  190.       if(img_has_alpha) arow = atmp.col + (sy+y) * atmp.width * 3;
  191.       for(x = 0; x < shadow->width; x++) {
  192.     int k = (sx + x) * 3;
  193.     if((sx + x) < 0) continue;
  194.     if((sx + x) >= tmp.width) break;
  195.     h = shadow->col[y*shadow->width*3+x*3+2];
  196.     if(!h) continue;
  197.     v = 1.0 - (h / 255.0 * runningvals.generalshadowdarkness / 100.0);
  198.     row[k+0] *= v;
  199.     row[k+1] *= v;
  200.     row[k+2] *= v;
  201.     if(img_has_alpha) arow[k] *= v;
  202.       }
  203.     }
  204.   }
  205.  
  206.   for(y = 0; y < brush->height; y++) {
  207.     guchar *row = tmp.col + (ty+y)*tmp.width*3;
  208.     guchar *arow = NULL;
  209.     if(img_has_alpha) arow = atmp.col + (ty+y)*atmp.width*3;
  210.     for(x = 0; x < brush->width; x++) {
  211.       int k = (tx + x) * 3;
  212.       h = brush->col[y*brush->width*3+x*3];
  213.       if(!h) continue;
  214.  
  215.       if(runningvals.colorbrushes) {
  216.     v = 1.0 - brush->col[y*brush->width*3+x*3+2] / 255.0;
  217.     row[k+0] *= v;
  218.     row[k+1] *= v;
  219.     row[k+2] *= v;
  220.     if(img_has_alpha) arow[(tx+x)*3] *= v;
  221.       }
  222.       v = (1.0 - h / 255.0) * edgedarken;
  223.       row[k+0] *= v;
  224.       row[k+1] *= v;
  225.       row[k+2] *= v;
  226.       if(img_has_alpha) arow[k] *= v;
  227.  
  228.       v = h / 255.0;
  229.       row[k+0] += r * v;
  230.       row[k+1] += g * v;
  231.       row[k+2] += b * v;
  232.     }
  233.   }
  234.  
  235.   if(relief > 0.001) {
  236.     for(y = 1; y < brush->height; y++) {
  237.       guchar *row = tmp.col + (ty+y)*tmp.width*3;
  238.       for(x = 1; x < brush->width; x++) {
  239.     int k = (tx + x) * 3;
  240.     h = brush->col[y*brush->width*3+x*3+1] * relief;
  241.     if(h < 0.001) continue;
  242.     if(h > 255) h = 255;
  243.     row[k+0] = (row[k+0] * (255-h) + 255 * h) / 255;
  244.     row[k+1] = (row[k+1] * (255-h) + 255 * h) / 255;
  245.     row[k+2] = (row[k+2] * (255-h) + 255 * h) / 255;
  246.       }
  247.     }
  248.   }
  249. }
  250.  
  251. void repaint(struct ppm *p, struct ppm *a)
  252. {
  253.   int x, y;
  254.   int tx = 0, ty = 0;
  255.   struct ppm tmp = {0,0,NULL};
  256.   struct ppm atmp = {0,0,NULL};
  257.   int r, g, b, n, h, i, j, on, sn;
  258.   int numbrush, maxbrushwidth, maxbrushheight;
  259.   guchar back[3] = {0,0,0};
  260.   struct ppm *brushes, *shadows;
  261.   struct ppm *brush, *shadow = NULL;
  262.   double *brushsum;
  263.   int cx, cy, maxdist;
  264.   double scale, relief, startangle, anglespan, density, bgamma;
  265.   double thissum;
  266.   int max_progress;
  267.   struct ppm paperppm = {0,0,NULL};
  268.   struct ppm dirmap = {0,0,NULL};
  269.   struct ppm sizmap = {0,0,NULL};
  270.   int *xpos = NULL, *ypos = NULL;
  271.   int step = 1;
  272.   int progstep;
  273.   static int running = 0;
  274.  
  275.   int dropshadow = pcvals.generaldropshadow;
  276.   int shadowblur = pcvals.generalshadowblur;
  277.  
  278.   if(running)
  279.     return;
  280.   running++;
  281.  
  282.   memcpy(&runningvals, &pcvals, sizeof(pcvals));
  283.  
  284.   /* Shouldn't be necessary, but... */
  285.   if(img_has_alpha)
  286.     if((p->width != a->width) || (p->height != a->height)) {
  287.       fprintf(stderr, "Huh? Image size != alpha size?\n");
  288.       return;
  289.     }
  290.  
  291.   SRAND_FUNC(time(NULL));
  292.  
  293.   numbrush = runningvals.orientnum * runningvals.sizenum;
  294.   startangle = runningvals.orientfirst;
  295.   anglespan = runningvals.orientlast;
  296.  
  297.   density = runningvals.brushdensity;
  298.  
  299.   if(runningvals.placetype == 1) density /= 3.0;
  300.  
  301.   bgamma = runningvals.brushgamma;
  302.  
  303.   brushes = g_malloc (numbrush * sizeof(struct ppm));
  304.   brushsum = g_malloc (numbrush * sizeof(double));
  305.  
  306.   if(dropshadow)
  307.     shadows = g_malloc (numbrush * sizeof(struct ppm));
  308.   else
  309.     shadows = NULL;
  310.  
  311.   brushes[0].col = NULL;
  312.   if(brushfile)
  313.     reloadbrush(runningvals.selectedbrush, &brushes[0]);
  314.   else
  315.     copyppm(&brushppm, &brushes[0]);
  316.  
  317.   resize(&brushes[0], brushes[0].width, brushes[0].height * pow(10,runningvals.brushaspect));
  318.   scale = runningvals.sizelast / MAX(brushes[0].width, brushes[0].height);
  319.  
  320.   if(bgamma != 1.0)
  321.     ppmgamma(&brushes[0], 1.0/bgamma, 1,1,1);
  322.   
  323.   resize(&brushes[0], brushes[0].width * scale, brushes[0].height * scale);
  324.   i = 1 + sqrt(brushes[0].width * brushes[0].width +
  325.            brushes[0].height * brushes[0].height);
  326.   pad(&brushes[0], i-brushes[0].width, i-brushes[0].width,
  327.       i-brushes[0].height, i-brushes[0].height, back);
  328.   
  329.   for(i = 1; i < numbrush; i++) {
  330.     brushes[i].col = NULL;
  331.     copyppm(&brushes[0], &brushes[i]);
  332.   }
  333.  
  334.   for(i = 0; i < runningvals.sizenum; i++) {
  335.     double sv;
  336.     if(runningvals.sizenum > 1)
  337.       sv = i / (runningvals.sizenum - 1.0);
  338.     else sv = 1.0;
  339.     for(j = 0; j < runningvals.orientnum; j++) {
  340.       h = j + i * runningvals.orientnum;
  341.       freerotate(&brushes[h],
  342.          startangle + j * anglespan / runningvals.orientnum);
  343.       rescale(&brushes[h], (sv * runningvals.sizefirst + (1.0-sv) * runningvals.sizelast) / runningvals.sizelast);
  344.       autocrop(&brushes[h],1);
  345.     } 
  346.   }
  347.  
  348.   /* Brush-debugging */
  349.   /*
  350.   for(i = 0; i < numbrush; i++) {
  351.     char tmp[1000];
  352.     sprintf(tmp, "/tmp/_brush%03d.ppm", i);
  353.     saveppm(&brushes[i], tmp);
  354.   }
  355.   */
  356.  
  357.   for(i = 0; i < numbrush; i++) {
  358.     if(!runningvals.colorbrushes)
  359.       prepbrush(&brushes[i]);
  360.     brushsum[i] = sumbrush(&brushes[i]);
  361.   }
  362.  
  363.   brush = &brushes[0];
  364.   thissum = brushsum[0];
  365.  
  366.   maxbrushwidth = maxbrushheight = 0;
  367.   for(i = 0; i < numbrush; i++) {
  368.     if(brushes[i].width > maxbrushwidth) maxbrushwidth = brushes[i].width;
  369.     if(brushes[i].height > maxbrushheight) maxbrushheight = brushes[i].height;
  370.   }
  371.   
  372.   for(i = 0; i < numbrush; i++) {
  373.     int xp, yp;
  374.     guchar blk[3] = {0,0,0};
  375.  
  376.     xp = maxbrushwidth - brushes[i].width;
  377.     yp = maxbrushheight - brushes[i].height;
  378.     if(xp || yp)
  379.       pad(&brushes[i], xp/2, xp-xp/2, yp/2, yp-yp/2, blk);
  380.   }
  381.  
  382.   if(dropshadow) {
  383.     for(i = 0; i < numbrush; i++) {
  384.       shadows[i].col = NULL;
  385.       copyppm(&brushes[i], &shadows[i]);
  386.       ppmgamma(&shadows[i], 0, 1,1,0);
  387.       pad(&shadows[i], shadowblur*2, shadowblur*2, 
  388.       shadowblur*2, shadowblur*2, back);
  389.       for(j = 0; j < shadowblur; j++)
  390.     blur(&shadows[i], 2, 2);
  391.       /* autocrop(&shadows[i],1); */
  392.     }
  393.     /*
  394.     maxbrushwidth += shadowdepth*3;
  395.     maxbrushheight += shadowdepth*3;
  396.     */
  397.   }
  398.   
  399.   /* For extra annoying debugging :-) */
  400.   /*
  401.   saveppm(brushes, "/tmp/__brush.ppm");
  402.   if(shadows) saveppm(shadows, "/tmp/__shadow.ppm");
  403.   system("xv /tmp/__brush.ppm & xv /tmp/__shadow.ppm & ");
  404.   */
  405.  
  406.   if(runningvals.generalpaintedges) {
  407.     edgepad(p, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight);
  408.     if(img_has_alpha)
  409.       edgepad(a, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight);
  410.   }
  411.  
  412.   if(img_has_alpha) {
  413.     /* Initially fully transparent */
  414.     if(runningvals.generalbgtype == 3) {
  415.       guchar tmpcol[3] = {255,255,255};
  416.       newppm(&atmp, a->width, a->height);
  417.       fill(&atmp, tmpcol);
  418.     } else {
  419.       copyppm(a, &atmp);
  420.     }
  421.   }
  422.  
  423.   if(runningvals.generalbgtype == 0) {
  424.     guchar tmpcol[3];
  425.     newppm(&tmp, p->width, p->height);
  426.     memcpy(&tmpcol, runningvals.color, 3);
  427.     fill(&tmp, tmpcol);
  428.   } else if(runningvals.generalbgtype == 1) {
  429.     copyppm(p, &tmp);
  430.   } else {
  431.     scale = runningvals.paperscale / 100.0;
  432.     newppm(&tmp, p->width, p->height);
  433.     loadppm(runningvals.selectedpaper, &paperppm);
  434.     resize(&paperppm, paperppm.width * scale, paperppm.height * scale);
  435.     if(runningvals.paperinvert)
  436.       ppmgamma(&paperppm, -1.0, 1, 1, 1);
  437.     for(x = 0; x < tmp.width; x++) {
  438.       int rx = x % paperppm.width;
  439.       for(y = 0; y < tmp.height; y++) {
  440.     int ry = y % paperppm.height;
  441.     memcpy(&tmp.col[y*tmp.width*3+x*3], &paperppm.col[ry*paperppm.width*3+rx*3], 3);
  442.       }
  443.     }
  444.   }
  445.  
  446.   cx = p->width / 2;
  447.   cy = p->height / 2;
  448.   maxdist = sqrt(cx*cx+cy*cy);
  449.  
  450.   if(runningvals.orienttype == 0) { /* Value */
  451.     newppm(&dirmap, p->width, p->height);
  452.     for(y = 0; y < dirmap.height; y++) {
  453.       guchar *dstrow = &dirmap.col[y*dirmap.width*3];
  454.       guchar *srcrow = &p->col[y*p->width*3];
  455.       for(x = 0; x < dirmap.width; x++) {
  456.     dstrow[x*3] = (srcrow[x*3] + srcrow[x*3+1] + srcrow[x*3+2]) / 3;
  457.       }
  458.     }
  459.   } else if(runningvals.orienttype == 1) { /* Radius */
  460.     newppm(&dirmap, p->width, p->height);
  461.     for(y = 0; y < dirmap.height; y++) {
  462.       guchar *dstrow = &dirmap.col[y*dirmap.width*3];
  463.       double ysqr = (cy-y)*(cy-y);
  464.       for(x = 0; x < dirmap.width; x++) {
  465.     dstrow[x*3] = sqrt((cx-x)*(cx-x)+ysqr) * 255 / maxdist;
  466.       }
  467.     }
  468.   } else if(runningvals.orienttype == 3) { /* Radial */
  469.     newppm(&dirmap, p->width, p->height);
  470.     for(y = 0; y < dirmap.height; y++) {
  471.       guchar *dstrow = &dirmap.col[y*dirmap.width*3];
  472.       for(x = 0; x < dirmap.width; x++) {
  473.     dstrow[x*3] = (G_PI + atan2(cy-y, cx-x)) * 255.0 / (G_PI*2);
  474.       }
  475.     }
  476.   } else if(runningvals.orienttype == 4) { /* Flowing */
  477.     newppm(&dirmap, p->width / 6 + 5, p->height / 6 + 5);
  478.     mkgrayplasma(&dirmap, 15);
  479.     blur(&dirmap, 2, 2);
  480.     blur(&dirmap, 2, 2);
  481.     resize(&dirmap, p->width, p->height);
  482.     blur(&dirmap, 2, 2);
  483.     if(runningvals.generalpaintedges)
  484.       edgepad(&dirmap, maxbrushwidth, maxbrushheight,maxbrushwidth, maxbrushheight);
  485.   } else if(runningvals.orienttype == 5) { /* Hue */
  486.     newppm(&dirmap, p->width, p->height);
  487.     for(y = 0; y < dirmap.height; y++) {
  488.       guchar *dstrow = &dirmap.col[y*dirmap.width*3];
  489.       guchar *srcrow = &p->col[y*p->width*3];
  490.       for(x = 0; x < dirmap.width; x++) {
  491.     dstrow[x*3] = gethue(&srcrow[x*3]);
  492.       }
  493.     }
  494.   } else if(runningvals.orienttype == 6) {
  495.     guchar tmpcol[3] = {0,0,0};
  496.     newppm(&dirmap, p->width, p->height);
  497.     fill(&dirmap, tmpcol);
  498.  
  499.   } else if(runningvals.orienttype == 7) { /* Manual */
  500.     newppm(&dirmap, p->width-maxbrushwidth*2, p->height-maxbrushheight*2);
  501.     for(y = 0; y < dirmap.height; y++) {
  502.       guchar *dstrow = &dirmap.col[y*dirmap.width*3];
  503.       double tmpy = y / (double)dirmap.height;
  504.       for(x = 0; x < dirmap.width; x++) {
  505.     dstrow[x*3] = pixval(90-getdir(x / (double)dirmap.width, tmpy, 1));
  506.       }
  507.     }
  508.     edgepad(&dirmap, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight);
  509.   }
  510.  
  511.   if(runningvals.sizetype == 0) { /* Value */
  512.     newppm(&sizmap, p->width, p->height);
  513.     for(y = 0; y < sizmap.height; y++) {
  514.       guchar *dstrow = &sizmap.col[y*sizmap.width*3];
  515.       guchar *srcrow = &p->col[y*p->width*3];
  516.       for(x = 0; x < sizmap.width; x++) {
  517.     dstrow[x*3] = (srcrow[x*3] + srcrow[x*3+1] + srcrow[x*3+2]) / 3;
  518.       }
  519.     }
  520.   } else if(runningvals.sizetype == 1) { /* Radius */
  521.     newppm(&sizmap, p->width, p->height);
  522.     for(y = 0; y < sizmap.height; y++) {
  523.       guchar *dstrow = &sizmap.col[y*sizmap.width*3];
  524.       double ysqr = (cy-y)*(cy-y);
  525.       for(x = 0; x < sizmap.width; x++) {
  526.     dstrow[x*3] = sqrt((cx-x)*(cx-x)+ysqr) * 255 / maxdist;
  527.       }
  528.     }
  529.   } else if(runningvals.sizetype == 3) { /* Radial */
  530.     newppm(&sizmap, p->width, p->height);
  531.     for(y = 0; y < sizmap.height; y++) {
  532.       guchar *dstrow = &sizmap.col[y*sizmap.width*3];
  533.       for(x = 0; x < sizmap.width; x++) {
  534.     dstrow[x*3] = (G_PI + atan2(cy-y, cx-x)) * 255.0 / (G_PI*2);
  535.       }
  536.     }
  537.   } else if(runningvals.sizetype == 4) { /* Flowing */
  538.     newppm(&sizmap, p->width / 6 + 5, p->height / 6 + 5);
  539.     mkgrayplasma(&sizmap, 15);
  540.     blur(&sizmap, 2, 2);
  541.     blur(&sizmap, 2, 2);
  542.     resize(&sizmap, p->width, p->height);
  543.     blur(&sizmap, 2, 2);
  544.     if(runningvals.generalpaintedges)
  545.       edgepad(&sizmap, maxbrushwidth, maxbrushheight,maxbrushwidth, maxbrushheight);
  546.   } else if(runningvals.sizetype == 5) { /* Hue */
  547.     newppm(&sizmap, p->width, p->height);
  548.     for(y = 0; y < sizmap.height; y++) {
  549.       guchar *dstrow = &sizmap.col[y*sizmap.width*3];
  550.       guchar *srcrow = &p->col[y*p->width*3];
  551.       for(x = 0; x < sizmap.width; x++) {
  552.     dstrow[x*3] = gethue(&srcrow[x*3]);
  553.       }
  554.     }
  555.   } else if(runningvals.sizetype == 6) {
  556.     guchar tmpcol[3] = {0,0,0};
  557.     newppm(&sizmap, p->width, p->height);
  558.     fill(&sizmap, tmpcol);
  559.  
  560.   } else if(runningvals.sizetype == 7) { /* Manual */
  561.     newppm(&sizmap, p->width-maxbrushwidth*2, p->height-maxbrushheight*2);
  562.     for(y = 0; y < sizmap.height; y++) {
  563.       guchar *dstrow = &sizmap.col[y*sizmap.width*3];
  564.       double tmpy = y / (double)sizmap.height;
  565.       for(x = 0; x < sizmap.width; x++) {
  566.     dstrow[x*3] = 255 * (1.0 - getsiz(x / (double)sizmap.width, tmpy, 1));
  567.       }
  568.     }
  569.     edgepad(&sizmap, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight);
  570.   }
  571.   /*
  572.   saveppm(&sizmap, "/tmp/_sizmap.ppm");
  573.   */
  574.   if(runningvals.placetype == 0) {
  575.     i = tmp.width * tmp.height / (maxbrushwidth * maxbrushheight);
  576.     i *= density;
  577.   } else if(runningvals.placetype == 1) {
  578.     i = (int)(tmp.width * density / maxbrushwidth) *
  579.       (int)(tmp.height * density / maxbrushheight);
  580.     step = i;
  581.     /* fprintf(stderr, "step=%d i=%d\n", step, i); */
  582.   }
  583.   if(i < 1) i = 1;
  584.  
  585.   max_progress = i;
  586.   progstep = max_progress / 30;
  587.   if(progstep < 10) progstep = 10;
  588.  
  589.   if(runningvals.placetype == 1) {
  590.     int j;
  591.     xpos = g_new (int, i);
  592.     ypos = g_new (int, i);
  593.     for(j = 0; j < i; j++) {
  594.       int factor = (int)(tmp.width * density / maxbrushwidth + 0.5);
  595.       if(factor < 1) factor = 1;
  596.       xpos[j] = maxbrushwidth/2 + (j % factor) * maxbrushwidth / density;
  597.       ypos[j] = maxbrushheight/2 + (j / factor) * maxbrushheight / density;
  598.     }
  599.     for(j = 0; j < i; j++) {
  600.       int a, b;
  601.       a = RAND_FUNC() % i;
  602.       b = xpos[j]; xpos[j] = xpos[a]; xpos[a] = b;
  603.       b = ypos[j]; ypos[j] = ypos[a]; ypos[a] = b;
  604.     }
  605.   }
  606.  
  607.   for(; i; i--) {
  608.     if(i % progstep == 0) {
  609.       if(runningvals.run) {
  610.     if(!standalone)
  611.       gimp_progress_update(0.8 - 0.8*((double)i / max_progress));
  612.     else {
  613.       fprintf(stderr, "."); fflush(stderr);
  614.     }
  615.       } else {
  616.     char tmps[40];
  617.     sprintf(tmps, "%.1f %%", 100 * (1.0 - ((double)i / max_progress)));
  618. #if GTK_MINOR_VERSION == 0
  619.     gtk_label_set(GTK_LABEL(GTK_BUTTON(previewbutton)->child), tmps);
  620. #else
  621.     gtk_label_set_text(GTK_LABEL(GTK_BUTTON(previewbutton)->child), tmps);
  622. #endif
  623.     while(gtk_events_pending())
  624.       gtk_main_iteration();
  625.       }
  626.     }
  627.  
  628.     if(runningvals.placetype == 0) {
  629.       tx = RAND_FUNC() % (tmp.width - maxbrushwidth) + maxbrushwidth/2;
  630.       ty = RAND_FUNC() % (tmp.height - maxbrushheight) + maxbrushheight/2;
  631.     } else if(runningvals.placetype == 1) {
  632.       tx = xpos[i-1];
  633.       ty = ypos[i-1];
  634.     }
  635.     if(runningvals.placecenter) {
  636.       double z = RAND_FUNC() * 0.75 / G_MAXRAND;
  637.       tx = tx * (1.0-z) + tmp.width/2 * z;
  638.       ty = ty * (1.0-z) + tmp.height/2 * z;
  639.     }
  640.  
  641.     if((tx < maxbrushwidth/2) || (ty < maxbrushwidth/2) ||
  642.        (tx + maxbrushwidth/2 >= p->width) ||
  643.        (ty + maxbrushheight/2 >= p->height)) {
  644.       /*
  645.       fprintf(stderr, "Internal Error; invalid coords: (%d,%d) i=%d\n", tx, ty, i);
  646.       */
  647.       continue;
  648.     }
  649.  
  650.     if(img_has_alpha) {
  651.       if(a->col[ty*a->width*3+tx*3] > 128)
  652.     continue;
  653.     }
  654.  
  655.     n = sn = on = 0;
  656.  
  657.     switch(runningvals.orienttype) {
  658.     case 2: /* Random */
  659.       on = RAND_FUNC() % runningvals.orientnum;
  660.       break;
  661.     case 0: /* Value */
  662.     case 1: /* Radius */
  663.     case 3: /* Radial */
  664.     case 4: /* Flowing */
  665.     case 5: /* Hue */
  666.     case 7: /* Manual */
  667.       on = runningvals.orientnum * dirmap.col[ty*dirmap.width*3+tx*3] / 256;
  668.       break;
  669.     case 6: /* Adaptive */
  670.       break; /* Handled below */
  671.     default:
  672.       fprintf(stderr, "Internal error; Unknown orientationtype\n");
  673.       on = 0;
  674.       break;
  675.     }
  676.  
  677.     switch(runningvals.sizetype) {
  678.     case 2: /* Random */
  679.       sn = RAND_FUNC() % runningvals.sizenum;
  680.       break;
  681.     case 0: /* Value */
  682.     case 1: /* Radius */
  683.     case 3: /* Radial */
  684.     case 4: /* Flowing */
  685.     case 5: /* Hue */
  686.     case 7: /* Manual */
  687.       sn = runningvals.sizenum * sizmap.col[ty*sizmap.width*3+tx*3] / 256;
  688.       break;
  689.     case 6: /* Adaptive */
  690.       break; /* Handled below */
  691.     default:
  692.       fprintf(stderr, "Internal error; Unknown sizetype\n");
  693.       sn = 0;
  694.       break;
  695.     }
  696.  
  697.     /* Handle Adaptive selections */
  698.     if((runningvals.orienttype == 6) && (runningvals.sizetype == 6)) {
  699.       n = bestbrush(p, a, tx-maxbrushwidth/2, ty-maxbrushheight/2,
  700.             brushes, numbrush, brushsum, 0, 1);
  701.     } else if(runningvals.orienttype == 6) {
  702.       int st = sn * runningvals.orientnum;
  703.       n = bestbrush(p, a, tx-maxbrushwidth/2, ty-maxbrushheight/2,
  704.             brushes, st+runningvals.orientnum, brushsum, st, 1);
  705.     } else if(runningvals.sizetype == 6) {
  706.       n = bestbrush(p, a, tx-maxbrushwidth/2, ty-maxbrushheight/2,
  707.             brushes, numbrush, brushsum, on, runningvals.orientnum);
  708.     } else {
  709.       n = sn * runningvals.orientnum + on;
  710.     }
  711.  
  712.     /* Should never happen, but hey... */
  713.     if(n < 0) n = 0;
  714.     else if(n >= numbrush) n = numbrush - 1;
  715.  
  716.     tx -= maxbrushwidth/2;
  717.     ty -= maxbrushheight/2;
  718.  
  719.     brush = &brushes[n];
  720.     if(dropshadow)
  721.       shadow = &shadows[n];
  722.     thissum = brushsum[n];
  723.  
  724.     /* Calculate color - avg. of in-brush pixels */
  725.     if(runningvals.colortype == 0) {
  726.       r = g = b = 0;
  727.       for(y = 0; y < brush->height; y++) {
  728.     guchar *row = &p->col[(ty+y)*p->width*3];
  729.     for(x = 0; x < brush->width; x++) {
  730.       int k = (tx+x) * 3;
  731.       double v;
  732.       if((h = brush->col[y*brush->width*3+x*3])) {
  733.         v = h / 255.0;
  734.         r += row[k+0] * v;
  735.         g += row[k+1] * v;
  736.         b += row[k+2] * v;
  737.       }
  738.     }
  739.       }
  740.       r = r * 255.0 / thissum;
  741.       g = g * 255.0 / thissum;
  742.       b = b * 255.0 / thissum;
  743.     } else if(runningvals.colortype == 1) {
  744.       guchar *pixel;
  745.       y = ty + (brush->height / 2);
  746.       x = tx + (brush->width / 2);
  747.       pixel = &p->col[y*p->width*3 + x*3];
  748.       r = pixel[0];
  749.       g = pixel[1];
  750.       b = pixel[2];
  751.     } else {
  752.       /* No such colortype! */
  753.       r = g = b = 0;
  754.     }
  755.     if(runningvals.colornoise > 0.0) {
  756.       double v = runningvals.colornoise;
  757.       r = r + RAND_FUNC() / (float)G_MAXRAND * v - v/2;
  758.       g = g + RAND_FUNC() / (float)G_MAXRAND * v - v/2;
  759.       b = b + RAND_FUNC() / (float)G_MAXRAND * v - v/2;
  760.       if(r < 0) r = 0; else if(r > 255) r = 255;
  761.       if(g < 0) g = 0; else if(g > 255) g = 255;
  762.       if(b < 0) b = 0; else if(b > 255) b = 255;
  763.     }
  764.  
  765.     applybrush(brush, shadow, &tmp, &atmp, tx,ty, r,g,b);
  766.     if(runningvals.generaltileable && runningvals.generalpaintedges) {
  767.       int origwidth = tmp.width - 2 * maxbrushwidth;
  768.       int origheight = tmp.height - 2 * maxbrushheight;
  769.       int dox = 0, doy = 0;
  770.       if(tx < maxbrushwidth) {
  771.     applybrush(brush, shadow, &tmp, &atmp, tx+origwidth,ty, r,g,b);
  772.     dox = -1;
  773.       } else if(tx > origwidth) {
  774.     applybrush(brush, shadow, &tmp, &atmp, tx-origwidth,ty, r,g,b);
  775.     dox = 1;
  776.       }
  777.       if(ty < maxbrushheight) {
  778.     applybrush(brush, shadow, &tmp, &atmp, tx,ty+origheight, r,g,b);
  779.     doy = 1;
  780.       } else if(ty > origheight) {
  781.     applybrush(brush, shadow, &tmp, &atmp, tx,ty-origheight, r,g,b);
  782.     doy = -1;
  783.       }
  784.       if(doy) {
  785.     if(dox < 0)
  786.       applybrush(brush, shadow, &tmp, &atmp, tx+origwidth,ty+doy*origheight,r,g,b);
  787.     if(dox > 0)
  788.       applybrush(brush, shadow, &tmp, &atmp, tx-origwidth,ty+doy*origheight,r,g,b);
  789.       }
  790.     }
  791.   }
  792.   for(i = 0; i < numbrush; i++) {
  793.     killppm(&brushes[i]);
  794.   }
  795.   g_free(brushes);
  796.   if(shadows)
  797.     g_free(shadows);
  798.   g_free(brushsum);
  799.  
  800.   if (xpos)
  801.     g_free (xpos);
  802.   if (ypos)
  803.     g_free (ypos);
  804.   
  805.  
  806.   if(runningvals.generalpaintedges) {
  807.     crop(&tmp, maxbrushwidth, maxbrushheight, tmp.width - maxbrushwidth, tmp.height - maxbrushheight);
  808.     if(img_has_alpha)
  809.       crop(&atmp, maxbrushwidth, maxbrushheight, atmp.width - maxbrushwidth, atmp.height - maxbrushheight);
  810.   }
  811.  
  812.   killppm(p);
  813.   p->width = tmp.width;
  814.   p->height = tmp.height;
  815.   p->col = tmp.col;
  816.  
  817.   if(img_has_alpha) {
  818.     killppm(a);
  819.     a->width = atmp.width;
  820.     a->height = atmp.height;
  821.     a->col = atmp.col;
  822.   }
  823.  
  824.   relief = runningvals.paperrelief / 100.0;
  825.   if(relief > 0.001) {
  826.     scale = runningvals.paperscale / 100.0;
  827.  
  828.     if(paperppm.col) {
  829.       memcpy(&tmp, &paperppm, sizeof(struct ppm));
  830.       paperppm.col = NULL;
  831.     } else {
  832.       tmp.col = NULL;
  833.       loadppm(runningvals.selectedpaper, &tmp);
  834.       resize(&tmp, tmp.width * scale, tmp.height * scale);
  835.       if(runningvals.paperinvert)
  836.     ppmgamma(&tmp, -1.0, 1,1,1);
  837.     }
  838.     for(x = 0; x < p->width; x++) {
  839.       double h, v;
  840.       int px = x % tmp.width, py;
  841.       for(y = 0; y < p->height; y++) {
  842.     int k = y * p->width * 3 + x * 3;
  843.     py = y % tmp.height;
  844.     if(runningvals.paperoverlay)
  845.       h = (tmp.col[py*tmp.width*3+px*3]-128) * relief;
  846.     else
  847.       h = (tmp.col[py*tmp.width*3+px*3] - (int)tmp.col[((py+1)%tmp.height)*tmp.width*3+((px+1)%tmp.width)*3]) / -2.0 * relief;
  848.     if(h <= 0.0) {
  849.       v = 1.0 + h/128.0;
  850.       if(v < 0.0) v = 0.0; else if(v > 1.0) v = 1.0;
  851.       p->col[k+0] *= v;
  852.       p->col[k+1] *= v;
  853.       p->col[k+2] *= v;
  854.     } else {
  855.       v = h/128.0;
  856.       if(v < 0.0) v = 0.0; else if(v > 1.0) v = 1.0;
  857.       p->col[k+0] = p->col[k+0] * (1.0-v) + 255 * v;
  858.       p->col[k+1] = p->col[k+1] * (1.0-v) + 255 * v;
  859.       p->col[k+2] = p->col[k+2] * (1.0-v) + 255 * v;
  860.     }
  861.       }
  862.     }
  863.     killppm(&tmp);
  864.   }
  865.  
  866.   if(paperppm.col) killppm(&paperppm);
  867.   if(dirmap.col) killppm(&dirmap);
  868.   if(sizmap.col) killppm(&sizmap);
  869.   if(runningvals.run) {
  870.     if(!standalone)
  871.       gimp_progress_update(0.8);
  872.     else {
  873.       fprintf(stderr, ".\n"); fflush(stderr);
  874.     }
  875.   } else {
  876. #if GTK_MINOR_VERSION == 0
  877.     gtk_label_set(GTK_LABEL(GTK_BUTTON(previewbutton)->child), _("Update"));
  878. #else
  879.     gtk_label_set_text(GTK_LABEL(GTK_BUTTON(previewbutton)->child), _("Update"));
  880. #endif
  881.   }
  882.   running = 0;
  883. }
  884.