static void analyzeDistribution(struct pam * const inpamP, bool const verbose, const unsigned int ** const histogramP, struct range * const rangeP) { /*---------------------------------------------------------------------------- Find the distribution of the sample values -- minimum, maximum, and how many of each value -- in input image *inpamP, whose file is positioned to the raster. Return the minimum and maximum as *rangeP and the frequency distribution as *histogramP, an array such that histogram[i] is the number of pixels that have sample value i. Assume the file is positioned to the raster upon entry and leave it positioned at the same place. -----------------------------------------------------------------------------*/ unsigned int row; tuple * inrow; tuplen * inrown; unsigned int * histogram; /* malloced array */ unsigned int i; pm_filepos rasterPos; /* Position in input file of the raster */ pm_tell2(inpamP->file, &rasterPos, sizeof(rasterPos)); inrow = pnm_allocpamrow(inpamP); inrown = pnm_allocpamrown(inpamP); MALLOCARRAY(histogram, inpamP->maxval+1); if (histogram == NULL) pm_error("Unable to allocate space for %lu-entry histogram", inpamP->maxval+1); /* Initialize histogram -- zero occurrences of everything */ for (i = 0; i <= inpamP->maxval; ++i) histogram[i] = 0; initRange(rangeP); for (row = 0; row < inpamP->height; ++row) { unsigned int col; pnm_readpamrow(inpamP, inrow); pnm_normalizeRow(inpamP, inrow, NULL, inrown); for (col = 0; col < inpamP->width; ++col) { ++histogram[inrow[col][0]]; addToRange(rangeP, inrown[col][0]); } } *histogramP = histogram; pnm_freepamrow(inrow); pnm_freepamrown(inrown); pm_seek2(inpamP->file, &rasterPos, sizeof(rasterPos)); if (verbose) pm_message("Pixel values range from %f to %f", rangeP->min, rangeP->max); }
struct Button* initSongButton(int x, int y, char* name, int id, struct Frame* panel){ struct Button* sb = initButton(); sb->name = name; sb->Panel = panel; sb->range = initRange(x, y, 79, 10); sb->x_pos = x; sb->y_pos = y; sb->draw = drawTxtButton; sb->collide = songButtonCollide; sb->id = id; return sb; }
struct Button* initMenuButton(int x, char* name, int type, struct Frame* menuFrame){ struct Button* b = initButton(); b->range = initRange(x, 1, 30, 10); b->name = name; b->x_pos = x; b->y_pos = 1; // all menu buttons have to be drawn at y = 1 b->draw = drawTxtButton; b->type = type; b->collide = menuButtonCollide; b->Panel = menuFrame; b->buttonType = menu; return b; }
static void getLocalThreshold(tuplen ** const inrows, unsigned int const windowWidth, unsigned int const x, unsigned int const localWidth, unsigned int const localHeight, float const darkness, float const minSpread, samplen const defaultThreshold, samplen * const thresholdP) { /*---------------------------------------------------------------------------- Find a suitable threshold in local area around one pixel. inrows[][] is a an array of 'windowWidth' pixels by 'localHeight'. 'x' is a column number within the window. We look at the rectangle consisting of the 'localWidth' columns surrounding x, all rows. If x is near the left or right edge, we truncate the window as needed. We base the threshold on the local spread (difference between minimum and maximum sample values in the local areas) and the 'darkness' factor. A higher 'darkness' gets a higher threshold. If the spread is less than 'minSpread', we return 'defaultThreshold' and 'darkness' is irrelevant. 'localWidth' must be odd. -----------------------------------------------------------------------------*/ unsigned int const startCol = x >= localWidth/2 ? x - localWidth/2 : 0; unsigned int col; struct range localRange; assert(localWidth % 2 == 1); /* entry condition */ initRange(&localRange); for (col = startCol; col <= x + localWidth/2 && col < windowWidth; ++col) { unsigned int row; for (row = 0; row < localHeight; ++row) addToRange(&localRange, inrows[row][col][0]); } if (spread(localRange) < minSpread) *thresholdP = defaultThreshold; else *thresholdP = localRange.min + darkness * spread(localRange); }
void LaserMessage::init(int num_readings, int num_remissions) { if (m_msg != NULL) { freeRange(); freeRemission(); } else { m_msg = new carmen_laser_laser_message; carmen_test_alloc(m_msg); } carmen_erase_structure(m_msg, sizeof(carmen_laser_laser_message)); m_msg->config = LaserConfig(); initRange(num_readings); initRemission(num_remissions); }
static void thresholdLocal(struct pam * const inpamP, struct pam * const outpamP, struct cmdlineInfo const cmdline) { /*---------------------------------------------------------------------------- Threshold the image described by *inpamP, whose file is positioned to the raster, and output the resulting raster to the image described by *outpamP. Use local adaptive thresholding aka dynamic thresholding or dual thresholding (global for low contrast areas, LAT otherwise) -----------------------------------------------------------------------------*/ struct range globalRange; /* Range of sample values in entire image */ tuplen ** inrows; /* vertical window of image containing the local area. This is a ring of 'windowHeight' rows. Row R of the image, when it is in the window, is inrows[R % windowHeight]. */ unsigned int windowHeight; /* size of 'inrows' window */ unsigned int nextRowToRead; /* Number of the next row to be read from the file into the inrows[] buffer. */ tuple * outrow; /* raw output row */ unsigned int row; /* Number of the current row. The current row is normally the one in the center of the inrows[] buffer (which has an actual center row because it is of odd height), but when near the top and bottom edge of the image, it is not. */ const unsigned int * histogram; samplen globalThreshold; /* This is a threshold based on the entire image, to use in areas where the contrast is too small to use a locally-derived threshold. */ unsigned int oddLocalWidth; unsigned int oddLocalHeight; unsigned int i; /* use a subimage with odd width and height to have a middle pixel */ if (cmdline.width % 2 == 0) oddLocalWidth = cmdline.width + 1; else oddLocalWidth = cmdline.width; if (cmdline.height % 2 == 0) oddLocalHeight = cmdline.height + 1; else oddLocalHeight = cmdline.height; windowHeight = MIN(oddLocalHeight, inpamP->height); /* global information is needed for dual thresholding */ if (cmdline.dual) { analyzeDistribution(inpamP, cmdline.verbose, &histogram, &globalRange); computeGlobalThreshold(inpamP, histogram, globalRange, &globalThreshold); } else { histogram = NULL; initRange(&globalRange); globalThreshold = 1.0; } outrow = pnm_allocpamrow(outpamP); MALLOCARRAY(inrows, windowHeight); if (inrows == NULL) pm_error("Unable to allocate memory for a %u-row array", windowHeight); for (i = 0; i < windowHeight; ++i) inrows[i] = pnm_allocpamrown(inpamP); /* Fill the vertical window buffer */ nextRowToRead = 0; while (nextRowToRead < windowHeight) pnm_readpamrown(inpamP, inrows[nextRowToRead++ % windowHeight]); for (row = 0; row < inpamP->height; ++row) { thresholdLocalRow(inpamP, inrows, oddLocalWidth, windowHeight, row, cmdline, globalRange, globalThreshold, outpamP, outrow); pnm_writepamrow(outpamP, outrow); /* read next image line if available and necessary */ if (row + windowHeight / 2 >= nextRowToRead && nextRowToRead < inpamP->height) pnm_readpamrown(inpamP, inrows[nextRowToRead++ % windowHeight]); } free((void*)histogram); for (i = 0; i < windowHeight; ++i) pnm_freepamrow(inrows[i]); free(inrows); pnm_freepamrow(outrow); }