main(int argc, char **argv) { l_int32 i; PIX *pixs, *pixt0, *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6; static char mainName[] = "binmorph4_reg"; pixs = pixRead("feyn.tif"); #if TEST_SYMMETRIC /* This works properly if there is an added border */ resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); #if 1 pixt1 = pixAddBorder(pixs, 64, 0); pixTransferAllData(pixs, &pixt1, 0, 0); #endif #endif /* TEST_SYMMETRIC */ pixt1 = pixCreateTemplateNoInit(pixs); pixt2 = pixCreateTemplateNoInit(pixs); pixt3 = pixCreateTemplateNoInit(pixs); pixt4 = pixCreateTemplateNoInit(pixs); pixt5 = pixCreateTemplateNoInit(pixs); pixt6 = pixCreateTemplateNoInit(pixs); for (i = 2; i < 64; i++) { #if 1 /* Compare morph composite with morph non-composite */ DoComparisonDwa1(pixs, pixt1, pixt2, pixt3, pixt4, pixt5, pixt6, i); #endif #if 1 /* Compare DWA non-composite with morph composite */ if (i < 16) DoComparisonDwa2(pixs, pixt1, pixt2, pixt3, pixt4, pixt5, pixt6, i); /* Compare DWA composite with DWA non-composite */ if (i < 16) DoComparisonDwa3(pixs, pixt1, pixt2, pixt3, pixt4, pixt5, pixt6, i); /* Compare DWA composite with morph composite */ DoComparisonDwa4(pixs, pixt1, pixt2, pixt3, pixt4, pixt5, pixt6, i); /* Compare DWA composite with morph non-composite */ DoComparisonDwa5(pixs, pixt1, pixt2, pixt3, pixt4, pixt5, pixt6, i); #endif } pixDestroy(&pixs); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); return 0; }
/*! * pixColorGrayCmap() * * Input: pixs (2, 4 or 8 bpp, with colormap) * box (<optional> region to set color; can be NULL) * type (L_PAINT_LIGHT, L_PAINT_DARK) * rval, gval, bval (target color) * Return: 0 if OK, 1 on error * * Notes: * (1) This is an in-place operation. * (2) If type == L_PAINT_LIGHT, it colorizes non-black pixels, * preserving antialiasing. * If type == L_PAINT_DARK, it colorizes non-white pixels, * preserving antialiasing. * (3) box gives the region to apply color; if NULL, this * colorizes the entire image. * (4) If the cmap is only 2 or 4 bpp, pixs is converted in-place * to an 8 bpp cmap. A 1 bpp cmap is not a valid input pix. * (5) This can also be called through pixColorGray(). * (6) This operation increases the colormap size by the number of * different gray (non-black or non-white) colors in the * input colormap. If there is not enough room in the colormap * for this expansion, it returns 1 (error), and the caller * should check the return value. * (7) Using the darkness of each original pixel in the rect, * it generates a new color (based on the input rgb values). * If type == L_PAINT_LIGHT, the new color is a (generally) * darken-to-black version of the input rgb color, where the * amount of darkening increases with the darkness of the * original pixel color. * If type == L_PAINT_DARK, the new color is a (generally) * faded-to-white version of the input rgb color, where the * amount of fading increases with the brightness of the * original pixel color. */ l_int32 pixColorGrayCmap(PIX *pixs, BOX *box, l_int32 type, l_int32 rval, l_int32 gval, l_int32 bval) { l_int32 w, h, d, ret; PIX *pixt; BOXA *boxa; PIXCMAP *cmap; PROCNAME("pixColorGrayCmap"); if (!pixs) return ERROR_INT("pixs not defined", procName, 1); if ((cmap = pixGetColormap(pixs)) == NULL) return ERROR_INT("no colormap", procName, 1); pixGetDimensions(pixs, &w, &h, &d); if (d != 2 && d != 4 && d != 8) return ERROR_INT("depth not in {2, 4, 8}", procName, 1); if (type != L_PAINT_DARK && type != L_PAINT_LIGHT) return ERROR_INT("invalid type", procName, 1); /* If 2 bpp or 4 bpp, convert in-place to 8 bpp. */ if (d == 2 || d == 4) { pixt = pixConvertTo8(pixs, 1); pixTransferAllData(pixs, &pixt, 0, 0); } /* If box == NULL, color the entire image */ boxa = boxaCreate(1); if (box) { boxaAddBox(boxa, box, L_COPY); } else { box = boxCreate(0, 0, w, h); boxaAddBox(boxa, box, L_INSERT); } ret = pixColorGrayRegionsCmap(pixs, boxa, type, rval, gval, bval); boxaDestroy(&boxa); return ret; }
/*! * \brief gifToPix() * * \param[in] gif opened gif stream * \return pix, or NULL on error * * <pre> * Notes: * (1) This decodes the pix from the compressed gif stream and * closes the stream. * (2) It is static so that the stream is not exposed to clients. * </pre> */ static PIX * gifToPix(GifFileType *gif) { l_int32 wpl, i, j, w, h, d, cindex, ncolors; l_int32 rval, gval, bval; l_uint32 *data, *line; PIX *pixd, *pixdi; PIXCMAP *cmap; ColorMapObject *gif_cmap; SavedImage si; #if (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || GIFLIB_MAJOR > 5 int giferr; #endif /* 5.1 and beyond */ PROCNAME("gifToPix"); /* Read all the data, but use only the first image found */ if (DGifSlurp(gif) != GIF_OK) { DGifCloseFile(gif, &giferr); return (PIX *)ERROR_PTR("failed to read GIF data", procName, NULL); } if (gif->SavedImages == NULL) { DGifCloseFile(gif, &giferr); return (PIX *)ERROR_PTR("no images found in GIF", procName, NULL); } si = gif->SavedImages[0]; w = si.ImageDesc.Width; h = si.ImageDesc.Height; if (w <= 0 || h <= 0) { DGifCloseFile(gif, &giferr); return (PIX *)ERROR_PTR("invalid image dimensions", procName, NULL); } if (si.RasterBits == NULL) { DGifCloseFile(gif, &giferr); return (PIX *)ERROR_PTR("no raster data in GIF", procName, NULL); } if (si.ImageDesc.ColorMap) { /* private cmap for this image */ gif_cmap = si.ImageDesc.ColorMap; } else if (gif->SColorMap) { /* global cmap for whole picture */ gif_cmap = gif->SColorMap; } else { /* don't know where to take cmap from */ DGifCloseFile(gif, &giferr); return (PIX *)ERROR_PTR("color map is missing", procName, NULL); } ncolors = gif_cmap->ColorCount; if (ncolors <= 2) d = 1; else if (ncolors <= 4) d = 2; else if (ncolors <= 16) d = 4; else d = 8; if ((cmap = pixcmapCreate(d)) == NULL) { DGifCloseFile(gif, &giferr); return (PIX *)ERROR_PTR("cmap creation failed", procName, NULL); } for (cindex = 0; cindex < ncolors; cindex++) { rval = gif_cmap->Colors[cindex].Red; gval = gif_cmap->Colors[cindex].Green; bval = gif_cmap->Colors[cindex].Blue; pixcmapAddColor(cmap, rval, gval, bval); } if ((pixd = pixCreate(w, h, d)) == NULL) { DGifCloseFile(gif, &giferr); pixcmapDestroy(&cmap); return (PIX *)ERROR_PTR("failed to allocate pixd", procName, NULL); } pixSetInputFormat(pixd, IFF_GIF); pixSetColormap(pixd, cmap); wpl = pixGetWpl(pixd); data = pixGetData(pixd); for (i = 0; i < h; i++) { line = data + i * wpl; if (d == 1) { for (j = 0; j < w; j++) { if (si.RasterBits[i * w + j]) SET_DATA_BIT(line, j); } } else if (d == 2) { for (j = 0; j < w; j++) SET_DATA_DIBIT(line, j, si.RasterBits[i * w + j]); } else if (d == 4) { for (j = 0; j < w; j++) SET_DATA_QBIT(line, j, si.RasterBits[i * w + j]); } else { /* d == 8 */ for (j = 0; j < w; j++) SET_DATA_BYTE(line, j, si.RasterBits[i * w + j]); } } /* If the image has been interlaced (for viewing in a browser), * this restores the raster lines to normal order. */ if (gif->Image.Interlace) { pixdi = pixUninterlaceGIF(pixd); pixTransferAllData(pixd, &pixdi, 0, 0); } DGifCloseFile(gif, &giferr); return pixd; }
main(int argc, char **argv) { l_int32 error; l_uint32 *data; PIX *pix1, *pix2, *pix3, *pix1c, *pix2c, *pix1t, *pix2t, *pixd; PIXA *pixa; static char mainName[] = "pixmem_reg"; error = 0; pixa = pixaCreate(0); /* Copy with internal resizing: onto a cmapped image */ pix1 = pixRead("weasel4.16c.png"); pix2 = pixRead("feyn-fract.tif"); pix3 = pixRead("lucasta.150.jpg"); fprintf(stderr, "before copy 2 --> 3\n"); pixCopy(pix3, pix2); Compare(pix2, pix3, &error); pixSaveTiled(pix3, pixa, 4, 1, 30, 32); fprintf(stderr, "before copy 3 --> 1\n"); pixCopy(pix1, pix3); Compare(pix2, pix1, &error); pixSaveTiled(pix1, pixa, 4, 0, 30, 32); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); /* Copy with internal resizing: from a cmapped image */ pix1 = pixRead("weasel4.16c.png"); pix2 = pixRead("feyn-fract.tif"); pix3 = pixRead("lucasta.150.jpg"); fprintf(stderr, "before copy 1 --> 2\n"); pixCopy(pix2, pix1); Compare(pix2, pix1, &error); pixSaveTiled(pix2, pixa, 1, 1, 30, 32); fprintf(stderr, "before copy 2 --> 3\n"); pixCopy(pix3, pix2); Compare(pix3, pix2, &error); pixSaveTiled(pix3, pixa, 1, 0, 30, 32); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); /* Transfer of data pixs --> pixd, when pixs is not cloned. * pixs is destroyed. */ pix1 = pixRead("weasel4.16c.png"); pix2 = pixRead("feyn-fract.tif"); pix3 = pixRead("lucasta.150.jpg"); pix1c = pixCopy(NULL, pix1); fprintf(stderr, "before transfer 1 --> 2\n"); pixTransferAllData(pix2, &pix1, 0, 0); Compare(pix2, pix1c, &error); pixSaveTiled(pix2, pixa, 1, 1, 30, 32); fprintf(stderr, "before transfer 2 --> 3\n"); pixTransferAllData(pix3, &pix2, 0, 0); Compare(pix3, pix1c, &error); pixSaveTiled(pix3, pixa, 1, 0, 30, 32); pixDestroy(&pix1c); pixDestroy(&pix3); /* Another transfer of data pixs --> pixd, when pixs is not cloned. * pixs is destroyed. */ pix1 = pixRead("weasel4.16c.png"); pix2 = pixRead("feyn-fract.tif"); pix3 = pixRead("lucasta.150.jpg"); pix1c = pixCopy(NULL, pix1); pix2c = pixCopy(NULL, pix2); fprintf(stderr, "before copy transfer 1 --> 2\n"); pixTransferAllData(pix2, &pix1c, 0, 0); Compare(pix2, pix1, &error); pixSaveTiled(pix2, pixa, 1, 0, 30, 32); fprintf(stderr, "before copy transfer 2 --> 3\n"); pixTransferAllData(pix3, &pix2, 0, 0); Compare(pix3, pix1, &error); pixSaveTiled(pix3, pixa, 1, 0, 30, 32); pixDestroy(&pix1); pixDestroy(&pix2c); pixDestroy(&pix3); /* Transfer of data pixs --> pixd, when pixs is cloned. * pixs has its refcount reduced by 1. */ pix1 = pixRead("weasel4.16c.png"); pix2 = pixRead("feyn-fract.tif"); pix3 = pixRead("lucasta.150.jpg"); pix1c = pixClone(pix1); pix2c = pixClone(pix2); fprintf(stderr, "before clone transfer 1 --> 2\n"); pixTransferAllData(pix2, &pix1c, 0, 0); Compare(pix2, pix1, &error); pixSaveTiled(pix2, pixa, 1, 0, 30, 32); fprintf(stderr, "before clone transfer 2 --> 3\n"); pixTransferAllData(pix3, &pix2c, 0, 0); Compare(pix3, pix1, &error); pixSaveTiled(pix3, pixa, 1, 0, 30, 32); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); /* Extraction of data when pixs is not cloned, putting * the data into a new template of pixs. */ pix2 = pixRead("feyn-fract.tif"); fprintf(stderr, "no clone: before extraction and reinsertion of 2\n"); pix2c = pixCopy(NULL, pix2); /* for later reference */ data = pixExtractData(pix2); pix2t = pixCreateTemplateNoInit(pix2); pixFreeData(pix2t); pixSetData(pix2t, data); Compare(pix2c, pix2t, &error); pixSaveTiled(pix2t, pixa, 4, 1, 30, 32); pixDestroy(&pix2); pixDestroy(&pix2c); pixDestroy(&pix2t); /* Extraction of data when pixs is cloned, putting * a copy of the data into a new template of pixs. */ pix1 = pixRead("weasel4.16c.png"); fprintf(stderr, "clone: before extraction and reinsertion of 1\n"); pix1c = pixClone(pix1); /* bump refcount of pix1 to 2 */ data = pixExtractData(pix1); /* should make a copy of data */ pix1t = pixCreateTemplateNoInit(pix1); pixFreeData(pix1t); pixSetData(pix1t, data); Compare(pix1c, pix1t, &error); pixSaveTiled(pix1t, pixa, 1, 0, 30, 32); pixDestroy(&pix1); pixDestroy(&pix1c); pixDestroy(&pix1t); pixd = pixaDisplay(pixa, 0, 0); pixDisplay(pixd, 100, 100); pixWrite("/tmp/junkpixmem.png", pixd, IFF_PNG); pixaDestroy(&pixa); pixDestroy(&pixd); if (error) fprintf(stderr, "Fail: an error occurred\n"); else fprintf(stderr, "Success: no errors\n"); return 0; }
void TestAll(L_REGPARAMS *rp, PIX *pixs, l_int32 symmetric) { l_int32 i, n, rsize, fact1, fact2, extra; l_int32 size, lastsize; l_int32 dwasize[256]; l_int32 ropsize[256]; PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; if (symmetric) { /* This works properly with an added border of 128 */ resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); pix1 = pixAddBorder(pixs, 128, 0); pixTransferAllData(pixs, &pix1, 0, 0); fprintf(stderr, "Testing with symmetric boundary conditions\n"); } else { resetMorphBoundaryCondition(ASYMMETRIC_MORPH_BC); fprintf(stderr, "Testing with asymmetric boundary conditions\n"); } pix1 = pixCreateTemplateNoInit(pixs); pix2 = pixCreateTemplateNoInit(pixs); pix3 = pixCreateTemplateNoInit(pixs); pix4 = pixCreateTemplateNoInit(pixs); pix5 = pixCreateTemplateNoInit(pixs); pix6 = pixCreateTemplateNoInit(pixs); /* ---------------------------------------------------------------- * * Faster test; testing fewer sizes * * ---------------------------------------------------------------- */ #if FASTER_TEST /* Compute the actual sizes used for each input size 'i' */ for (i = 0; i < 256; i++) { dwasize[i] = 0; ropsize[i] = 0; } for (i = 65; i < 256; i++) { selectComposableSizes(i, &fact1, &fact2); rsize = fact1 * fact2; ropsize[i] = rsize; getExtendedCompositeParameters(i, &n, &extra, &dwasize[i]); } /* Use only values where the resulting sizes are equal */ for (i = 65; i < 240; i++) { n = 1 + (l_int32)((i - 63) / 62); extra = i - 63 - (n - 1) * 62 + 1; if (extra == 2) continue; /* don't use this one (e.g., i == 126) */ if (ropsize[i] == dwasize[i]) DoComparisonDwa1(rp, pixs, pix1, pix2, pix3, pix4, pix5, pix6, i); } #endif /* FASTER_TEST */ /* ---------------------------------------------------------------- * * Slower test; testing maximum number of sizes * * ---------------------------------------------------------------- */ #if SLOWER_TEST lastsize = 0; for (i = 65; i < 199; i++) { getExtendedCompositeParameters(i, &n, &extra, &size); if (size == lastsize) continue; if (size == 126 || size == 188) continue; /* deliberately off by one */ lastsize = size; DoComparisonDwa2(rp, pixs, pix1, pix2, pix3, pix4, pix5, pix6, size); } #endif /* SLOWER_TEST */ fprintf(stderr, "\n"); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); pixDestroy(&pix5); pixDestroy(&pix6); }
main(int argc, char **argv) { l_int32 i, n, rsize, fact1, fact2, extra; l_int32 size, lastsize; l_int32 dwasize[256]; l_int32 ropsize[256]; PIX *pixs, *pixt0, *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6; static char mainName[] = "binmorph5_reg"; pixs = pixRead("feyn.tif"); #if TEST_SYMMETRIC /* This works properly if there's an added border */ resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); #if 1 pixt1 = pixAddBorder(pixs, 64, 0); pixTransferAllData(pixs, &pixt1, 0, 0); #endif #endif /* TEST_SYMMETRIC */ pixt1 = pixCreateTemplateNoInit(pixs); pixt2 = pixCreateTemplateNoInit(pixs); pixt3 = pixCreateTemplateNoInit(pixs); pixt4 = pixCreateTemplateNoInit(pixs); pixt5 = pixCreateTemplateNoInit(pixs); pixt6 = pixCreateTemplateNoInit(pixs); /* ---------------------------------------------------------------- * * Faster test; testing fewer sizes * * ---------------------------------------------------------------- */ #if FASTER_TEST /* Compute the actual sizes used for each input size 'i' */ for (i = 0; i < 256; i++) { dwasize[i] = 0; ropsize[i] = 0; } for (i = 65; i < 256; i++) { selectComposableSizes(i, &fact1, &fact2); rsize = fact1 * fact2; ropsize[i] = rsize; getExtendedCompositeParameters(i, &n, &extra, &dwasize[i]); } /* Use only values where the resulting sizes are equal */ for (i = 65; i < 240; i++) { n = 1 + (l_int32)((i - 63) / 62); extra = i - 63 - (n - 1) * 62 + 1; if (extra == 2) continue; /* don't use this one (e.g., i == 126) */ if (ropsize[i] == dwasize[i]) DoComparisonDwa1(pixs, pixt1, pixt2, pixt3, pixt4, pixt5, pixt6, i); } #endif /* FASTER_TEST */ /* ---------------------------------------------------------------- * * Slower test; testing maximum number of sizes * * ---------------------------------------------------------------- */ #if SLOWER_TEST lastsize = 0; for (i = 65; i < 199; i++) { getExtendedCompositeParameters(i, &n, &extra, &size); if (size == lastsize) continue; if (size == 126 || size == 188) continue; /* deliberately off by one */ lastsize = size; DoComparisonDwa2(pixs, pixt1, pixt2, pixt3, pixt4, pixt5, pixt6, size); } #endif /* SLOWER_TEST */ pixDestroy(&pixs); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); return 0; }
/*! * pixColorGrayCmap() * * Input: pixs (2, 4 or 8 bpp, with colormap) * box (<optional> region to set color; can be NULL) * type (L_PAINT_LIGHT, L_PAINT_DARK) * rval, gval, bval (target color) * Return: 0 if OK, 1 on error * * Notes: * (1) This is an in-place operation. * (2) If type == L_PAINT_LIGHT, it colorizes non-black pixels, * preserving antialiasing. * If type == L_PAINT_DARK, it colorizes non-white pixels, * preserving antialiasing. * (3) If box is NULL, applies function to the entire image; otherwise, * clips the operation to the intersection of the box and pix. * (4) This can also be called through pixColorGray(). * (5) This increases the colormap size by the number of * different gray (non-black or non-white) colors in the * input colormap. If there is not enough room in the colormap * for this expansion, it returns 1 (error), and the caller * should check the return value. If an error is returned * and the cmap is only 2 or 4 bpp, the pix can be converted * to 8 bpp and this function will succeed if run again on * a larger colormap. * (6) Using the darkness of each original pixel in the rect, * it generates a new color (based on the input rgb values). * If type == L_PAINT_LIGHT, the new color is a (generally) * darken-to-black version of the input rgb color, where the * amount of darkening increases with the darkness of the * original pixel color. * If type == L_PAINT_DARK, the new color is a (generally) * faded-to-white version of the input rgb color, where the * amount of fading increases with the brightness of the * original pixel color. */ l_int32 pixColorGrayCmap(PIX *pixs, BOX *box, l_int32 type, l_int32 rval, l_int32 gval, l_int32 bval) { l_int32 i, j, w, h, d, x1, y1, x2, y2, bw, bh, wpl; l_int32 val, nval; l_int32 *map; l_uint32 *line, *data; NUMA *na; PIX *pixt; PIXCMAP *cmap, *cmapc; PROCNAME("pixColorGrayCmap"); if (!pixs) return ERROR_INT("pixs not defined", procName, 1); if ((cmap = pixGetColormap(pixs)) == NULL) return ERROR_INT("no colormap", procName, 1); d = pixGetDepth(pixs); if (d != 2 && d != 4 && d != 8) return ERROR_INT("depth not in {2, 4, 8}", procName, 1); if (type != L_PAINT_DARK && type != L_PAINT_LIGHT) return ERROR_INT("invalid type", procName, 1); /* If 2 bpp or 4 bpp, see if the new colors will fit into * the existing colormap. If not, convert in-place to 8 bpp. */ if (d == 2 || d == 4) { cmapc = pixcmapCopy(cmap); /* experiment with a copy */ if (addColorizedGrayToCmap(cmapc, type, rval, gval, bval, NULL)) { pixt = pixConvertTo8(pixs, 1); pixTransferAllData(pixs, &pixt, 0, 0); } pixcmapDestroy(&cmapc); } /* Find gray colors, add the corresponding new colors, * and set up a mapping table from gray to new. * That table has the value 256 for all colors that are * not to be mapped. */ cmap = pixGetColormap(pixs); if (addColorizedGrayToCmap(cmap, type, rval, gval, bval, &na)) { numaDestroy(&na); return ERROR_INT("no room; cmap full", procName, 1); } map = numaGetIArray(na); /* Determine the region of substitution */ pixGetDimensions(pixs, &w, &h, &d); /* d may be different */ data = pixGetData(pixs); wpl = pixGetWpl(pixs); if (!box) { x1 = y1 = 0; x2 = w; y2 = h; } else { boxGetGeometry(box, &x1, &y1, &bw, &bh); x2 = x1 + bw - 1; y2 = y1 + bh - 1; } /* Remap gray pixels in the region */ for (i = y1; i <= y2; i++) { if (i < 0 || i >= h) /* clip */ continue; line = data + i * wpl; for (j = x1; j <= x2; j++) { if (j < 0 || j >= w) /* clip */ continue; switch (d) { case 2: val = GET_DATA_DIBIT(line, j); nval = map[val]; if (nval != 256) SET_DATA_DIBIT(line, j, nval); break; case 4: val = GET_DATA_QBIT(line, j); nval = map[val]; if (nval != 256) SET_DATA_QBIT(line, j, nval); break; case 8: val = GET_DATA_BYTE(line, j); nval = map[val]; if (nval != 256) SET_DATA_BYTE(line, j, nval); break; } } } FREE(map); numaDestroy(&na); return 0; }
/*! * pixReadStreamGif() * * Input: stream * Return: pix, or null on error */ PIX * pixReadStreamGif(FILE *fp) { l_int32 fd, wpl, i, j, w, h, d, cindex, ncolors; l_int32 rval, gval, bval; l_uint32 *data, *line; GifFileType *gif; PIX *pixd, *pixdi; PIXCMAP *cmap; ColorMapObject *gif_cmap; SavedImage si; PROCNAME("pixReadStreamGif"); if ((fd = fileno(fp)) < 0) return (PIX *)ERROR_PTR("invalid file descriptor", procName, NULL); #ifndef _MSC_VER lseek(fd, 0, SEEK_SET); #else _lseek(fd, 0, SEEK_SET); #endif /* _MSC_VER */ if ((gif = DGifOpenFileHandle(fd)) == NULL) return (PIX *)ERROR_PTR("invalid file or file not found", procName, NULL); /* Read all the data, but use only the first image found */ if (DGifSlurp(gif) != GIF_OK) { DGifCloseFile(gif); return (PIX *)ERROR_PTR("failed to read GIF data", procName, NULL); } if (gif->SavedImages == NULL) { DGifCloseFile(gif); return (PIX *)ERROR_PTR("no images found in GIF", procName, NULL); } si = gif->SavedImages[0]; w = si.ImageDesc.Width; h = si.ImageDesc.Height; if (w <= 0 || h <= 0) { DGifCloseFile(gif); return (PIX *)ERROR_PTR("invalid image dimensions", procName, NULL); } if (si.RasterBits == NULL) { DGifCloseFile(gif); return (PIX *)ERROR_PTR("no raster data in GIF", procName, NULL); } if (si.ImageDesc.ColorMap) { /* private cmap for this image */ gif_cmap = si.ImageDesc.ColorMap; } else if (gif->SColorMap) { /* global cmap for whole picture */ gif_cmap = gif->SColorMap; } else { /* don't know where to take cmap from */ DGifCloseFile(gif); return (PIX *)ERROR_PTR("color map is missing", procName, NULL); } ncolors = gif_cmap->ColorCount; if (ncolors <= 2) d = 1; else if (ncolors <= 4) d = 2; else if (ncolors <= 16) d = 4; else d = 8; if ((cmap = pixcmapCreate(d)) == NULL) return (PIX *)ERROR_PTR("cmap creation failed", procName, NULL); for (cindex = 0; cindex < ncolors; cindex++) { rval = gif_cmap->Colors[cindex].Red; gval = gif_cmap->Colors[cindex].Green; bval = gif_cmap->Colors[cindex].Blue; pixcmapAddColor(cmap, rval, gval, bval); } if ((pixd = pixCreate(w, h, d)) == NULL) { DGifCloseFile(gif); pixcmapDestroy(&cmap); return (PIX *)ERROR_PTR("failed to allocate pixd", procName, NULL); } pixSetColormap(pixd, cmap); wpl = pixGetWpl(pixd); data = pixGetData(pixd); for (i = 0; i < h; i++) { line = data + i * wpl; if (d == 1) { for (j = 0; j < w; j++) { if (si.RasterBits[i * w + j]) SET_DATA_BIT(line, j); } } else if (d == 2) { for (j = 0; j < w; j++) SET_DATA_DIBIT(line, j, si.RasterBits[i * w + j]); } else if (d == 4) { for (j = 0; j < w; j++) SET_DATA_QBIT(line, j, si.RasterBits[i * w + j]); } else { /* d == 8 */ for (j = 0; j < w; j++) SET_DATA_BYTE(line, j, si.RasterBits[i * w + j]); } } if (gif->Image.Interlace) { pixdi = pixInterlaceGIF(pixd); pixTransferAllData(pixd, &pixdi, 0, 0); } DGifCloseFile(gif); return pixd; }
main(int argc, char **argv) { l_int32 i, ok, same; char sequence[512]; PIX *pixs, *pixref; PIX *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6; PIX *pixt7, *pixt8, *pixt9, *pixt10, *pixt11; PIX *pixt12, *pixt13, *pixt14; SEL *sel; static char mainName[] = "binmorph1_reg"; if (argc != 1) exit(ERROR_INT(" Syntax: binmorph1_reg", mainName, 1)); if ((pixs = pixRead("feyn.tif")) == NULL) exit(ERROR_INT("pix not made", mainName, 1)); #if TEST_SYMMETRIC /* This works properly if there is an added border */ resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); #if 1 pixt1 = pixAddBorder(pixs, 32, 0); pixTransferAllData(pixs, &pixt1, 0, 0); #endif #endif /* TEST_SYMMETRIC */ /* This is our test sel */ sel = selCreateBrick(HEIGHT, WIDTH, HEIGHT / 2, WIDTH / 2, SEL_HIT); /* Dilation */ fprintf(stderr, "Testing dilation\n"); ok = TRUE; pixref = pixDilate(NULL, pixs, sel); /* new one */ pixt1 = pixCreateTemplate(pixs); pixDilate(pixt1, pixs, sel); /* existing one */ pixEqual(pixref, pixt1, &same); if (!same) { fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE; } pixt2 = pixCopy(NULL, pixs); pixDilate(pixt2, pixt2, sel); /* in-place */ pixEqual(pixref, pixt2, &same); if (!same) { fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE; } sprintf(sequence, "d%d.%d", WIDTH, HEIGHT); pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */ pixEqual(pixref, pixt3, &same); if (!same) { fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE; } sprintf(sequence, "d%d.1 + d1.%d", WIDTH, HEIGHT); pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ pixEqual(pixref, pixt4, &same); if (!same) { fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE; } pixt5 = pixDilateBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt5, &same); if (!same) { fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE; } pixt6 = pixCreateTemplate(pixs); pixDilateBrick(pixt6, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt6, &same); if (!same) { fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE; } pixt7 = pixCopy(NULL, pixs); pixDilateBrick(pixt7, pixt7, WIDTH, HEIGHT); /* in-place */ pixEqual(pixref, pixt7, &same); if (!same) { fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE; } pixt8 = pixDilateBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt8, &same); if (!same) { fprintf(stderr, "pixref != pixt8 !\n"); ok = FALSE; } pixt9 = pixCreateTemplate(pixs); pixDilateBrickDwa(pixt9, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt9, &same); if (!same) { fprintf(stderr, "pixref != pixt9 !\n"); ok = FALSE; } pixt10 = pixCopy(NULL, pixs); pixDilateBrickDwa(pixt10, pixt10, WIDTH, HEIGHT); /* in-place */ pixEqual(pixref, pixt10, &same); if (!same) { fprintf(stderr, "pixref != pixt10 !\n"); ok = FALSE; } pixt11 = pixCreateTemplate(pixs); pixDilateCompBrickDwa(pixt11, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt11, &same); if (!same) { fprintf(stderr, "pixref != pixt11 !\n"); ok = FALSE; } sprintf(sequence, "d%d.%d", WIDTH, HEIGHT); pixt12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */ pixEqual(pixref, pixt12, &same); if (!same) { fprintf(stderr, "pixref != pixt12!\n"); ok = FALSE; } pixt13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */ pixEqual(pixref, pixt13, &same); if (!same) { fprintf(stderr, "pixref != pixt13!\n"); ok = FALSE; } pixDestroy(&pixref); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); pixDestroy(&pixt7); pixDestroy(&pixt8); pixDestroy(&pixt9); pixDestroy(&pixt10); pixDestroy(&pixt11); pixDestroy(&pixt12); pixDestroy(&pixt13); /* Erosion */ fprintf(stderr, "Testing erosion\n"); pixref = pixErode(NULL, pixs, sel); /* new one */ pixt1 = pixCreateTemplate(pixs); pixErode(pixt1, pixs, sel); /* existing one */ pixEqual(pixref, pixt1, &same); if (!same) { fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE; } pixt2 = pixCopy(NULL, pixs); pixErode(pixt2, pixt2, sel); /* in-place */ pixEqual(pixref, pixt2, &same); if (!same) { fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE; } sprintf(sequence, "e%d.%d", WIDTH, HEIGHT); pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */ pixEqual(pixref, pixt3, &same); if (!same) { fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE; } sprintf(sequence, "e%d.1 + e1.%d", WIDTH, HEIGHT); pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ pixEqual(pixref, pixt4, &same); if (!same) { fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE; } pixt5 = pixErodeBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt5, &same); if (!same) { fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE; } pixt6 = pixCreateTemplate(pixs); pixErodeBrick(pixt6, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt6, &same); if (!same) { fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE; } pixt7 = pixCopy(NULL, pixs); pixErodeBrick(pixt7, pixt7, WIDTH, HEIGHT); /* in-place */ pixEqual(pixref, pixt7, &same); if (!same) { fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE; } pixt8 = pixErodeBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt8, &same); if (!same) { fprintf(stderr, "pixref != pixt8 !\n"); ok = FALSE; } pixt9 = pixCreateTemplate(pixs); pixErodeBrickDwa(pixt9, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt9, &same); if (!same) { fprintf(stderr, "pixref != pixt9 !\n"); ok = FALSE; } pixt10 = pixCopy(NULL, pixs); pixErodeBrickDwa(pixt10, pixt10, WIDTH, HEIGHT); /* in-place */ pixEqual(pixref, pixt10, &same); if (!same) { fprintf(stderr, "pixref != pixt10 !\n"); ok = FALSE; } pixt11 = pixCreateTemplate(pixs); pixErodeCompBrickDwa(pixt11, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt11, &same); if (!same) { fprintf(stderr, "pixref != pixt11 !\n"); ok = FALSE; } sprintf(sequence, "e%d.%d", WIDTH, HEIGHT); pixt12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */ pixEqual(pixref, pixt12, &same); if (!same) { fprintf(stderr, "pixref != pixt12!\n"); ok = FALSE; } pixt13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */ pixEqual(pixref, pixt13, &same); if (!same) { fprintf(stderr, "pixref != pixt13!\n"); ok = FALSE; } pixDestroy(&pixref); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); pixDestroy(&pixt7); pixDestroy(&pixt8); pixDestroy(&pixt9); pixDestroy(&pixt10); pixDestroy(&pixt11); pixDestroy(&pixt12); pixDestroy(&pixt13); /* Opening */ fprintf(stderr, "Testing opening\n"); pixref = pixOpen(NULL, pixs, sel); /* new one */ pixt1 = pixCreateTemplate(pixs); pixOpen(pixt1, pixs, sel); /* existing one */ pixEqual(pixref, pixt1, &same); if (!same) { fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE; } pixt2 = pixCopy(NULL, pixs); pixOpen(pixt2, pixt2, sel); /* in-place */ pixEqual(pixref, pixt2, &same); if (!same) { fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE; } sprintf(sequence, "o%d.%d", WIDTH, HEIGHT); pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */ pixEqual(pixref, pixt3, &same); if (!same) { fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE; } sprintf(sequence, "e%d.%d + d%d.%d", WIDTH, HEIGHT, WIDTH, HEIGHT); pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ pixEqual(pixref, pixt4, &same); if (!same) { fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE; } sprintf(sequence, "e%d.1 + e1.%d + d%d.1 + d1.%d", WIDTH, HEIGHT, WIDTH, HEIGHT); pixt5 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable^2 */ pixEqual(pixref, pixt5, &same); if (!same) { fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE; } pixt6 = pixOpenBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt6, &same); if (!same) { fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE; } pixt7 = pixCreateTemplate(pixs); pixOpenBrick(pixt7, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt7, &same); if (!same) { fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE; } pixt8 = pixCopy(NULL, pixs); /* in-place */ pixOpenBrick(pixt8, pixt8, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt8, &same); if (!same) { fprintf(stderr, "pixref != pixt8 !\n"); ok = FALSE; } pixt9 = pixOpenBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt9, &same); if (!same) { fprintf(stderr, "pixref != pixt9 !\n"); ok = FALSE; } pixt10 = pixCreateTemplate(pixs); pixOpenBrickDwa(pixt10, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt10, &same); if (!same) { fprintf(stderr, "pixref != pixt10 !\n"); ok = FALSE; } pixt11 = pixCopy(NULL, pixs); pixOpenBrickDwa(pixt11, pixt11, WIDTH, HEIGHT); /* in-place */ pixEqual(pixref, pixt11, &same); if (!same) { fprintf(stderr, "pixref != pixt11 !\n"); ok = FALSE; } sprintf(sequence, "o%d.%d", WIDTH, HEIGHT); pixt12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */ pixEqual(pixref, pixt12, &same); if (!same) { fprintf(stderr, "pixref != pixt12!\n"); ok = FALSE; } #if 0 pixWrite("/tmp/junkref.png", pixref, IFF_PNG); pixWrite("/tmp/junk12.png", pixt12, IFF_PNG); pixt13 = pixXor(NULL, pixref, pixt12); pixWrite("/tmp/junk12a.png", pixt13, IFF_PNG); pixDestroy(&pixt13); #endif pixt13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */ pixEqual(pixref, pixt13, &same); if (!same) { fprintf(stderr, "pixref != pixt13!\n"); ok = FALSE; } pixt14 = pixCreateTemplate(pixs); pixOpenCompBrickDwa(pixt14, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt14, &same); if (!same) { fprintf(stderr, "pixref != pixt14 !\n"); ok = FALSE; } pixDestroy(&pixref); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); pixDestroy(&pixt7); pixDestroy(&pixt8); pixDestroy(&pixt9); pixDestroy(&pixt10); pixDestroy(&pixt11); pixDestroy(&pixt12); pixDestroy(&pixt13); pixDestroy(&pixt14); /* Closing */ fprintf(stderr, "Testing closing\n"); pixref = pixClose(NULL, pixs, sel); /* new one */ pixt1 = pixCreateTemplate(pixs); pixClose(pixt1, pixs, sel); /* existing one */ pixEqual(pixref, pixt1, &same); if (!same) { fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE; } pixt2 = pixCopy(NULL, pixs); pixClose(pixt2, pixt2, sel); /* in-place */ pixEqual(pixref, pixt2, &same); if (!same) { fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE; } sprintf(sequence, "d%d.%d + e%d.%d", WIDTH, HEIGHT, WIDTH, HEIGHT); pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ pixEqual(pixref, pixt3, &same); if (!same) { fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE; } sprintf(sequence, "d%d.1 + d1.%d + e%d.1 + e1.%d", WIDTH, HEIGHT, WIDTH, HEIGHT); pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable^2 */ pixEqual(pixref, pixt4, &same); if (!same) { fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE; } pixt5 = pixCloseBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt5, &same); if (!same) { fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE; } pixt6 = pixCreateTemplate(pixs); pixCloseBrick(pixt6, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt6, &same); if (!same) { fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE; } pixt7 = pixCopy(NULL, pixs); /* in-place */ pixCloseBrick(pixt7, pixt7, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt7, &same); if (!same) { fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE; } pixDestroy(&pixref); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); pixDestroy(&pixt7); /* Safe closing (using pix, not pixs) */ fprintf(stderr, "Testing safe closing\n"); pixref = pixCloseSafe(NULL, pixs, sel); /* new one */ pixt1 = pixCreateTemplate(pixs); pixCloseSafe(pixt1, pixs, sel); /* existing one */ pixEqual(pixref, pixt1, &same); if (!same) { fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE; } pixt2 = pixCopy(NULL, pixs); pixCloseSafe(pixt2, pixt2, sel); /* in-place */ pixEqual(pixref, pixt2, &same); if (!same) { fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE; } sprintf(sequence, "c%d.%d", WIDTH, HEIGHT); pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */ pixEqual(pixref, pixt3, &same); if (!same) { fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE; } sprintf(sequence, "b32 + d%d.%d + e%d.%d", WIDTH, HEIGHT, WIDTH, HEIGHT); pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ pixEqual(pixref, pixt4, &same); if (!same) { fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE; } sprintf(sequence, "b32 + d%d.1 + d1.%d + e%d.1 + e1.%d", WIDTH, HEIGHT, WIDTH, HEIGHT); pixt5 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable^2 */ pixEqual(pixref, pixt5, &same); if (!same) { fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE; } pixt6 = pixCloseSafeBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt6, &same); if (!same) { fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE; } pixt7 = pixCreateTemplate(pixs); pixCloseSafeBrick(pixt7, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt7, &same); if (!same) { fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE; } pixt8 = pixCopy(NULL, pixs); /* in-place */ pixCloseSafeBrick(pixt8, pixt8, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt8, &same); if (!same) { fprintf(stderr, "pixref != pixt8 !\n"); ok = FALSE; } pixt9 = pixCloseBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt9, &same); if (!same) { fprintf(stderr, "pixref != pixt9 !\n"); ok = FALSE; } pixt10 = pixCreateTemplate(pixs); pixCloseBrickDwa(pixt10, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt10, &same); if (!same) { fprintf(stderr, "pixref != pixt10 !\n"); ok = FALSE; } pixt11 = pixCopy(NULL, pixs); pixCloseBrickDwa(pixt11, pixt11, WIDTH, HEIGHT); /* in-place */ pixEqual(pixref, pixt11, &same); if (!same) { fprintf(stderr, "pixref != pixt11 !\n"); ok = FALSE; } sprintf(sequence, "c%d.%d", WIDTH, HEIGHT); pixt12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */ pixEqual(pixref, pixt12, &same); if (!same) { fprintf(stderr, "pixref != pixt12!\n"); ok = FALSE; } pixt13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */ pixEqual(pixref, pixt13, &same); if (!same) { fprintf(stderr, "pixref != pixt13!\n"); ok = FALSE; } pixt14 = pixCreateTemplate(pixs); pixCloseCompBrickDwa(pixt14, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt14, &same); if (!same) { fprintf(stderr, "pixref != pixt14 !\n"); ok = FALSE; } #if 0 pixWrite("/tmp/junkref.png", pixref, IFF_PNG); pixWrite("/tmp/junk12.png", pixt12, IFF_PNG); pixt13 = pixXor(NULL, pixref, pixt12); pixWrite("/tmp/junk12a.png", pixt13, IFF_PNG); pixDestroy(&pixt13); #endif pixDestroy(&pixref); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); pixDestroy(&pixt7); pixDestroy(&pixt8); pixDestroy(&pixt9); pixDestroy(&pixt10); pixDestroy(&pixt11); pixDestroy(&pixt12); pixDestroy(&pixt13); pixDestroy(&pixt14); if (ok) fprintf(stderr, "All morph tests OK!\n"); pixDestroy(&pixs); selDestroy(&sel); exit(0); }