static void createBmepsOutputEncoder(struct bmepsoe ** const bmepsoePP, FILE * const ofP, bool const rle, bool const flate, bool const ascii85) { unsigned int const FLATE_IN_SIZE = 16384; unsigned int const FLATE_OUT_SIZE = 17408; struct bmepsoe * bmepsoeP; int mode; MALLOCVAR_NOFAIL(bmepsoeP); MALLOCVAR_NOFAIL(bmepsoeP->oeP); MALLOCARRAY_NOFAIL(bmepsoeP->rleBuffer, 129); MALLOCARRAY_NOFAIL(bmepsoeP->flateInBuffer, FLATE_IN_SIZE); MALLOCARRAY_NOFAIL(bmepsoeP->flateOutBuffer, FLATE_OUT_SIZE); mode = 0; if (rle) mode |= OE_RL; if (flate) mode |= OE_FLATE; if (ascii85) mode |= OE_ASC85; oe_init(bmepsoeP->oeP, ofP, mode, 9, bmepsoeP->rleBuffer, bmepsoeP->flateInBuffer, FLATE_IN_SIZE, bmepsoeP->flateOutBuffer, FLATE_OUT_SIZE); *bmepsoePP = bmepsoeP; }
/* * Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the * encoding mechanism is different. * * I didn't re-use the code from ppmtobmp since I need to keep the * bitmaps in memory till I've loaded all ppms. * * 8bpp => 1 byte/palette index. * 4bpp => High Nibble, Low Nibble * 1bpp => 1 palette value per bit, high bit 1st. */ static ICON_bmp create1Bitmap (pixel ** const pa, int const cols, int const rows, colorhash_table const cht) { /* * How wide should the u1 string for each row be? * each byte is 8 pixels, but must be a multiple of 4 bytes. */ ICON_bmp icBitmap; int xBytes,y,x; int wt = cols; u1 ** rowData; MALLOCVAR_NOFAIL(icBitmap); wt >>= 3; if (wt & 3) { wt = (wt & ~3) + 4; } xBytes = wt; MALLOCARRAY_NOFAIL(rowData, rows); icBitmap->xBytes = xBytes; icBitmap->data = rowData; icBitmap->size = xBytes * rows; for (y=0;y<rows;y++) { u1 * row; int byteOn = 0; int bitOn = 128; int value; MALLOCARRAY_NOFAIL(row, xBytes); memset (row, 0, xBytes); rowData[rows-y-1] = row; /* * Check there's a pixel array, otherwise we're just faking this... */ if (pa) { for (x=0;x<cols;x++) { /* * So we've got a colorhash_table with two colors in it. * Which is black?! * * Unless the hashing function changes, 0's black. */ value = ppm_lookupcolor(cht, &pa[y][x]); if (!value) { /* leave black. */ } else { row[byteOn] |= bitOn; } if (bitOn == 1) { byteOn++; bitOn = 128; } else { bitOn >>= 1; } } } } return icBitmap; }
Image * newRGBImage(unsigned int const width, unsigned int const height, unsigned int const depth) { unsigned int const pixlen = depth > 0 ? (depth + 7) / 8 : 1; /* Special case for "zero" depth image, which is sometimes interpreted as "one color" */ unsigned int const numcolors = depthToColors(depth); Image * imageP; MALLOCVAR_NOFAIL(imageP); imageP->type = IRGB; newRGBMapData(&imageP->rgb, numcolors); imageP->width = width; imageP->height = height; imageP->depth = depth; imageP->pixlen = pixlen; if (UINT_MAX / width / height < pixlen) pm_error("Image dimensions %u x %u x %u are too big to compute.", width, height, pixlen); MALLOCARRAY(imageP->data, width * height * pixlen); if (imageP->data == NULL) pm_error("Unable to allocate %u x %u x %u raster array", width, height, pixlen); return imageP; }
Image * newBitImage(unsigned int const width, unsigned int const height) { unsigned int const linelen = (width + 7) / 8; Image * imageP; MALLOCVAR_NOFAIL(imageP); imageP->type = IBITMAP; newRGBMapData(&imageP->rgb, 2); imageP->rgb.red[0] = imageP->rgb.grn[0] = imageP->rgb.blu[0] = 65535; imageP->rgb.red[1] = imageP->rgb.grn[1] = imageP->rgb.blu[1] = 0; imageP->rgb.used = 2; imageP->width = width; imageP->height = height; imageP->depth = 1; if (UINT_MAX / linelen < height) pm_error("Image dimensions too big to compute: %u x %u", linelen, height); MALLOCARRAY(imageP->data, linelen * height); if (imageP->data == NULL) pm_error("Out of memory allocating array of %u x %u", linelen, height); return imageP; }
static void createoutputGenerator(struct cmdlineInfo const cmdline, const struct pam * const inPamP, outGenerator ** const outputGeneratorPP) { outGenerator * outGenP; MALLOCVAR_NOFAIL(outGenP); outGenP->pam.size = sizeof(struct pam); outGenP->pam.len = PAM_STRUCT_SIZE(tuple_type); outGenP->pam.file = stdout; outGenP->pam.height = inPamP->height + 3 * abs(cmdline.guidesize); /* Allow room for guides. */ outGenP->pam.width = inPamP->width; if (cmdline.patFilespec) { /* Background pixels should come from the pattern file. */ initPatternPixel(outGenP, cmdline); } else { /* Background pixels should be generated randomly */ initRandomColor(outGenP, inPamP, cmdline); } outGenP->pam.bytes_per_sample = pnm_bytespersample(outGenP->pam.maxval); *outputGeneratorPP = outGenP; }
static struct converter createFsConverter(struct pam * const graypamP, float const threshFraction) { struct fsState * stateP; struct converter converter; converter.cols = graypamP->width; converter.convertRow = &fsConvertRow; converter.destroy = &fsDestroy; MALLOCVAR_NOFAIL(stateP); /* Initialize Floyd-Steinberg error vectors. */ MALLOCARRAY_NOFAIL(stateP->thiserr, graypamP->width + 2); MALLOCARRAY_NOFAIL(stateP->nexterr, graypamP->width + 2); { /* (random errors in [-1/8 .. 1/8]) */ unsigned int col; for (col = 0; col < graypamP->width + 2; ++col) stateP->thiserr[col] = ((float)rand()/RAND_MAX - 0.5) / 4; } stateP->halfWhite = threshFraction; stateP->white = 2 * threshFraction; stateP->fs_forward = TRUE; converter.stateP = stateP; return converter; }
static void initPatternPixel(outGenerator * const outGenP, struct cmdlineInfo const cmdline) { struct patternPixelState * stateP; FILE * patternFileP; MALLOCVAR_NOFAIL(stateP); patternFileP = pm_openr(cmdline.patFilespec); stateP->patTuples = pnm_readpam(patternFileP, &stateP->patPam, PAM_STRUCT_SIZE(tuple_type)); pm_close(patternFileP); stateP->xshift = cmdline.xshift; stateP->yshift = cmdline.yshift; stateP->magnifypat = cmdline.magnifypat; outGenP->stateP = stateP; outGenP->getTuple = &patternPixel; outGenP->terminateState = &termPatternPixel; outGenP->pam.format = stateP->patPam.format; outGenP->pam.plainformat = stateP->patPam.plainformat; outGenP->pam.depth = stateP->patPam.depth; outGenP->pam.maxval = stateP->patPam.maxval; strcpy(outGenP->pam.tuple_type, stateP->patPam.tuple_type); if (cmdline.verbose) reportImageParameters("Pattern file", &stateP->patPam); }
static struct converter createAtkinsonConverter(struct pam * const graypamP, float const threshFraction) { struct atkinsonState * stateP; struct converter converter; unsigned int relRow; converter.cols = graypamP->width; converter.convertRow = &atkinsonConvertRow; converter.destroy = &atkinsonDestroy; MALLOCVAR_NOFAIL(stateP); for (relRow = 0; relRow < 3; ++relRow) MALLOCARRAY_NOFAIL(stateP->error[relRow], graypamP->width + 2); { /* (random errors in [-1/8 .. 1/8]) */ unsigned int col; for (col = 0; col < graypamP->width + 2; ++col) { stateP->error[0][col] = ((float)rand()/RAND_MAX - 0.5) / 4; stateP->error[1][col] = 0.0; stateP->error[2][col] = 0.0; } } stateP->halfWhite = threshFraction; stateP->white = 2 * threshFraction; converter.stateP = stateP; return converter; }
Image * newTrueImage(unsigned int const width, unsigned int const height) { unsigned int const pixlen = 3; Image * imageP; MALLOCVAR_NOFAIL(imageP); imageP->type = ITRUE; imageP->rgb.used = 0; imageP->rgb.size = 0; imageP->width = width; imageP->height = height; imageP->depth = 24; imageP->pixlen = 3; if (UINT_MAX / width / height < pixlen) pm_error("Image dimensions %u x %u x %u are too big to compute.", width, height, pixlen); MALLOCARRAY(imageP->data, width * height * pixlen); if (imageP->data == NULL) pm_error("Unable to allocate %u x %u x %u raster array", width, height, pixlen); return imageP; }
at_fitting_opts_type * at_fitting_opts_new(void) { at_fitting_opts_type * opts; MALLOCVAR_NOFAIL(opts); return opts; }
int pthread_create(pthread_t * const newThreadIdP, const pthread_attr_t * const attr, pthread_func * func, void * const arg) { HANDLE hThread; DWORD dwThreadID; struct winStartArg * winStartArgP; MALLOCVAR_NOFAIL(winStartArgP); winStartArgP->func = func; winStartArgP->arg = arg; hThread = (HANDLE) _beginthreadex( NULL, 0, &winThreadStart, (LPVOID)winStartArgP, CREATE_SUSPENDED, &dwThreadID); SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL); ResumeThread(hThread); *newThreadIdP = hThread; return hThread ? 0 : -1; }
static void createColormapFinder(struct pam * const pamP, tupletable const colormap, unsigned int const colors, struct colormapFinder ** const colormapFinderPP) { struct colormapFinder * colormapFinderP; MALLOCVAR_NOFAIL(colormapFinderP); colormapFinderP->colormap = colormap; colormapFinderP->colors = colors; { unsigned int const maxHandleableSqrDiff = (unsigned int)UINT_MAX / pamP->depth; if (SQR(pamP->maxval) > maxHandleableSqrDiff) colormapFinderP->distanceDivider = (unsigned int) (SQR(pamP->maxval) / maxHandleableSqrDiff + 0.1 + 1.0); /* The 0.1 is a fudge factor to keep us out of rounding trouble. The 1.0 effects a round-up. */ else colormapFinderP->distanceDivider = 1; } *colormapFinderPP = colormapFinderP; }
static ICON_bmp create4Bitmap (pixel ** const pa, int const cols, int const rows, colorhash_table const cht) { /* * How wide should the u1 string for each row be? * each byte is 8 pixels, but must be a multiple of 4 bytes. */ ICON_bmp icBitmap; int xBytes,y,x; int wt = cols; u1 ** rowData; MALLOCVAR_NOFAIL(icBitmap); wt >>= 1; if (wt & 3) { wt = (wt & ~3) + 4; } xBytes = wt; MALLOCARRAY_NOFAIL(rowData, rows); icBitmap->xBytes = xBytes; icBitmap->data = rowData; overflow2(xBytes, rows); icBitmap->size = xBytes * rows; for (y=0;y<rows;y++) { u1 * row; int byteOn = 0; int nibble = 1; /* high nibble = 1, low nibble = 0; */ int value; MALLOCARRAY_NOFAIL(row, xBytes); memset (row, 0, xBytes); rowData[rows-y-1] = row; /* * Check there's a pixel array, otherwise we're just faking this... */ if (pa) { for (x=0;x<cols;x++) { value = ppm_lookupcolor(cht, &pa[y][x]); /* * Shift it, if we're putting it in the high nibble. */ if (nibble) { value <<= 4; } row[byteOn] |= value; if (nibble) { nibble = 0; } else { nibble = 1; byteOn++; } } } } return icBitmap; }
at_output_opts_type * at_output_opts_new(void) { at_output_opts_type * opts; MALLOCVAR_NOFAIL(opts); opts->dpi = AT_DEFAULT_DPI; return opts; }
void xmlrpc_server_abyss_set_handler3( xmlrpc_env * const envP, TServer * const srvP, const xmlrpc_server_abyss_handler_parms * const parmsP, unsigned int const parmSize) { struct uriHandlerXmlrpc * uriHandlerXmlrpcP; size_t xmlProcessorMaxStackSize; MALLOCVAR_NOFAIL(uriHandlerXmlrpcP); if (!envP->fault_occurred) { if (parmSize >= XMLRPC_AHPSIZE(xml_processor)) uriHandlerXmlrpcP->xmlProcessor = parmsP->xml_processor; else xmlrpc_faultf(envP, "Parameter too short to contain the required " "'xml_processor' member"); } if (!envP->fault_occurred) { if (parmSize >= XMLRPC_AHPSIZE(xml_processor_arg)) uriHandlerXmlrpcP->xmlProcessorArg = parmsP->xml_processor_arg; else xmlrpc_faultf(envP, "Parameter too short to contain the required " "'xml_processor_arg' member"); } if (!envP->fault_occurred) { if (parmSize >= XMLRPC_AHPSIZE(xml_processor_max_stack)) xmlProcessorMaxStackSize = parmsP->xml_processor_max_stack; else xmlrpc_faultf(envP, "Parameter too short to contain the required " "'xml_processor_max_stack' member"); } if (!envP->fault_occurred) { if (parmSize >= XMLRPC_AHPSIZE(uri_path) && parmsP->uri_path) uriHandlerXmlrpcP->uriPath = xmlrpc_strdupsol(parmsP->uri_path); else uriHandlerXmlrpcP->uriPath = xmlrpc_strdupsol("/RPC2"); if (parmSize >= XMLRPC_AHPSIZE(chunk_response) && parmsP->chunk_response) uriHandlerXmlrpcP->chunkResponse = parmsP->chunk_response; else uriHandlerXmlrpcP->chunkResponse = false; interpretHttpAccessControl(parmsP, parmSize, &uriHandlerXmlrpcP->accessControl); if (envP->fault_occurred) xmlrpc_termAccessControl(&uriHandlerXmlrpcP->accessControl); } if (!envP->fault_occurred) setHandler(envP, srvP, uriHandlerXmlrpcP, xmlProcessorMaxStackSize); if (envP->fault_occurred) free(uriHandlerXmlrpcP); }
static ICON_bmp createAndBitmap (gray ** const ba, int const cols, int const rows, gray const maxval) { /* * How wide should the u1 string for each row be? * each byte is 8 pixels, but must be a multiple of 4 bytes. */ ICON_bmp icBitmap; int xBytes,y,x; int wt = cols; u1 ** rowData; MALLOCVAR_NOFAIL(icBitmap); wt >>= 3; if (wt & 3) { wt = (wt & ~3) + 4; } xBytes = wt; MALLOCARRAY_NOFAIL(rowData, rows); icBitmap->xBytes = xBytes; icBitmap->data = rowData; overflow2(xBytes, rows); icBitmap->size = xBytes * rows; for (y=0;y<rows;y++) { u1 * row; int byteOn = 0; int bitOn = 128; MALLOCARRAY_NOFAIL(row, xBytes); memset (row, 0, xBytes); rowData[rows-y-1] = row; /* * Check there's a bit array, otherwise we're just faking this... */ if (ba) { for (x=0;x<cols;x++) { /* Black (bit clear) is transparent in PGM alpha maps, * in ICO bit *set* is transparent. */ if (ba[y][x] <= maxval/2) row[byteOn] |= bitOn; if (bitOn == 1) { byteOn++; bitOn = 128; } else { bitOn >>= 1; } } } } return icBitmap; }
static void addColorToPalette(IC_Palette const palette, int const i, int const r, int const g, int const b) { MALLOCVAR_NOFAIL(palette->colors[i]); palette->colors[i]->red = r; palette->colors[i]->green = g; palette->colors[i]->blue = b; palette->colors[i]->reserved = 0; }
static void createOutstandingConnList(outstandingConnList ** const listPP) { outstandingConnList * listP; MALLOCVAR_NOFAIL(listP); listP->firstP = NULL; /* empty list */ listP->count = 0; *listPP = listP; }
static MS_Ico createIconFile (void) { MS_Ico MSIconData; MALLOCVAR_NOFAIL(MSIconData); MSIconData->reserved = 0; MSIconData->type = 1; MSIconData->count = 0; MSIconData->entries = NULL; return MSIconData; }
static void scaler_create(sample const outputMaxval, struct colorResolution const colorRes, scaler ** const scalerPP) { scaler * scalerP; unsigned int mapSize; if (UINT_MAX / colorRes.c[RED] / colorRes.c[GRN] / colorRes.c[BLU] < 1) pm_error("red/green/blue dimensions %u/%u/%u is uncomputably large", colorRes.c[RED], colorRes.c[GRN], colorRes.c[BLU]); { unsigned int plane; for (plane = 0, mapSize = 1; plane < 3; ++plane) mapSize *= colorRes.c[plane]; } MALLOCVAR_NOFAIL(scalerP); scalerP->colorRes = colorRes; scalerP->out = allocScalerMap(mapSize); if (scalerP->out == NULL) pm_error("Unable to allocate memory for %u colors " "(%u red x %u green x %u blue)", mapSize, colorRes.c[RED], colorRes.c[GRN], colorRes.c[BLU]); { unsigned int r; for (r = 0; r < colorRes.c[RED]; ++r) { unsigned int g; for (g = 0; g < colorRes.c[GRN]; ++g) { unsigned int b; for (b = 0; b < colorRes.c[BLU]; ++b) { unsigned int const index = (r * colorRes.c[GRN] + g) * colorRes.c[BLU] + b; tuple const t = scalerP->out[index]; t[PAM_RED_PLANE] = r * outputMaxval / (colorRes.c[RED] - 1); t[PAM_GRN_PLANE] = g * outputMaxval / (colorRes.c[GRN] - 1); t[PAM_BLU_PLANE] = b * outputMaxval / (colorRes.c[BLU] - 1); } } } } *scalerPP = scalerP; }
at_bitmap_type * at_bitmap_new(unsigned short width, unsigned short height, unsigned int planes) { at_bitmap_type * bitmap; MALLOCVAR_NOFAIL(bitmap); *bitmap = at_bitmap_init(NULL, width, height, planes); return bitmap; }
static IC_Palette createCleanPalette(void) { IC_Palette palette; int x; MALLOCVAR_NOFAIL(palette); MALLOCARRAY_NOFAIL(palette->colors, MAXCOLORS); for (x=0;x<MAXCOLORS;x++ ){ palette->colors[x] = NULL; } return palette; }
static void createPathReader(path * const pathP, pathReader ** const pathReaderPP) { pathReader * pathReaderP; MALLOCVAR_NOFAIL(pathReaderP); pathReaderP->pathP = pathP; pathReaderP->cursor = 0; *pathReaderPP = pathReaderP; }
static void createCanvas(unsigned int const width, unsigned int const height, pixval const maxval, canvas ** const canvasPP) { canvas * canvasP; MALLOCVAR_NOFAIL(canvasP); canvasP->width = width; canvasP->height = height; canvasP->pixels = ppm_allocarray(width, height); canvasP->maxval = maxval; *canvasPP = canvasP; }
static struct converter createThreshConverter(struct pam * const graypamP, float const threshFraction) { struct threshState * stateP; struct converter converter; MALLOCVAR_NOFAIL(stateP); converter.cols = graypamP->width; converter.convertRow = &threshConvertRow; converter.destroy = &threshDestroy; stateP->threshval = threshFraction; converter.stateP = stateP; return converter; }
static IC_InfoHeader createInfoHeader(IC_Entry const entry, ICON_bmp const xbmp, ICON_bmp const abmp) { IC_InfoHeader ih; MALLOCVAR_NOFAIL(ih); ih->size = 40; ih->width = entry->width; ih->height = entry->height * 2; ih->planes = 1; ih->bitcount = entry->bitcount; ih->compression = 0; ih->imagesize = entry->width * entry->height * 8 / entry->bitcount; ih->x_pixels_per_m= 0; ih->y_pixels_per_m= 0; ih->colors_used = 1 << entry->bitcount; ih->colors_important = 0; return ih; }
static ICON_bmp create8Bitmap (pixel ** const pa, int const cols, int const rows, colorhash_table const cht) { /* * How wide should the u1 string for each row be? * each byte is 8 pixels, but must be a multiple of 4 bytes. */ ICON_bmp icBitmap; int xBytes,y,x; int wt = cols; u1 ** rowData; MALLOCVAR_NOFAIL(icBitmap); if (wt & 3) { wt = (wt & ~3) + 4; } xBytes = wt; MALLOCARRAY_NOFAIL(rowData, rows); icBitmap->xBytes = xBytes; icBitmap->data = rowData; overflow2(xBytes, rows); icBitmap->size = xBytes * rows; for (y=0;y<rows;y++) { u1 * row; MALLOCARRAY_NOFAIL(row, xBytes); memset (row, 0, xBytes); rowData[rows-y-1] = row; /* * Check there's a pixel array, otherwise we're just faking this... */ if (pa) { for (x=0;x<cols;x++) { row[x] = ppm_lookupcolor(cht, &pa[y][x]); } } } return icBitmap; }
static void initRandomColor(outGenerator * const outGenP, const struct pam * const inPamP, struct cmdlineInfo const cmdline) { struct randomState * stateP; outGenP->pam.format = PAM_FORMAT; outGenP->pam.plainformat = 0; switch (cmdline.outputType) { case OUTPUT_BW: strcpy(outGenP->pam.tuple_type, PAM_PBM_TUPLETYPE); outGenP->pam.maxval = 1; outGenP->pam.depth = 1; break; case OUTPUT_GRAYSCALE: strcpy(outGenP->pam.tuple_type, PAM_PGM_TUPLETYPE); outGenP->pam.maxval = cmdline.maxvalSpec ? cmdline.maxval : inPamP->maxval; outGenP->pam.depth = 1; break; case OUTPUT_COLOR: strcpy(outGenP->pam.tuple_type, PAM_PPM_TUPLETYPE); outGenP->pam.maxval = cmdline.maxvalSpec ? cmdline.maxval : inPamP->maxval; outGenP->pam.depth = 3; break; } MALLOCVAR_NOFAIL(stateP); stateP->currentRow = pnm_allocpamrow(&outGenP->pam); stateP->magnifypat = cmdline.magnifypat; stateP->prevy = (unsigned int)(-cmdline.magnifypat); outGenP->stateP = stateP; outGenP->getTuple = &randomColor; outGenP->terminateState = &termRandomColor; }
/* at_splines_new_full modifies its 'bitmap' argument when it does the thin_image thing. */ at_spline_list_array_type * at_splines_new_full(at_bitmap_type * const bitmap, at_fitting_opts_type * const opts, at_msg_func msg_func, void * const msg_data, at_progress_func notify_progress, void * const progress_data, at_testcancel_func test_cancel, void * const testcancel_data) { at_spline_list_array_type * retval; image_header_type image_header; pixel_outline_list_type pixelOutlineList; at_exception_type exp; distance_map_type distanceMap; bool haveDistMap; exp = at_exception_new(msg_func, msg_data); image_header.width = at_bitmap_get_width(bitmap); image_header.height = at_bitmap_get_height(bitmap); if (opts->centerline) { if (opts->preserve_width) { /* Preserve line width prior to thinning. */ bool const paddedTrue = true; distanceMap = new_distance_map(*bitmap, 255, paddedTrue, &exp); haveDistMap = true; } else haveDistMap = false; thin_image(bitmap, opts->backgroundSpec, opts->background_color, &exp); } else haveDistMap = false; if (at_exception_got_fatal(&exp)) retval = NULL; else { if (opts->centerline) { pixel background_color; if (opts->backgroundSpec) background_color = opts->background_color; else PPM_ASSIGN(background_color, 255, 255, 255); pixelOutlineList = find_centerline_pixels(*bitmap, background_color, notify_progress, progress_data, test_cancel, testcancel_data, &exp); } else pixelOutlineList = find_outline_pixels(*bitmap, opts->backgroundSpec, opts->background_color, notify_progress, progress_data, test_cancel, testcancel_data, &exp); if (at_exception_got_fatal(&exp) || (test_cancel && test_cancel(testcancel_data))) retval = NULL; else { at_spline_list_array_type * splinesP; MALLOCVAR_NOFAIL(splinesP); fit_outlines_to_splines(pixelOutlineList, opts, haveDistMap ? &distanceMap : NULL, image_header.width, image_header.height, &exp, notify_progress, progress_data, test_cancel, testcancel_data, splinesP); if (at_exception_got_fatal(&exp) || (test_cancel && test_cancel(testcancel_data))) retval = NULL; else { if (notify_progress) notify_progress(1.0, progress_data); retval = splinesP; } free_pixel_outline_list(&pixelOutlineList); } if (haveDistMap) free_distance_map(&distanceMap); } return retval; }
static struct converter createClusterConverter(struct pam * const graypamP, enum ditherType const ditherType, unsigned int const radius) { /* TODO: We create a floating point normalized, gamma-adjusted dither matrix from the old integer dither matrices that were developed for use with integer arithmetic. We really should just change the literal values in dither.h instead of computing the matrix from the integer literal values here. */ int const clusterNormalizer = radius * radius * 2; unsigned int const diameter = 2 * radius; struct converter converter; struct clusterState * stateP; unsigned int row; converter.cols = graypamP->width; converter.convertRow = &clusterConvertRow; converter.destroy = &clusterDestroy; MALLOCVAR_NOFAIL(stateP); stateP->radius = radius; MALLOCARRAY_NOFAIL(stateP->clusterMatrix, diameter); for (row = 0; row < diameter; ++row) { unsigned int col; MALLOCARRAY_NOFAIL(stateP->clusterMatrix[row], diameter); for (col = 0; col < diameter; ++col) { switch (ditherType) { case DT_REGULAR: switch (radius) { case 8: stateP->clusterMatrix[row][col] = pm_gamma709((float)dither8[row][col] / 256); break; default: pm_error("INTERNAL ERROR: invalid radius"); } break; case DT_CLUSTER: { int val; switch (radius) { case 3: val = cluster3[row][col]; break; case 4: val = cluster4[row][col]; break; case 8: val = cluster8[row][col]; break; default: pm_error("INTERNAL ERROR: invalid radius"); } stateP->clusterMatrix[row][col] = pm_gamma709((float)val / clusterNormalizer); } break; } } } converter.stateP = stateP; return converter; }