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; }
/*! * pixDilateGray3h() * * Input: pixs (8 bpp, not cmapped) * Return: pixd, or null on error * * Notes: * (1) Special case for horizontal 3x1 brick Sel; * also used as the first step for the 3x3 brick Sel. */ static PIX * pixDilateGray3h(PIX *pixs) { l_uint32 *datas, *datad, *lines, *lined; l_int32 w, h, wpl, i, j; l_int32 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, maxval; PIX *pixd; PROCNAME("pixDilateGray3h"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); if (pixGetDepth(pixs) != 8) return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL); pixd = pixCreateTemplateNoInit(pixs); pixSetBorderVal(pixd, 4, 8, 2, 8, 0); /* only to silence valgrind */ pixGetDimensions(pixs, &w, &h, NULL); datas = pixGetData(pixs); datad = pixGetData(pixd); wpl = pixGetWpl(pixs); for (i = 0; i < h; i++) { lines = datas + i * wpl; lined = datad + i * wpl; for (j = 1; j < w - 8; j += 8) { val0 = GET_DATA_BYTE(lines, j - 1); val1 = GET_DATA_BYTE(lines, j); val2 = GET_DATA_BYTE(lines, j + 1); val3 = GET_DATA_BYTE(lines, j + 2); val4 = GET_DATA_BYTE(lines, j + 3); val5 = GET_DATA_BYTE(lines, j + 4); val6 = GET_DATA_BYTE(lines, j + 5); val7 = GET_DATA_BYTE(lines, j + 6); val8 = GET_DATA_BYTE(lines, j + 7); val9 = GET_DATA_BYTE(lines, j + 8); maxval = L_MAX(val1, val2); SET_DATA_BYTE(lined, j, L_MAX(val0, maxval)); SET_DATA_BYTE(lined, j + 1, L_MAX(maxval, val3)); maxval = L_MAX(val3, val4); SET_DATA_BYTE(lined, j + 2, L_MAX(val2, maxval)); SET_DATA_BYTE(lined, j + 3, L_MAX(maxval, val5)); maxval = L_MAX(val5, val6); SET_DATA_BYTE(lined, j + 4, L_MAX(val4, maxval)); SET_DATA_BYTE(lined, j + 5, L_MAX(maxval, val7)); maxval = L_MAX(val7, val8); SET_DATA_BYTE(lined, j + 6, L_MAX(val6, maxval)); SET_DATA_BYTE(lined, j + 7, L_MAX(maxval, val9)); } } return pixd; }
/*! * pixDilateGray3v() * * Input: pixs (8 bpp, not cmapped) * Return: pixd, or null on error * * Notes: * (1) Special case for vertical 1x3 brick Sel; * also used as the second step for the 3x3 brick Sel. */ static PIX * pixDilateGray3v(PIX *pixs) { l_uint32 *datas, *datad, *linesi, *linedi; l_int32 w, h, wpl, i, j; l_int32 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, maxval; PIX *pixd; PROCNAME("pixDilateGray3v"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); if (pixGetDepth(pixs) != 8) return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL); pixd = pixCreateTemplateNoInit(pixs); pixGetDimensions(pixs, &w, &h, NULL); datas = pixGetData(pixs); datad = pixGetData(pixd); wpl = pixGetWpl(pixs); for (j = 0; j < w; j++) { for (i = 1; i < h - 8; i += 8) { linesi = datas + i * wpl; linedi = datad + i * wpl; val0 = GET_DATA_BYTE(linesi - wpl, j); val1 = GET_DATA_BYTE(linesi, j); val2 = GET_DATA_BYTE(linesi + wpl, j); val3 = GET_DATA_BYTE(linesi + 2 * wpl, j); val4 = GET_DATA_BYTE(linesi + 3 * wpl, j); val5 = GET_DATA_BYTE(linesi + 4 * wpl, j); val6 = GET_DATA_BYTE(linesi + 5 * wpl, j); val7 = GET_DATA_BYTE(linesi + 6 * wpl, j); val8 = GET_DATA_BYTE(linesi + 7 * wpl, j); val9 = GET_DATA_BYTE(linesi + 8 * wpl, j); maxval = L_MAX(val1, val2); SET_DATA_BYTE(linedi, j, L_MAX(val0, maxval)); SET_DATA_BYTE(linedi + wpl, j, L_MAX(maxval, val3)); maxval = L_MAX(val3, val4); SET_DATA_BYTE(linedi + 2 * wpl, j, L_MAX(val2, maxval)); SET_DATA_BYTE(linedi + 3 * wpl, j, L_MAX(maxval, val5)); maxval = L_MAX(val5, val6); SET_DATA_BYTE(linedi + 4 * wpl, j, L_MAX(val4, maxval)); SET_DATA_BYTE(linedi + 5 * wpl, j, L_MAX(maxval, val7)); maxval = L_MAX(val7, val8); SET_DATA_BYTE(linedi + 6 * wpl, j, L_MAX(val6, maxval)); SET_DATA_BYTE(linedi + 7 * wpl, j, L_MAX(maxval, val9)); } } return pixd; }
/*! * pixCreateTemplate() * * Input: pixs * Return: pixd, or null on error * * Notes: * (1) Makes a Pix of the same size as the input Pix, with the * data array allocated and initialized to 0. * (2) Copies the other fields, including colormap if it exists. */ PIX * pixCreateTemplate(PIX *pixs) { PIX *pixd; PROCNAME("pixCreateTemplate"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); if ((pixd = pixCreateTemplateNoInit(pixs)) == NULL) return (PIX *)ERROR_PTR("pixd not made", procName, NULL); memset(pixd->data, 0, 4 * pixd->wpl * pixd->h); 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; }
//--------------------------------------------------------------------------- //Уменьшение в 2 раза //Поиск угла //Предварительное выпрямление //Эрозия для удаления тонких линий //Поиск box для обрезки белых полей изображения //Обрезка предварительно выпрямленного изображения //Получение трёх изображений: //------------------------------------------------------------------------------ PIX* LeptPrepareFile::getClearImage(PIX *pix, l_float32 *angle, l_float32 *conf) { PIX *pixReduce2, *pixDeskew, *pixCrop, *pixErode; PIXA *pixa1, *pixa2; l_int32 result; l_float32 _angle, _conf; l_int32 XC_crop, YC_crop, XC_old, YC_old, XC_new, YC_new; LEP_LOG("enter"); SetNULL(7, (void **)&pixReduce2, &pixDeskew, &pixCrop, &pixErode, &pixa1, &pixa2, &boxFirstCrop); SetNULL(2, (void **)angle, conf); try { LEP_STR_THROW(!pix, "Изображение не найдено"); //Уменьшение в 2 раза для ускорения (при DPI = 600) if ((pix->xres == 600) && (pix->yres == 600)) //В дальнейшем переработать потому как в текущем варианте обрабатывает корректно только DPI300 и DPI600 pixReduce2 = pixReduceBinary2(pix, NULL); else { pixReduce2 = pixCreateTemplateNoInit(pix); LEP_STR_THROW(!pixReduce2, "Ошибка в pixReduceBinary2"); pixCopy(pixReduce2, pix); } LEP_STR_THROW(!pixReduce2, "Ошибка в pixReduceBinary2"); //Поиск угла наклона result = pixFindSkewSweepAndSearch(pixReduce2, &_angle, &_conf, 4, //линеное уменьшение, DEFAULT_SWEEP_REDUCTION = 4 2, //бинарное уменьшение, DEFAULT_BS_REDUCTION = 2 10, //максимальный угол поиска 0.1, //дельта угла поиска 0.01);//конечная дельта угла поиска, DEFAULT_MINBS_DELTA = 0.01 LEP_STR_THROW(result != 0, "Ошибка поиска угла"); if (angle) *angle = _angle; if (conf) *conf = _conf; //Предварительное выпрямление pixDeskew = pixRotate(pixReduce2, 3.1415926535 / 180. * _angle, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, 0, 0); LEP_STR_THROW(!pixDeskew, "Ошибка при предварительном повороте изображения"); //Эрозия для удаления тонких линий pixErode = pixCreateTemplateNoInit(pixDeskew); LEP_STR_THROW(!pixErode, "Ошибка в pixCreateTemplateNoInit"); pixCopy(pixErode, pixDeskew); pixErodeBrick(pixErode, pixErode, 3, 3); //pixWrite("c:\\temp0_0.tif", pixErode, IFF_TIFF_ZIP); //Поиск box для обрезки белых полей изображения result = pixClipBoxToForeground(pixErode, NULL, NULL, &boxFirstCrop); LEP_STR_THROW(result != 0, "Ошибка при поиске обрезки изображения"); //Получение точки вокруг которой происходило вращение, с учётом обрезки XC_old = pixErode->w / 2; //точка вращения старого изображения на старом изображении YC_old = pixErode->h / 2; XC_new = boxFirstCrop->w / 2; //точка вращения нового изображения на новом изображении YC_new = boxFirstCrop->h / 2; XC_crop = boxFirstCrop->x + XC_new; //точка вращения нового изображения на старом изображении YC_crop = boxFirstCrop->y + YC_new; centerXRotate = XC_new - (XC_crop - XC_old); //точка вращения старого изображения на новом изображении centerYRotate = YC_new - (YC_crop - YC_old); //Обрезка предварительно выпрямленного изображения pixCrop = pixClipRectangle(pixDeskew, boxFirstCrop, NULL); LEP_STR_THROW(!pixCrop, "Ошибка при обрезке изображения"); //pixWrite("c:\\pixCrop.tif", pixCrop, IFF_TIFF_ZIP); }catch (string error) { LEP_ERROR(error); }; pixDestroy(&pixReduce2); pixDestroy(&pixDeskew); pixDestroy(&pixErode); LEP_LOG("exit"); return pixCrop; }
/*! * pixRotateBySampling() * * Input: pixs (1, 2, 4, 8, 16, 32 bpp rgb; can be cmapped) * xcen (x value of center of rotation) * ycen (y value of center of rotation) * angle (radians; clockwise is positive) * incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK) * Return: pixd, or null on error * * Notes: * (1) For very small rotations, just return a clone. * (2) Rotation brings either white or black pixels in * from outside the image. * (3) Colormaps are retained. */ PIX * pixRotateBySampling(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor) { l_int32 w, h, d, i, j, x, y, xdif, ydif, wm1, hm1, wpld; l_uint32 val; l_float32 sina, cosa; l_uint32 *datad, *lined; void **lines; PIX *pixd; PROCNAME("pixRotateBySampling"); if (!pixs) return (PIX *) ERROR_PTR("pixs not defined", procName, NULL); if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK) return (PIX *) ERROR_PTR("invalid incolor", procName, NULL); pixGetDimensions(pixs, &w, &h, &d); if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32) return (PIX *) ERROR_PTR("invalid depth", procName, NULL); if (L_ABS(angle) < MIN_ANGLE_TO_ROTATE) return pixClone(pixs); if ((pixd = pixCreateTemplateNoInit(pixs)) == NULL) return (PIX *) ERROR_PTR("pixd not made", procName, NULL); pixSetBlackOrWhite(pixd, incolor); sina = sin(angle); cosa = cos(angle); datad = pixGetData(pixd); wpld = pixGetWpl(pixd); wm1 = w - 1; hm1 = h - 1; lines = pixGetLinePtrs(pixs, NULL); /* Treat 1 bpp case specially */ if (d == 1) { for (i = 0; i < h; i++) { /* scan over pixd */ lined = datad + i * wpld; ydif = ycen - i; for (j = 0; j < w; j++) { xdif = xcen - j; x = xcen + (l_int32)(-xdif * cosa - ydif * sina); if (x < 0 || x > wm1) continue; y = ycen + (l_int32)(-ydif * cosa + xdif * sina); if (y < 0 || y > hm1) continue; if (incolor == L_BRING_IN_WHITE) { if (GET_DATA_BIT(lines[y], x)) SET_DATA_BIT(lined, j); } else { if (!GET_DATA_BIT(lines[y], x)) CLEAR_DATA_BIT(lined, j); } } } FREE(lines); return pixd; } for (i = 0; i < h; i++) { /* scan over pixd */ lined = datad + i * wpld; ydif = ycen - i; for (j = 0; j < w; j++) { xdif = xcen - j; x = xcen + (l_int32)(-xdif * cosa - ydif * sina); if (x < 0 || x > wm1) continue; y = ycen + (l_int32)(-ydif * cosa + xdif * sina); if (y < 0 || y > hm1) continue; switch (d) { case 8: val = GET_DATA_BYTE(lines[y], x); SET_DATA_BYTE(lined, j, val); break; case 32: val = GET_DATA_FOUR_BYTES(lines[y], x); SET_DATA_FOUR_BYTES(lined, j, val); break; case 2: val = GET_DATA_DIBIT(lines[y], x); SET_DATA_DIBIT(lined, j, val); break; case 4: val = GET_DATA_QBIT(lines[y], x); SET_DATA_QBIT(lined, j, val); break; case 16: val = GET_DATA_TWO_BYTES(lines[y], x); SET_DATA_TWO_BYTES(lined, j, val); break; default: return (PIX *) ERROR_PTR("invalid depth", procName, NULL); } } } FREE(lines); return pixd; }