- Timestamp:
- Nov 27, 2019, 10:54:47 AM (7 years ago)
- Location:
- trunk/Ohana/src/libkapa
- Files:
-
- 5 edited
-
include/kapa.h (modified) (6 diffs)
-
src/KapaStyles.c (modified) (1 diff)
-
src/KapaWindow.c (modified) (1 diff)
-
src/RotFont.c (modified) (1 diff)
-
src/bDrawFuncs.c (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Ohana/src/libkapa/include/kapa.h
r40558 r41156 45 45 KAPA_PLOT_BARS_OUTLINE = 4, 46 46 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, 48 50 } KapaPlotStyle; 49 51 … … 172 174 int Nx, Ny, Nbyte; 173 175 bDrawColor **pixels; 176 char **mask; 174 177 png_color *palette; 175 178 int Npalette; 179 176 180 // current drawing values: 177 181 int bWeight; … … 256 260 int KapaGetImageData (int fd, KapaImageData *graphmode); 257 261 int KapaSetToolbox (int fd, int location); 262 int KapaSetSmoothSigma (int fd, float sigma); 263 int KapaMemoryDump (int fd); 264 int KapaMemoryDumpLines (int fd, int Nlines); 265 int KapaMemoryDumpOnExit (int fd, int state); 258 266 259 267 /* KapaColors */ … … 272 280 /* RotFont.c */ 273 281 void InitRotFonts PROTO((void)); 282 void FreeRotFonts PROTO((void)); 274 283 int SetRotFont PROTO((char *name, int size)); 275 284 char *GetRotFont PROTO((int *size)); … … 292 301 bDrawBuffer *bDrawBufferCreate (int Nx, int Ny, int Nbyte, png_color *palette, int Npalette); 293 302 void bDrawBufferFree (bDrawBuffer *buffer); 303 int bDrawMerge (bDrawBuffer *base, bDrawBuffer *layer); 294 304 void bDrawSetBuffer (bDrawBuffer *buffer); 295 305 void bDrawSetColor (bDrawBuffer *buffer, bDrawColor color); … … 312 322 void bDrawTriOpen (bDrawBuffer *buffer, double x1, double y1, double x2, double y2, double x3, double y3); 313 323 void bDrawTriFill (bDrawBuffer *buffer, double x1, double y1, double dx, double dy); 324 void bDrawPolyFill (bDrawBuffer *buffer, double *x, double *y, int Npoints); 325 326 void bDrawSmooth (bDrawBuffer *buffer, float sigma); 314 327 315 328 /* bDrawRotFont.c */ -
trunk/Ohana/src/libkapa/src/KapaStyles.c
r40106 r41156 54 54 if (!strcasecmp (string, "outline")) return KAPA_PLOT_BARS_OUTLINE; 55 55 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; 56 59 57 60 if (strlen(string) > 2) { -
trunk/Ohana/src/libkapa/src/KapaWindow.c
r40570 r41156 455 455 } 456 456 457 int 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 465 int KapaMemoryDump (int fd) { 466 467 KiiSendCommand (fd, 4, "MEMD"); 468 KiiWaitAnswer (fd, "DONE"); 469 return (TRUE); 470 } 471 472 int 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 480 int 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 32 32 strncpy (currentname, RotFonts[DEFFONT].name, 63); currentname[63] = 0; 33 33 currentsize = RotFonts[DEFFONT].size; 34 } 35 36 void FreeRotFonts (void) { 37 free (RotFonts); 38 RotFonts = FALSE; 39 RotFontInited = FALSE; 34 40 } 35 41 -
trunk/Ohana/src/libkapa/src/bDrawFuncs.c
r40572 r41156 1 1 # include <kapa_internal.h> 2 2 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 11 5 12 6 void bDrawCircleSingle (bDrawBuffer *buffer, double xc, double yc, double radius); 7 8 int 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 } 13 33 14 34 // create a drawing buffer with either 1 or 3 byte colors … … 35 55 36 56 ALLOCATE (buffer[0].pixels, bDrawColor *, Ny); 57 ALLOCATE (buffer[0].mask, char *, Ny); 37 58 for (i = 0; i < Ny; i++) { 38 59 ALLOCATE (buffer[0].pixels[i], bDrawColor, Nbyte*Nx); 60 ALLOCATE (buffer[0].mask[i], char, Nx); 39 61 for (j = 0; j < Nx; j++) { 40 62 if (Nbyte == 1) { … … 45 67 buffer[0].pixels[i][3*j+2] = white_B; 46 68 } 69 buffer[0].mask[i][j] = 0; // for now: 0 = no data, 1 = data 47 70 } 48 71 } … … 63 86 for (i = 0; i < buffer[0].Ny; i++) { 64 87 free (buffer[0].pixels[i]); 88 free (buffer[0].mask[i]); 65 89 } 66 90 free (buffer[0].pixels); 67 free (buffer[0].palette); 91 free (buffer[0].mask); 92 // free (buffer[0].palette); 68 93 free (buffer); 69 94 return; … … 121 146 buffer[0].pixels[y][x] = buffer->bColor; 122 147 } 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 127 149 buffer[0].pixels[y][3*x+1] = MAX (0x00, MIN(0xff, beta * buffer[0].pixels[y][3*x+1] + alpha * buffer->bColor_G)); 128 150 buffer[0].pixels[y][3*x+2] = MAX (0x00, MIN(0xff, beta * buffer[0].pixels[y][3*x+2] + alpha * buffer->bColor_B)); 129 151 } 152 buffer[0].mask[y][x] = 1; 130 153 return; 131 154 } … … 150 173 void bDrawRectOpen (bDrawBuffer *buffer, double x1, double y1, double x2, double y2) { 151 174 152 int X1, Y1, X2, Y2;153 154 175 if (x1 > x2) SWAP (x1, x2); 155 176 if (y1 > y2) SWAP (y1, y2); 156 177 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 206 void 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 157 214 X1 = MIN (MAX (ROUND (x1), 0), buffer[0].Nx - 1); 158 215 X2 = MIN (MAX (ROUND (x2), 1), buffer[0].Nx - 1); 159 216 160 217 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);182 218 Y2 = MIN (MAX (ROUND (y2), 0), buffer[0].Ny - 1); 183 219 184 220 for (i = Y1; i < Y2; i++) { 221 // this should be a line of width 1 or we duplicate pixels 185 222 bDrawLineHorizontal (buffer, X1, X2, i); 186 223 } … … 235 272 // use the Bresenham line drawing technique 236 273 // integer-only Bresenham line-draw version which is fast 274 // bresenham assumes x1 < x2 and (y2 - y1) < (x2 - x1) 237 275 void bDrawLineBresen (bDrawBuffer *buffer, int X1, int Y1, int X2, int Y2, int swapcoords) { 238 276 … … 299 337 buffer[0].pixels[Y][3*i+1] = MAX (0x00, MIN(0xff, beta * buffer[0].pixels[Y][3*i+1] + alpha * buffer->bColor_G)); 300 338 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; 305 341 } 306 342 return; … … 326 362 buffer[0].pixels[i][3*X+1] = MAX (0x00, MIN(0xff, beta * buffer[0].pixels[i][3*X+1] + alpha * buffer->bColor_G)); 327 363 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; 332 366 } 333 367 return; … … 384 418 385 419 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 430 int GetNextSeqNumber (int seq, int Npoint, int Clockwise, int LeftSide); 431 int bDrawFillBetweenSegments (bDrawBuffer *buffer, int *x, int *y, int ystart); 432 433 void 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 510 int 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 542 int 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; 386 564 } 387 565 … … 585 763 if (x == 0) { 586 764 if (decrementY) { 765 // this should must be a line or width 1 or we duplicate pixels 587 766 bDrawLineHorizontal (buffer, Xc , Xc + 1, Yc + y); 588 767 bDrawLineHorizontal (buffer, Xc , Xc + 1, Yc - y); … … 590 769 591 770 // center line 771 // this should must be a line or width 1 or we duplicate pixels 592 772 bDrawLineHorizontal (buffer, Xc - y, Xc + y + 1, Yc ); 593 773 return; … … 595 775 596 776 if (x == y) { 777 // this should must be a line or width 1 or we duplicate pixels 597 778 bDrawLineHorizontal (buffer, Xc - x, Xc + x + 1, Yc + y); 598 779 bDrawLineHorizontal (buffer, Xc - x, Xc + x + 1, Yc - y); … … 602 783 // only draw these two lines if we decrement y 603 784 if (decrementY) { 785 // this must be a line or width 1 or we duplicate pixels 604 786 bDrawLineHorizontal (buffer, Xc - x, Xc + x + 1, Yc + y); 605 787 bDrawLineHorizontal (buffer, Xc - x, Xc + x + 1, Yc - y); … … 607 789 608 790 // always draw these two lines: 791 // this must be a line or width 1 or we duplicate pixels 609 792 bDrawLineHorizontal (buffer, Xc - y, Xc + y + 1, Yc + x); 610 793 bDrawLineHorizontal (buffer, Xc - y, Xc + y + 1, Yc - x); … … 648 831 } 649 832 833 // run a smoothing kernel on each channel for anti-aliasing 834 // XXX I need to consider the mask as well 835 void 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 650 937 /* 938 NOTES on Bresenham-style circles: 651 939 the discriminant of inside or outside the circle is: 652 940
Note:
See TracChangeset
for help on using the changeset viewer.
