IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 41156 for trunk


Ignore:
Timestamp:
Nov 27, 2019, 10:54:47 AM (7 years ago)
Author:
eugene
Message:

add multi-point polygon plots (and filled versions); add memory checks; add buffer smoothing for anti-aliasing

Location:
trunk/Ohana/src/libkapa
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Ohana/src/libkapa/include/kapa.h

    r40558 r41156  
    4545  KAPA_PLOT_BARS_OUTLINE =  4,
    4646  KAPA_PLOT_BARS_OUTFILL =  5,
    47   KAPA_PLOT_INVALID_MAX  =  6,
     47  KAPA_PLOT_POLYGON      =  6,
     48  KAPA_PLOT_POLYFILL     =  7,
     49  KAPA_PLOT_INVALID_MAX  =  8,
    4850} KapaPlotStyle;
    4951
     
    172174  int Nx, Ny, Nbyte;
    173175  bDrawColor **pixels;
     176  char **mask;
    174177  png_color *palette;
    175178  int Npalette;
     179
    176180  // current drawing values:
    177181  int bWeight;
     
    256260int KapaGetImageData (int fd, KapaImageData *graphmode);
    257261int KapaSetToolbox (int fd, int location);
     262int KapaSetSmoothSigma (int fd, float sigma);
     263int KapaMemoryDump (int fd);
     264int KapaMemoryDumpLines (int fd, int Nlines);
     265int KapaMemoryDumpOnExit (int fd, int state);
    258266
    259267/* KapaColors */
     
    272280/* RotFont.c */
    273281void InitRotFonts PROTO((void));
     282void FreeRotFonts PROTO((void));
    274283int SetRotFont PROTO((char *name, int size));
    275284char *GetRotFont PROTO((int *size));
     
    292301bDrawBuffer *bDrawBufferCreate (int Nx, int Ny, int Nbyte, png_color *palette, int Npalette);
    293302void bDrawBufferFree (bDrawBuffer *buffer);
     303int bDrawMerge (bDrawBuffer *base, bDrawBuffer *layer);
    294304void bDrawSetBuffer (bDrawBuffer *buffer);
    295305void bDrawSetColor (bDrawBuffer *buffer, bDrawColor color);
     
    312322void bDrawTriOpen  (bDrawBuffer *buffer, double x1, double y1, double x2, double y2, double x3, double y3);
    313323void bDrawTriFill  (bDrawBuffer *buffer, double x1, double y1, double dx, double dy);
     324void bDrawPolyFill (bDrawBuffer *buffer, double *x, double *y, int Npoints);
     325
     326void bDrawSmooth (bDrawBuffer *buffer, float sigma);
    314327
    315328/* bDrawRotFont.c */
  • trunk/Ohana/src/libkapa/src/KapaStyles.c

    r40106 r41156  
    5454  if (!strcasecmp (string,  "outline")) return KAPA_PLOT_BARS_OUTLINE;
    5555  if (!strcasecmp (string,  "outfill")) return KAPA_PLOT_BARS_OUTFILL;
     56
     57  if (!strcasecmp (string,  "polygon"))   return KAPA_PLOT_POLYGON;
     58  if (!strcasecmp (string,  "polyfill"))  return KAPA_PLOT_POLYFILL;
    5659
    5760  if (strlen(string) > 2) {
  • trunk/Ohana/src/libkapa/src/KapaWindow.c

    r40570 r41156  
    455455}
    456456
     457int KapaSetSmoothSigma (int fd, float sigma) {
     458
     459  KiiSendCommand (fd, 4, "SIGM");
     460  KiiSendMessage (fd, "%4.1f ", sigma);
     461  KiiWaitAnswer (fd, "DONE");
     462  return (TRUE);
     463}
     464
     465int KapaMemoryDump (int fd) {
     466
     467  KiiSendCommand (fd, 4, "MEMD");
     468  KiiWaitAnswer (fd, "DONE");
     469  return (TRUE);
     470}
     471
     472int KapaMemoryDumpLines (int fd, int Nlines) {
     473
     474  KiiSendCommand (fd, 4, "MEML");
     475  KiiSendMessage (fd, "%d ", Nlines);
     476  KiiWaitAnswer (fd, "DONE");
     477  return (TRUE);
     478}
     479
     480int KapaMemoryDumpOnExit (int fd, int state) {
     481
     482  KiiSendCommand (fd, 4, "MEMX");
     483  KiiSendMessage (fd, "%d ", state);
     484  KiiWaitAnswer (fd, "DONE");
     485  return (TRUE);
     486}
     487
  • trunk/Ohana/src/libkapa/src/RotFont.c

    r39576 r41156  
    3232  strncpy (currentname, RotFonts[DEFFONT].name, 63); currentname[63] = 0;
    3333  currentsize = RotFonts[DEFFONT].size;
     34}
     35
     36void FreeRotFonts (void) {
     37  free (RotFonts);
     38  RotFonts = FALSE;
     39  RotFontInited = FALSE;
    3440}
    3541
  • trunk/Ohana/src/libkapa/src/bDrawFuncs.c

    r40572 r41156  
    11# include <kapa_internal.h>
    22
    3 // move these to the bDrawBuffer type
    4 // static int bWeight;
    5 // static int bType;
    6 // static bDrawColor bColor;
    7 // static bDrawColor bColor_R;
    8 // static bDrawColor bColor_G;
    9 // static bDrawColor bColor_B;
    10 // static bDrawBuffer *bBuffer;
     3// buffer->pixels carries the plot image
     4// buffer->mask is 0 if the pixel is untouched, 1 if the pixel has data
    115
    126void bDrawCircleSingle (bDrawBuffer *buffer, double xc, double yc, double radius);
     7
     8int bDrawMerge (bDrawBuffer *base, bDrawBuffer *layer) {
     9
     10  // the two bDrawBuffers must match in size and depth
     11
     12  if (base->Nx != layer->Nx) return FALSE;
     13  if (base->Ny != layer->Ny) return FALSE;
     14  if (base->Nbyte != layer->Nbyte) return FALSE;
     15
     16  for (int j = 0; j < base->Ny; j++) {
     17    for (int i = 0; i < base->Nx; i++) {
     18
     19      if (!layer->mask[j][i]) continue;
     20     
     21      // completely opaque top layer:
     22      if (base->Nbyte == 1) {
     23        base->pixels[j][i] = layer->pixels[j][i];
     24      } else {
     25        base->pixels[j][3*i+0] = layer->pixels[j][3*i+0];
     26        base->pixels[j][3*i+1] = layer->pixels[j][3*i+1];
     27        base->pixels[j][3*i+2] = layer->pixels[j][3*i+2];
     28      }
     29    }
     30  }
     31  return TRUE;
     32}
    1333
    1434// create a drawing buffer with either 1 or 3 byte colors
     
    3555
    3656  ALLOCATE (buffer[0].pixels, bDrawColor *, Ny);
     57  ALLOCATE (buffer[0].mask, char *, Ny);
    3758  for (i = 0; i < Ny; i++) {
    3859    ALLOCATE (buffer[0].pixels[i], bDrawColor, Nbyte*Nx);
     60    ALLOCATE (buffer[0].mask[i], char, Nx);
    3961    for (j = 0; j < Nx; j++) {
    4062      if (Nbyte == 1) {
     
    4567        buffer[0].pixels[i][3*j+2] = white_B;
    4668      }
     69      buffer[0].mask[i][j] = 0; // for now: 0 = no data, 1 = data
    4770    }
    4871  }
     
    6386  for (i = 0; i < buffer[0].Ny; i++) {
    6487    free (buffer[0].pixels[i]);
     88    free (buffer[0].mask[i]);
    6589  }
    6690  free (buffer[0].pixels);
    67   free (buffer[0].palette);
     91  free (buffer[0].mask);
     92  // free (buffer[0].palette);
    6893  free (buffer);
    6994  return;
     
    121146    buffer[0].pixels[y][x] = buffer->bColor;
    122147  } else {
    123     // buffer[0].pixels[y][3*x+0] = buffer->bColor_R;
    124     // buffer[0].pixels[y][3*x+1] = buffer->bColor_G;
    125     // buffer[0].pixels[y][3*x+2] = buffer->bColor_B;
    126     buffer[0].pixels[y][3*x+0] = MAX (0x00, MIN(0xff, beta * buffer[0].pixels[y][3*x+0] + alpha * buffer->bColor_R));
     148    buffer[0].pixels[y][3*x+0] = MAX (0x00, MIN(0xff, beta * buffer[0].pixels[y][3*x+0] + alpha * buffer->bColor_R)); // was just buffer->bColor_R, etc
    127149    buffer[0].pixels[y][3*x+1] = MAX (0x00, MIN(0xff, beta * buffer[0].pixels[y][3*x+1] + alpha * buffer->bColor_G));
    128150    buffer[0].pixels[y][3*x+2] = MAX (0x00, MIN(0xff, beta * buffer[0].pixels[y][3*x+2] + alpha * buffer->bColor_B));
    129151  }
     152  buffer[0].mask[y][x] = 1;
    130153  return;
    131154}
     
    150173void bDrawRectOpen (bDrawBuffer *buffer, double x1, double y1, double x2, double y2) {
    151174
    152   int X1, Y1, X2, Y2;
    153 
    154175  if (x1 > x2) SWAP (x1, x2);
    155176  if (y1 > y2) SWAP (y1, y2);
    156177
     178  int X1 = MIN (MAX (ROUND (x1), 0), buffer[0].Nx - 1);
     179  int X2 = MIN (MAX (ROUND (x2), 1), buffer[0].Nx - 1);
     180
     181  int Y1 = MIN (MAX (ROUND (y1), 0), buffer[0].Ny - 1);
     182  int Y2 = MIN (MAX (ROUND (y2), 1), buffer[0].Ny - 1);
     183
     184  int dNs = -0.5*(buffer->bWeight - 1);
     185  /* 0, 0, 0, -1, -1, -2, -2 */
     186
     187  int dNe = +0.5*buffer->bWeight + 1;
     188  /* 1, 1, 2, 2, 2, 3, 3 */
     189
     190  for (int dN = dNs; dN < dNe; dN ++) {
     191    // line on the bottom needs to run longer for the negative dN values
     192    bDrawLineHorizontal (buffer, X1 + dN, X2 + 1 - dN, Y1 + dN);
     193
     194    // line on the top needs to run longer for the positive dN values
     195    bDrawLineHorizontal (buffer, X1 + dN, X2 + 1 - dN, Y2 - dN);
     196
     197    // line on the left needs to run longer for the negative dN values
     198    bDrawLineVertical   (buffer, X1 + dN, Y1 + dN, Y2 - dN);
     199
     200    // line on the right needs to run longer for the positive dN values
     201    bDrawLineVertical   (buffer, X2 - dN, Y1 + dN, Y2 - dN);
     202  }
     203  return;
     204}
     205
     206void bDrawRectFill (bDrawBuffer *buffer, double x1, double y1, double x2, double y2) {
     207
     208  int i;
     209  int X1, Y1, X2, Y2;
     210
     211  if (x1 > x2) SWAP (x1, x2);
     212  if (y1 > y2) SWAP (y1, y2);
     213
    157214  X1 = MIN (MAX (ROUND (x1), 0), buffer[0].Nx - 1);
    158215  X2 = MIN (MAX (ROUND (x2), 1), buffer[0].Nx - 1);
    159216
    160217  Y1 = MIN (MAX (ROUND (y1), 0), buffer[0].Ny - 1);
    161   Y2 = MIN (MAX (ROUND (y2), 1), buffer[0].Ny - 1);
    162 
    163   bDrawLineHorizontal (buffer, X1, X2 + 1, Y1);
    164   bDrawLineHorizontal (buffer, X1, X2 + 1, Y2);
    165   bDrawLineVertical   (buffer, X1, Y1, Y2);
    166   bDrawLineVertical   (buffer, X2, Y1, Y2);
    167   return;
    168 }
    169 
    170 void bDrawRectFill (bDrawBuffer *buffer, double x1, double y1, double x2, double y2) {
    171 
    172   int i;
    173   int X1, Y1, X2, Y2;
    174 
    175   if (x1 > x2) SWAP (x1, x2);
    176   if (y1 > y2) SWAP (y1, y2);
    177 
    178   X1 = MIN (MAX (ROUND (x1), 0), buffer[0].Nx - 1);
    179   X2 = MIN (MAX (ROUND (x2), 1), buffer[0].Nx - 1);
    180 
    181   Y1 = MIN (MAX (ROUND (y1), 0), buffer[0].Ny - 1);
    182218  Y2 = MIN (MAX (ROUND (y2), 0), buffer[0].Ny - 1);
    183219
    184220  for (i = Y1; i < Y2; i++) {
     221    // this should be a line of width 1 or we duplicate pixels
    185222    bDrawLineHorizontal (buffer, X1, X2, i);
    186223  }
     
    235272// use the Bresenham line drawing technique
    236273// integer-only Bresenham line-draw version which is fast
     274// bresenham assumes x1 < x2 and (y2 - y1) < (x2 - x1)
    237275void bDrawLineBresen (bDrawBuffer *buffer, int X1, int Y1, int X2, int Y2, int swapcoords) {
    238276
     
    299337      buffer[0].pixels[Y][3*i+1] = MAX (0x00, MIN(0xff, beta * buffer[0].pixels[Y][3*i+1] + alpha * buffer->bColor_G));
    300338      buffer[0].pixels[Y][3*i+2] = MAX (0x00, MIN(0xff, beta * buffer[0].pixels[Y][3*i+2] + alpha * buffer->bColor_B));
    301       // buffer[0].pixels[Y][3*i+0] = buffer->bColor_R;
    302       // buffer[0].pixels[Y][3*i+1] = buffer->bColor_G;
    303       // buffer[0].pixels[Y][3*i+2] = buffer->bColor_B;
    304     }
     339    }
     340    buffer[0].mask[Y][i] = 1;
    305341  }
    306342  return;
     
    326362      buffer[0].pixels[i][3*X+1] = MAX (0x00, MIN(0xff, beta * buffer[0].pixels[i][3*X+1] + alpha * buffer->bColor_G));
    327363      buffer[0].pixels[i][3*X+2] = MAX (0x00, MIN(0xff, beta * buffer[0].pixels[i][3*X+2] + alpha * buffer->bColor_B));
    328       // buffer[0].pixels[i][3*X+0] = buffer->bColor_R;
    329       // buffer[0].pixels[i][3*X+1] = buffer->bColor_G;
    330       // buffer[0].pixels[i][3*X+2] = buffer->bColor_B;
    331     }
     364    }
     365    buffer[0].mask[i][X] = 1;
    332366  }
    333367  return;
     
    384418 
    385419  return;
     420}
     421
     422# define BOT_LEFT 0
     423# define BOT_RGHT 1
     424# define TOP_LEFT 2
     425# define TOP_RGHT 3
     426
     427// I should probably look up an appropriate recipe for this
     428// source code for XDrawPolyFill?
     429
     430int GetNextSeqNumber (int seq, int Npoint, int Clockwise, int LeftSide);
     431int bDrawFillBetweenSegments (bDrawBuffer *buffer, int *x, int *y, int ystart);
     432
     433void bDrawPolyFill (bDrawBuffer *buffer, double *x, double *y, int Npoints) {
     434
     435  // The coord list which is passed in (x,y) must be in order around the contour
     436  for (int i = 0; i < Npoints; i++) {
     437    fprintf (stderr, "%d : %f,%f\n", i, x[i], y[i]);
     438  }
     439
     440  // First, find the lowest point and start at that sequence number
     441  int iMin = 0;
     442  double yMin = y[iMin];
     443  for (int i = 1; i < Npoints; i++) {
     444    if (y[i] < yMin) { iMin = i; yMin = y[iMin]; }
     445  }
     446
     447  // we generate two line segments and will fill between them
     448  int xval[4];
     449  int yval[4];
     450
     451  // the starting point is a vertex
     452  xval[BOT_LEFT] = x[iMin];  yval[BOT_LEFT] = y[iMin];
     453  xval[BOT_RGHT] = x[iMin];  yval[BOT_RGHT] = y[iMin];
     454
     455  // get iNext, iPrev assuming ClockWise, then test
     456  int isCW = TRUE;
     457  int iNextLeft = GetNextSeqNumber (iMin, Npoints, isCW, TRUE); // TRUE => left-side
     458  int iNextRght = GetNextSeqNumber (iMin, Npoints, isCW, FALSE);
     459
     460  // if this is true, the points are not clockwise
     461  if (x[iNextLeft] > x[iNextRght]) {
     462    isCW = FALSE;
     463    int tmp = iNextLeft;
     464    iNextLeft = iNextRght;
     465    iNextRght = tmp;
     466  }
     467
     468  int iTL = iNextLeft; // sequence number of the top,left point
     469  int iTR = iNextRght; // sequence number of the top,right point
     470  xval[TOP_LEFT] = x[iTL]; yval[TOP_LEFT] = y[iTL];
     471  xval[TOP_RGHT] = x[iTR]; yval[TOP_RGHT] = y[iTR];
     472
     473  // we need to track the starting row, start at the bottom
     474  int ystart = yval[BOT_LEFT];
     475
     476  while (TRUE) {
     477    int isLeft = bDrawFillBetweenSegments (buffer, xval, yval, ystart);
     478
     479    // the last pair of segments in the sequence end at the same top point:
     480    if (iTL == iTR) break;
     481
     482    // after one pass, if isLeft is true, then cycle the points on the left
     483    // segment, otherwise cycle the right segment:
     484
     485    if (isLeft) {
     486      iTL = GetNextSeqNumber (iTL, Npoints, isCW, TRUE);
     487      xval[BOT_LEFT] = xval[TOP_LEFT]; yval[BOT_LEFT] = yval[TOP_LEFT];
     488      xval[TOP_LEFT] = x[iTL];         yval[TOP_LEFT] = y[iTL];
     489      ystart = yval[BOT_LEFT];
     490    } else {
     491      iTR = GetNextSeqNumber (iTR, Npoints, isCW, FALSE);
     492      xval[BOT_RGHT] = xval[TOP_RGHT]; yval[BOT_RGHT] = yval[TOP_RGHT];
     493      xval[TOP_RGHT] = x[iTR];         yval[TOP_RGHT] = y[iTR];
     494      ystart = yval[BOT_RGHT];
     495    }
     496  }
     497  return;
     498}
     499
     500// we have two line segments defined by x[],y[]. 
     501
     502// [0],[1] is the left-side segment
     503// [2],[3] is the right-side segment
     504
     505// Fill the region between the two segments until
     506// the lower of the two y coordinates y[1], y[3]
     507
     508// return which of y[1] or y[3] was the ending row
     509
     510int bDrawFillBetweenSegments (bDrawBuffer *buffer, int *x, int *y, int ystart) {
     511
     512  int dY_L = y[TOP_LEFT] - y[BOT_LEFT];
     513  int dX_L = x[TOP_LEFT] - x[BOT_LEFT];
     514
     515  int dY_R = y[TOP_RGHT] - y[BOT_RGHT];
     516  int dX_R = x[TOP_RGHT] - x[BOT_RGHT];
     517   
     518  double Slope_L = (dY_L == 0) ? NAN : dX_L / (double) dY_L;
     519  double Slope_R = (dY_R == 0) ? NAN : dX_R / (double) dY_R;
     520
     521  // stop at whichever comes first
     522  // XXX not sure if I need to use < or <= here:
     523  // with <=, the value of Y after the loop will be one too high.
     524  int Y;
     525  for (Y = ystart; (Y < y[TOP_LEFT]) && (Y < y[TOP_RGHT]); Y++) {
     526
     527    // calculating X_L, X_R based on the slope and current y point
     528    int X_L = (dY_L == 0) ? x[BOT_LEFT] : (Y - y[BOT_LEFT]) * Slope_L + x[BOT_LEFT];
     529    int X_R = (dY_R == 0) ? x[BOT_RGHT] : (Y - y[BOT_RGHT]) * Slope_R + x[BOT_RGHT];
     530     
     531    // draw horizontal line from X_L to X_R at Y
     532    bDrawLineHorizontal (buffer, X_L, X_R, Y);
     533  }
     534
     535  if (Y == y[TOP_LEFT]) {
     536    return TRUE; // TRUE is LEFT SIDE
     537  } else {
     538    return FALSE;
     539  }
     540}
     541
     542int GetNextSeqNumber (int seq, int Npoints, int Clockwise, int LeftSide) {
     543
     544  int iNext;
     545
     546  if (Clockwise) {
     547    if (LeftSide) {
     548      // next point is next in sequence
     549      iNext = (seq < Npoints - 1) ? seq + 1 : 0;
     550    } else {
     551      // next point is prev in sequence
     552      iNext = (seq > 0) ? seq - 1 : Npoints - 1;
     553    }
     554  } else {
     555    if (LeftSide) {
     556      // next point is prev in sequence
     557      iNext = (seq > 0) ? seq - 1 : Npoints - 1;
     558    } else {
     559      // next point is next in sequence
     560      iNext = (seq < Npoints - 1) ? seq + 1 : 0;
     561    }
     562  }
     563  return iNext;
    386564}
    387565
     
    585763  if (x == 0) {
    586764    if (decrementY) {
     765      // this should must be a line or width 1 or we duplicate pixels
    587766      bDrawLineHorizontal (buffer, Xc    , Xc + 1, Yc + y);
    588767      bDrawLineHorizontal (buffer, Xc    , Xc + 1, Yc - y);
     
    590769
    591770    // center line
     771    // this should must be a line or width 1 or we duplicate pixels
    592772    bDrawLineHorizontal (buffer, Xc - y, Xc + y + 1, Yc    );
    593773    return;
     
    595775
    596776  if (x == y) {
     777    // this should must be a line or width 1 or we duplicate pixels
    597778    bDrawLineHorizontal (buffer, Xc - x, Xc + x + 1, Yc + y);
    598779    bDrawLineHorizontal (buffer, Xc - x, Xc + x + 1, Yc - y);
     
    602783  // only draw these two lines if we decrement y
    603784  if (decrementY) {
     785    // this must be a line or width 1 or we duplicate pixels
    604786    bDrawLineHorizontal (buffer, Xc - x, Xc + x + 1, Yc + y);
    605787    bDrawLineHorizontal (buffer, Xc - x, Xc + x + 1, Yc - y);
     
    607789
    608790  // always draw these two lines:
     791  // this must be a line or width 1 or we duplicate pixels
    609792  bDrawLineHorizontal (buffer, Xc - y, Xc + y + 1, Yc + x);
    610793  bDrawLineHorizontal (buffer, Xc - y, Xc + y + 1, Yc - x);
     
    648831}
    649832
     833// run a smoothing kernel on each channel for anti-aliasing
     834// XXX I need to consider the mask as well
     835void bDrawSmooth (bDrawBuffer *buffer, float sigma) {
     836
     837  // generate a temp buffer for storage of the smoothed result
     838  int Nx = buffer[0].Nx;
     839  int Ny = buffer[0].Ny;
     840  ALLOCATE_PTR (temp, bDrawColor, Nx*Ny);
     841
     842  //* build a 1D gaussian
     843  int Nsigma = 2;
     844  int Ns = (int) (Nsigma*sigma + 0.5);
     845  int Ngauss = 2*Ns + 1;
     846  ALLOCATE_PTR (gaussnorm, float, Ngauss);
     847  float *gauss = &gaussnorm[Ns];
     848  for (int i = -Ns; i < Ns + 1; i++) {
     849    gauss[i] = exp ((i*i)/(-2*sigma*sigma));
     850  }
     851
     852  // NOTE XXX: need to handle Nbyte = 1 or 3
     853  int Nchannel = 3;
     854
     855  // we need to smooth the 3 channels independently, do this as three passes
     856  for (int ch = 0; ch < Nchannel; ch++) {
     857
     858    // smooth in X direction
     859    for (int j = 0; j < Ny; j++) {
     860      bDrawColor *vi = (bDrawColor *) &buffer[0].pixels[j][ch];
     861      bDrawColor *vo = &temp[j*Nx];
     862      for (int i = 0; i < Nx; i++, vo++, vi += Nchannel) {
     863        float g = 0.0, s = 0.0;
     864        for (int n = -Ns; n <= Ns; n++) {
     865          if (i+n < 0) continue;
     866          if (i+n >= Nx) continue;
     867          s += gauss[n]*vi[Nchannel*n];
     868          g += gauss[n];
     869        }
     870        *vo = s / g;
     871      }
     872    }
     873
     874    // NOTE: output maps back into original image
     875    // careful on the counting
     876
     877    /* smooth in Y direction */
     878    for (int i = 0; i < Nx; i++) {
     879      bDrawColor *vi = &temp[i];
     880      for (int j = 0; j < Ny; j++) {
     881        float g = 0.0, s = 0.0;
     882        for (int n = -Ns; n <= Ns; n++) {
     883          if (j+n < 0) continue;
     884          if (j+n >= Ny) continue;
     885          s += gauss[n]*vi[(n+j)*Nx]; // vi is a single-index array, so this is stepping by rows
     886          g += gauss[n];
     887        }
     888        buffer[0].pixels[j][Nchannel*i + ch] = s / g;
     889      }
     890    }
     891  }
     892
     893  // smooth the mask
     894  ALLOCATE_PTR (temp_mask, float, Nx*Ny);
     895
     896  // smooth in X direction
     897  for (int j = 0; j < Ny; j++) {
     898    char *vi = (char *) &buffer[0].mask[j][0];
     899    float *vo = &temp_mask[j*Nx];
     900    for (int i = 0; i < Nx; i++, vo++, vi++) {
     901        float g = 0.0, s = 0.0;
     902        for (int n = -Ns; n <= Ns; n++) {
     903          if (i+n < 0) continue;
     904          if (i+n >= Nx) continue;
     905          s += gauss[n]*vi[n];
     906          g += gauss[n];
     907        }
     908        *vo = s / g;
     909    }
     910  }
     911
     912  // NOTE: output maps back into original image
     913  // careful on the counting
     914
     915  /* smooth in Y direction */
     916  for (int i = 0; i < Nx; i++) {
     917    float *vi = &temp_mask[i];
     918    for (int j = 0; j < Ny; j++) {
     919        float g = 0.0, s = 0.0;
     920        for (int n = -Ns; n <= Ns; n++) {
     921          if (j+n < 0) continue;
     922          if (j+n >= Ny) continue;
     923          s += gauss[n]*vi[(n+j)*Nx]; // vi is a single-index array, so this is stepping by rows
     924          g += gauss[n];
     925        }
     926        buffer[0].mask[j][i] = (s / g > 0.05) ? 1 : 0;
     927    }
     928  }
     929
     930  free (temp);
     931  free (temp_mask);
     932  free (gaussnorm);
     933
     934  return;
     935}
     936
    650937/*
     938NOTES on Bresenham-style circles:
    651939the discriminant of inside or outside the circle is:
    652940
Note: See TracChangeset for help on using the changeset viewer.