/*! * pixAddConstantGray() * * Input: pixs (8, 16 or 32 bpp) * val (amount to add to each pixel) * Return: 0 if OK, 1 on error * * Notes: * (1) In-place operation. * (2) No clipping for 32 bpp. * (3) For 8 and 16 bpp, if val > 0 the result is clipped * to 0xff and 0xffff, rsp. * (4) For 8 and 16 bpp, if val < 0 the result is clipped to 0. */ l_int32 pixAddConstantGray(PIX *pixs, l_int32 val) { l_int32 i, j, w, h, d, wpl, pval; l_uint32 *data, *line; PROCNAME("pixAddConstantGray"); if (!pixs) return ERROR_INT("pixs not defined", procName, 1); pixGetDimensions(pixs, &w, &h, &d); if (d != 8 && d != 16 && d != 32) return ERROR_INT("pixs not 8, 16 or 32 bpp", procName, 1); data = pixGetData(pixs); wpl = pixGetWpl(pixs); for (i = 0; i < h; i++) { line = data + i * wpl; if (d == 8) { if (val < 0) { for (j = 0; j < w; j++) { pval = GET_DATA_BYTE(line, j); pval = L_MAX(0, pval + val); SET_DATA_BYTE(line, j, pval); } } else { /* val >= 0 */ for (j = 0; j < w; j++) { pval = GET_DATA_BYTE(line, j); pval = L_MIN(255, pval + val); SET_DATA_BYTE(line, j, pval); } } } else if (d == 16) { if (val < 0) { for (j = 0; j < w; j++) { pval = GET_DATA_TWO_BYTES(line, j); pval = L_MAX(0, pval + val); SET_DATA_TWO_BYTES(line, j, pval); } } else { /* val >= 0 */ for (j = 0; j < w; j++) { pval = GET_DATA_TWO_BYTES(line, j); pval = L_MIN(0xffff, pval + val); SET_DATA_TWO_BYTES(line, j, pval); } } } else { /* d == 32; no check for overflow (< 0 or > 0xffffffff) */ for (j = 0; j < w; j++) *(line + j) += val; } } return 0; }
/*! * addConstantGrayLow() */ void addConstantGrayLow(l_uint32 *data, l_int32 w, l_int32 h, l_int32 d, l_int32 wpl, l_int32 val) { l_int32 i, j, pval; l_uint32 *line; for (i = 0; i < h; i++) { line = data + i * wpl; if (d == 8) { if (val < 0) { for (j = 0; j < w; j++) { pval = GET_DATA_BYTE(line, j); pval = L_MAX(0, pval + val); SET_DATA_BYTE(line, j, pval); } } else { /* val >= 0 */ for (j = 0; j < w; j++) { pval = GET_DATA_BYTE(line, j); pval = L_MIN(255, pval + val); SET_DATA_BYTE(line, j, pval); } } } else if (d == 16) { if (val < 0) { for (j = 0; j < w; j++) { pval = GET_DATA_TWO_BYTES(line, j); pval = L_MAX(0, pval + val); SET_DATA_TWO_BYTES(line, j, pval); } } else { /* val >= 0 */ for (j = 0; j < w; j++) { pval = GET_DATA_TWO_BYTES(line, j); pval = L_MIN(0xffff, pval + val); SET_DATA_TWO_BYTES(line, j, pval); } } } else { /* d == 32; no check for overflow (< 0 or > 0xffffffff) */ for (j = 0; j < w; j++) *(line + j) += val; } } return; }
/*! * addGrayLow() */ void addGrayLow(l_uint32 *datad, l_int32 w, l_int32 h, l_int32 d, l_int32 wpld, l_uint32 *datas, l_int32 wpls) { l_int32 i, j, val, sum; l_uint32 *lines, *lined; for (i = 0; i < h; i++) { lined = datad + i * wpld; lines = datas + i * wpls; if (d == 8) { for (j = 0; j < w; j++) { sum = GET_DATA_BYTE(lines, j) + GET_DATA_BYTE(lined, j); val = L_MIN(sum, 255); SET_DATA_BYTE(lined, j, val); } } else if (d == 16) { for (j = 0; j < w; j++) { sum = GET_DATA_TWO_BYTES(lines, j) + GET_DATA_TWO_BYTES(lined, j); val = L_MIN(sum, 0xffff); SET_DATA_TWO_BYTES(lined, j, val); } } else { /* d == 32; no clipping */ for (j = 0; j < w; j++) *(lined + j) += *(lines + j); } } return; }
/*! * subtractGrayLow() */ void subtractGrayLow(l_uint32 *datad, l_int32 w, l_int32 h, l_int32 d, l_int32 wpld, l_uint32 *datas, l_int32 wpls) { l_int32 i, j, val, diff; l_uint32 *lines, *lined; for (i = 0; i < h; i++) { lined = datad + i * wpld; lines = datas + i * wpls; if (d == 8) { for (j = 0; j < w; j++) { diff = GET_DATA_BYTE(lined, j) - GET_DATA_BYTE(lines, j); val = L_MAX(diff, 0); SET_DATA_BYTE(lined, j, val); } } else if (d == 16) { for (j = 0; j < w; j++) { diff = GET_DATA_TWO_BYTES(lined, j) - GET_DATA_TWO_BYTES(lines, j); val = L_MAX(diff, 0); SET_DATA_TWO_BYTES(lined, j, val); } } else { /* d == 32; no clipping */ for (j = 0; j < w; j++) *(lined + j) -= *(lines + j); } } return; }
/*! * pixMultConstantGray() * * Input: pixs (8, 16 or 32 bpp) * val (>= 0.0; amount to multiply by each pixel) * Return: 0 if OK, 1 on error * * Notes: * (1) In-place operation; val must be >= 0. * (2) No clipping for 32 bpp. * (3) For 8 and 16 bpp, the result is clipped to 0xff and 0xffff, rsp. */ l_int32 pixMultConstantGray(PIX *pixs, l_float32 val) { l_int32 i, j, w, h, d, wpl, pval; l_uint32 upval; l_uint32 *data, *line; PROCNAME("pixMultConstantGray"); if (!pixs) return ERROR_INT("pixs not defined", procName, 1); pixGetDimensions(pixs, &w, &h, &d); if (d != 8 && d != 16 && d != 32) return ERROR_INT("pixs not 8, 16 or 32 bpp", procName, 1); if (val < 0.0) return ERROR_INT("val < 0.0", procName, 1); data = pixGetData(pixs); wpl = pixGetWpl(pixs); for (i = 0; i < h; i++) { line = data + i * wpl; if (d == 8) { for (j = 0; j < w; j++) { pval = GET_DATA_BYTE(line, j); pval = (l_int32)(val * pval); pval = L_MIN(255, pval); SET_DATA_BYTE(line, j, pval); } } else if (d == 16) { for (j = 0; j < w; j++) { pval = GET_DATA_TWO_BYTES(line, j); pval = (l_int32)(val * pval); pval = L_MIN(0xffff, pval); SET_DATA_TWO_BYTES(line, j, pval); } } else { /* d == 32; no clipping */ for (j = 0; j < w; j++) { upval = *(line + j); upval = (l_uint32)(val * upval); *(line + j) = upval; } } } return 0; }
/*! * multConstantGrayLow() */ void multConstantGrayLow(l_uint32 *data, l_int32 w, l_int32 h, l_int32 d, l_int32 wpl, l_float32 val) { l_int32 i, j, pval; l_uint32 upval; l_uint32 *line; for (i = 0; i < h; i++) { line = data + i * wpl; if (d == 8) { for (j = 0; j < w; j++) { pval = GET_DATA_BYTE(line, j); pval = (l_int32)(val * pval); pval = L_MIN(255, pval); SET_DATA_BYTE(line, j, pval); } } else if (d == 16) { for (j = 0; j < w; j++) { pval = GET_DATA_TWO_BYTES(line, j); pval = (l_int32)(val * pval); pval = L_MIN(0xffff, pval); SET_DATA_TWO_BYTES(line, j, pval); } } else { /* d == 32; no clipping */ for (j = 0; j < w; j++) { upval = *(line + j); upval = (l_uint32)(val * upval); *(line + j) = upval; } } } return; }
/*! * pixAbsDifference() * * Input: pixs1, pixs2 (both either 8 or 16 bpp gray, or 32 bpp RGB) * Return: pixd, or null on error * * Notes: * (1) The depth of pixs1 and pixs2 must be equal. * (2) Clips computation to the min size, aligning the UL corners * (3) For 8 and 16 bpp, assumes one gray component. * (4) For 32 bpp, assumes 3 color components, and ignores the * LSB of each word (the alpha channel) * (5) Computes the absolute value of the difference between * each component value. */ PIX * pixAbsDifference(PIX *pixs1, PIX *pixs2) { l_int32 i, j, w, h, w2, h2, d, wpls1, wpls2, wpld, val1, val2, diff; l_int32 rval1, gval1, bval1, rval2, gval2, bval2, rdiff, gdiff, bdiff; l_uint32 *datas1, *datas2, *datad, *lines1, *lines2, *lined; PIX *pixd; PROCNAME("pixAbsDifference"); if (!pixs1) return (PIX *)ERROR_PTR("pixs1 not defined", procName, NULL); if (!pixs2) return (PIX *)ERROR_PTR("pixs2 not defined", procName, NULL); d = pixGetDepth(pixs1); if (d != pixGetDepth(pixs2)) return (PIX *)ERROR_PTR("src1 and src2 depths unequal", procName, NULL); if (d != 8 && d != 16 && d != 32) return (PIX *)ERROR_PTR("depths not in {8, 16, 32}", procName, NULL); pixGetDimensions(pixs1, &w, &h, NULL); pixGetDimensions(pixs2, &w2, &h2, NULL); w = L_MIN(w, w2); h = L_MIN(h, h2); if ((pixd = pixCreate(w, h, d)) == NULL) return (PIX *)ERROR_PTR("pixd not made", procName, NULL); pixCopyResolution(pixd, pixs1); datas1 = pixGetData(pixs1); datas2 = pixGetData(pixs2); datad = pixGetData(pixd); wpls1 = pixGetWpl(pixs1); wpls2 = pixGetWpl(pixs2); wpld = pixGetWpl(pixd); if (d == 8) { for (i = 0; i < h; i++) { lines1 = datas1 + i * wpls1; lines2 = datas2 + i * wpls2; lined = datad + i * wpld; for (j = 0; j < w; j++) { val1 = GET_DATA_BYTE(lines1, j); val2 = GET_DATA_BYTE(lines2, j); diff = L_ABS(val1 - val2); SET_DATA_BYTE(lined, j, diff); } } } else if (d == 16) { for (i = 0; i < h; i++) { lines1 = datas1 + i * wpls1; lines2 = datas2 + i * wpls2; lined = datad + i * wpld; for (j = 0; j < w; j++) { val1 = GET_DATA_TWO_BYTES(lines1, j); val2 = GET_DATA_TWO_BYTES(lines2, j); diff = L_ABS(val1 - val2); SET_DATA_TWO_BYTES(lined, j, diff); } } } else { /* d == 32 */ for (i = 0; i < h; i++) { lines1 = datas1 + i * wpls1; lines2 = datas2 + i * wpls2; lined = datad + i * wpld; for (j = 0; j < w; j++) { extractRGBValues(lines1[j], &rval1, &gval1, &bval1); extractRGBValues(lines2[j], &rval2, &gval2, &bval2); rdiff = L_ABS(rval1 - rval2); gdiff = L_ABS(gval1 - gval2); bdiff = L_ABS(bval1 - bval2); composeRGBPixel(rdiff, gdiff, bdiff, lined + j); } } } return pixd; }
/*! * pixMinOrMax() * * Input: pixd (<optional> destination: this can be null, * equal to pixs1, or different from pixs1) * pixs1 (can be == to pixd) * pixs2 * type (L_CHOOSE_MIN, L_CHOOSE_MAX) * Return: pixd always * * Notes: * (1) This gives the min or max of two images. * (2) The depth can be 8 or 16 bpp. * (3) There are 3 cases: * - if pixd == null, Min(src1, src2) --> new pixd * - if pixd == pixs1, Min(src1, src2) --> src1 (in-place) * - if pixd != pixs1, Min(src1, src2) --> input pixd */ PIX * pixMinOrMax(PIX *pixd, PIX *pixs1, PIX *pixs2, l_int32 type) { l_int32 d, ws, hs, w, h, wpls, wpld, i, j; l_int32 vals, vald, val; l_uint32 *datas, *datad, *lines, *lined; PROCNAME("pixMinOrMax"); if (!pixs1) return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd); if (!pixs2) return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd); if (pixs1 == pixs2) return (PIX *)ERROR_PTR("pixs1 and pixs2 must differ", procName, pixd); if (type != L_CHOOSE_MIN && type != L_CHOOSE_MAX) return (PIX *)ERROR_PTR("invalid type", procName, pixd); d = pixGetDepth(pixs1); if (pixGetDepth(pixs2) != d) return (PIX *)ERROR_PTR("depths unequal", procName, pixd); if (d != 8 && d != 16) return (PIX *)ERROR_PTR("depth not 8 or 16 bpp", procName, pixd); if (pixs1 != pixd) pixd = pixCopy(pixd, pixs1); pixGetDimensions(pixs2, &ws, &hs, NULL); pixGetDimensions(pixd, &w, &h, NULL); w = L_MIN(w, ws); h = L_MIN(h, hs); datas = pixGetData(pixs2); datad = pixGetData(pixd); wpls = pixGetWpl(pixs2); wpld = pixGetWpl(pixd); for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + i * wpld; if (d == 8) { if (type == L_CHOOSE_MIN) { for (j = 0; j < w; j++) { vals = GET_DATA_BYTE(lines, j); vald = GET_DATA_BYTE(lined, j); val = L_MIN(vals, vald); SET_DATA_BYTE(lined, j, val); } } else { /* type == L_CHOOSE_MAX */ for (j = 0; j < w; j++) { vals = GET_DATA_BYTE(lines, j); vald = GET_DATA_BYTE(lined, j); val = L_MAX(vals, vald); SET_DATA_BYTE(lined, j, val); } } } else { /* d == 16 */ if (type == L_CHOOSE_MIN) { for (j = 0; j < w; j++) { vals = GET_DATA_TWO_BYTES(lines, j); vald = GET_DATA_TWO_BYTES(lined, j); val = L_MIN(vals, vald); SET_DATA_TWO_BYTES(lined, j, val); } } else { /* type == L_CHOOSE_MAX */ for (j = 0; j < w; j++) { vals = GET_DATA_TWO_BYTES(lines, j); vald = GET_DATA_TWO_BYTES(lined, j); val = L_MAX(vals, vald); SET_DATA_TWO_BYTES(lined, j, val); } } } } return pixd; }
main(int argc, char **argv) { l_int32 x, y, i, j, k, w, h, w2, w4, w8, w16, w32, wpl, nerrors; l_int32 count1, count2, count3, ret, val1, val2; l_uint32 val32; l_uint32 *data, *line, *line1, *line2, *data1, *data2; void **lines1, **linet1, **linet2; PIX *pixs, *pixt1, *pixt2; static char mainName[] = "lowaccess_reg"; pixs = pixRead("feyn.tif"); /* width divisible by 16 */ pixGetDimensions(pixs, &w, &h, NULL); data = pixGetData(pixs); wpl = pixGetWpl(pixs); lines1 = pixGetLinePtrs(pixs, NULL); /* Get timing for the 3 different methods */ startTimer(); for (k = 0; k < 10; k++) { count1 = 0; for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { if (GET_DATA_BIT(lines1[i], j)) count1++; } } } fprintf(stderr, "Time with line ptrs = %5.3f sec, count1 = %d\n", stopTimer(), count1); startTimer(); for (k = 0; k < 10; k++) { count2 = 0; for (i = 0; i < h; i++) { line = data + i * wpl; for (j = 0; j < w; j++) { if (l_getDataBit(line, j)) count2++; } } } fprintf(stderr, "Time with l_get* = %5.3f sec, count2 = %d\n", stopTimer(), count2); startTimer(); for (k = 0; k < 10; k++) { count3 = 0; for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { pixGetPixel(pixs, j, i, &val32); count3 += val32; } } } fprintf(stderr, "Time with pixGetPixel() = %5.3f sec, count3 = %d\n", stopTimer(), count3); pixt1 = pixCreateTemplate(pixs); data1 = pixGetData(pixt1); linet1 = pixGetLinePtrs(pixt1, NULL); pixt2 = pixCreateTemplate(pixs); data2 = pixGetData(pixt2); linet2 = pixGetLinePtrs(pixt2, NULL); nerrors = 0; /* Test different methods for 1 bpp */ count1 = 0; for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { val1 = GET_DATA_BIT(lines1[i], j); count1 += val1; if (val1) SET_DATA_BIT(linet1[i], j); } } count2 = 0; for (i = 0; i < h; i++) { line = data + i * wpl; line2 = data2 + i * wpl; for (j = 0; j < w; j++) { val2 = l_getDataBit(line, j); count2 += val2; if (val2) l_setDataBit(line2, j); } } ret = compareResults(pixs, pixt1, pixt2, count1, count2, "1 bpp"); nerrors += ret; /* Test different methods for 2 bpp */ count1 = 0; w2 = w / 2; for (i = 0; i < h; i++) { for (j = 0; j < w2; j++) { val1 = GET_DATA_DIBIT(lines1[i], j); count1 += val1; val1 += 0xbbbbbbbc; SET_DATA_DIBIT(linet1[i], j, val1); } } count2 = 0; for (i = 0; i < h; i++) { line = data + i * wpl; line2 = data2 + i * wpl; for (j = 0; j < w2; j++) { val2 = l_getDataDibit(line, j); count2 += val2; val2 += 0xbbbbbbbc; l_setDataDibit(line2, j, val2); } } ret = compareResults(pixs, pixt1, pixt2, count1, count2, "2 bpp"); nerrors += ret; /* Test different methods for 4 bpp */ count1 = 0; w4 = w / 4; for (i = 0; i < h; i++) { for (j = 0; j < w4; j++) { val1 = GET_DATA_QBIT(lines1[i], j); count1 += val1; val1 += 0xbbbbbbb0; SET_DATA_QBIT(linet1[i], j, val1); } } count2 = 0; for (i = 0; i < h; i++) { line = data + i * wpl; line2 = data2 + i * wpl; for (j = 0; j < w4; j++) { val2 = l_getDataQbit(line, j); count2 += val2; val2 += 0xbbbbbbb0; l_setDataQbit(line2, j, val2); } } ret = compareResults(pixs, pixt1, pixt2, count1, count2, "4 bpp"); nerrors += ret; /* Test different methods for 8 bpp */ count1 = 0; w8 = w / 8; for (i = 0; i < h; i++) { for (j = 0; j < w8; j++) { val1 = GET_DATA_BYTE(lines1[i], j); count1 += val1; val1 += 0xbbbbbb00; SET_DATA_BYTE(linet1[i], j, val1); } } count2 = 0; for (i = 0; i < h; i++) { line = data + i * wpl; line2 = data2 + i * wpl; for (j = 0; j < w8; j++) { val2 = l_getDataByte(line, j); count2 += val2; val2 += 0xbbbbbb00; l_setDataByte(line2, j, val2); } } ret = compareResults(pixs, pixt1, pixt2, count1, count2, "8 bpp"); nerrors += ret; /* Test different methods for 16 bpp */ count1 = 0; w16 = w / 16; for (i = 0; i < h; i++) { for (j = 0; j < w16; j++) { val1 = GET_DATA_TWO_BYTES(lines1[i], j); count1 += val1; val1 += 0xbbbb0000; SET_DATA_TWO_BYTES(linet1[i], j, val1); } } count2 = 0; for (i = 0; i < h; i++) { line = data + i * wpl; line2 = data2 + i * wpl; for (j = 0; j < w16; j++) { val2 = l_getDataTwoBytes(line, j); count2 += val2; val2 += 0xbbbb0000; l_setDataTwoBytes(line2, j, val2); } } ret = compareResults(pixs, pixt1, pixt2, count1, count2, "16 bpp"); nerrors += ret; /* Test different methods for 32 bpp */ count1 = 0; w32 = w / 32; for (i = 0; i < h; i++) { for (j = 0; j < w32; j++) { val1 = GET_DATA_FOUR_BYTES(lines1[i], j); count1 += val1 & 0xfff; SET_DATA_FOUR_BYTES(linet1[i], j, val1); } } count2 = 0; for (i = 0; i < h; i++) { line = data + i * wpl; line2 = data2 + i * wpl; for (j = 0; j < w32; j++) { val2 = l_getDataFourBytes(line, j); count2 += val2 & 0xfff; l_setDataFourBytes(line2, j, val2); } } ret = compareResults(pixs, pixt1, pixt2, count1, count2, "32 bpp"); nerrors += ret; if (!nerrors) fprintf(stderr, "**** No errors ****\n"); else fprintf(stderr, "**** %d errors found! ****\n", nerrors); pixDestroy(&pixs); pixDestroy(&pixt1); pixDestroy(&pixt2); lept_free(lines1); lept_free(linet1); lept_free(linet2); return 0; }
/*! * absDifferenceLow() * * Finds the absolute value of the difference of each pixel, * for 8 and 16 bpp gray and for 32 bpp rgb. For 32 bpp, the * differences are found for each of the RGB components * separately, and the LSB component is ignored. * The results are written into datad. */ void absDifferenceLow(l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datas1, l_uint32 *datas2, l_int32 d, l_int32 wpls) { l_int32 i, j, val1, val2, diff; l_uint32 word1, word2; l_uint32 *lines1, *lines2, *lined, *pdword; PROCNAME("absDifferenceLow"); switch (d) { case 8: for (i = 0; i < h; i++) { lines1 = datas1 + i * wpls; lines2 = datas2 + i * wpls; lined = datad + i * wpld; for (j = 0; j < w; j++) { val1 = GET_DATA_BYTE(lines1, j); val2 = GET_DATA_BYTE(lines2, j); diff = L_ABS(val1 - val2); SET_DATA_BYTE(lined, j, diff); } } break; case 16: for (i = 0; i < h; i++) { lines1 = datas1 + i * wpls; lines2 = datas2 + i * wpls; lined = datad + i * wpld; for (j = 0; j < w; j++) { val1 = GET_DATA_TWO_BYTES(lines1, j); val2 = GET_DATA_TWO_BYTES(lines2, j); diff = L_ABS(val1 - val2); SET_DATA_TWO_BYTES(lined, j, diff); } } break; case 32: for (i = 0; i < h; i++) { lines1 = datas1 + i * wpls; lines2 = datas2 + i * wpls; lined = datad + i * wpld; for (j = 0; j < w; j++) { word1 = lines1[j]; word2 = lines2[j]; pdword = lined + j; val1 = GET_DATA_BYTE(&word1, COLOR_RED); val2 = GET_DATA_BYTE(&word2, COLOR_RED); diff = L_ABS(val1 - val2); SET_DATA_BYTE(pdword, COLOR_RED, diff); val1 = GET_DATA_BYTE(&word1, COLOR_GREEN); val2 = GET_DATA_BYTE(&word2, COLOR_GREEN); diff = L_ABS(val1 - val2); SET_DATA_BYTE(pdword, COLOR_GREEN, diff); val1 = GET_DATA_BYTE(&word1, COLOR_BLUE); val2 = GET_DATA_BYTE(&word2, COLOR_BLUE); diff = L_ABS(val1 - val2); SET_DATA_BYTE(pdword, COLOR_BLUE, diff); } } break; default: L_ERROR("source depth must be 8, 16 or 32 bpp", procName); break; } return; }
/*! * pixMinOrMax() * * Input: pixd (<optional> destination: this can be null, * equal to pixs1, or different from pixs1) * pixs1 (can be == to pixd) * pixs2 * type (L_CHOOSE_MIN, L_CHOOSE_MAX) * Return: pixd always * * Notes: * (1) This gives the min or max of two images, component-wise. * (2) The depth can be 8 or 16 bpp for 1 component, and 32 bpp * for a 3 component image. For 32 bpp, ignore the LSB * of each word (the alpha channel) * (3) There are 3 cases: * - if pixd == null, Min(src1, src2) --> new pixd * - if pixd == pixs1, Min(src1, src2) --> src1 (in-place) * - if pixd != pixs1, Min(src1, src2) --> input pixd */ PIX * pixMinOrMax(PIX *pixd, PIX *pixs1, PIX *pixs2, l_int32 type) { l_int32 d, ws, hs, w, h, wpls, wpld, i, j, vals, vald, val; l_int32 rval1, gval1, bval1, rval2, gval2, bval2, rval, gval, bval; l_uint32 *datas, *datad, *lines, *lined; PROCNAME("pixMinOrMax"); if (!pixs1) return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd); if (!pixs2) return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd); if (pixs1 == pixs2) return (PIX *)ERROR_PTR("pixs1 and pixs2 must differ", procName, pixd); if (type != L_CHOOSE_MIN && type != L_CHOOSE_MAX) return (PIX *)ERROR_PTR("invalid type", procName, pixd); d = pixGetDepth(pixs1); if (pixGetDepth(pixs2) != d) return (PIX *)ERROR_PTR("depths unequal", procName, pixd); if (d != 8 && d != 16 && d != 32) return (PIX *)ERROR_PTR("depth not 8, 16 or 32 bpp", procName, pixd); if (pixs1 != pixd) pixd = pixCopy(pixd, pixs1); pixGetDimensions(pixs2, &ws, &hs, NULL); pixGetDimensions(pixd, &w, &h, NULL); w = L_MIN(w, ws); h = L_MIN(h, hs); datas = pixGetData(pixs2); datad = pixGetData(pixd); wpls = pixGetWpl(pixs2); wpld = pixGetWpl(pixd); for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + i * wpld; if (d == 8) { for (j = 0; j < w; j++) { vals = GET_DATA_BYTE(lines, j); vald = GET_DATA_BYTE(lined, j); if (type == L_CHOOSE_MIN) val = L_MIN(vals, vald); else /* type == L_CHOOSE_MAX */ val = L_MAX(vals, vald); SET_DATA_BYTE(lined, j, val); } } else if (d == 16) { for (j = 0; j < w; j++) { vals = GET_DATA_TWO_BYTES(lines, j); vald = GET_DATA_TWO_BYTES(lined, j); if (type == L_CHOOSE_MIN) val = L_MIN(vals, vald); else /* type == L_CHOOSE_MAX */ val = L_MAX(vals, vald); SET_DATA_TWO_BYTES(lined, j, val); } } else { /* d == 32 */ for (j = 0; j < w; j++) { extractRGBValues(lines[j], &rval1, &gval1, &bval1); extractRGBValues(lined[j], &rval2, &gval2, &bval2); if (type == L_CHOOSE_MIN) { rval = L_MIN(rval1, rval2); gval = L_MIN(gval1, gval2); bval = L_MIN(bval1, bval2); } else { /* type == L_CHOOSE_MAX */ rval = L_MAX(rval1, rval2); gval = L_MAX(gval1, gval2); bval = L_MAX(bval1, bval2); } composeRGBPixel(rval, gval, bval, lined + j); } } } return pixd; }
/*! * \brief pixWriteStreamPnm() * * \param[in] fp file stream opened for write * \param[in] pix * \return 0 if OK; 1 on error * * <pre> * Notes: * (1) This writes "raw" packed format only: * 1 bpp --\> pbm (P4) * 2, 4, 8, 16 bpp, no colormap or grayscale colormap --\> pgm (P5) * 2, 4, 8 bpp with color-valued colormap, or rgb --\> rgb ppm (P6) * (2) 24 bpp rgb are not supported in leptonica, but this will * write them out as a packed array of bytes (3 to a pixel). * </pre> */ l_int32 pixWriteStreamPnm(FILE *fp, PIX *pix) { l_uint8 val8; l_uint8 pel[4]; l_uint16 val16; l_int32 h, w, d, ds, i, j, wpls, bpl, filebpl, writeerror, maxval; l_uint32 *pword, *datas, *lines; PIX *pixs; PROCNAME("pixWriteStreamPnm"); if (!fp) return ERROR_INT("fp not defined", procName, 1); if (!pix) return ERROR_INT("pix not defined", procName, 1); pixGetDimensions(pix, &w, &h, &d); if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32) return ERROR_INT("d not in {1,2,4,8,16,24,32}", procName, 1); /* If a colormap exists, remove and convert to grayscale or rgb */ if (pixGetColormap(pix) != NULL) pixs = pixRemoveColormap(pix, REMOVE_CMAP_BASED_ON_SRC); else pixs = pixClone(pix); ds = pixGetDepth(pixs); datas = pixGetData(pixs); wpls = pixGetWpl(pixs); writeerror = 0; if (ds == 1) { /* binary */ fprintf(fp, "P4\n# Raw PBM file written by leptonica " "(www.leptonica.com)\n%d %d\n", w, h); bpl = (w + 7) / 8; for (i = 0; i < h; i++) { lines = datas + i * wpls; for (j = 0; j < bpl; j++) { val8 = GET_DATA_BYTE(lines, j); fwrite(&val8, 1, 1, fp); } } } else if (ds == 2 || ds == 4 || ds == 8 || ds == 16) { /* grayscale */ maxval = (1 << ds) - 1; fprintf(fp, "P5\n# Raw PGM file written by leptonica " "(www.leptonica.com)\n%d %d\n%d\n", w, h, maxval); if (ds != 16) { for (i = 0; i < h; i++) { lines = datas + i * wpls; for (j = 0; j < w; j++) { if (ds == 2) val8 = GET_DATA_DIBIT(lines, j); else if (ds == 4) val8 = GET_DATA_QBIT(lines, j); else /* ds == 8 */ val8 = GET_DATA_BYTE(lines, j); fwrite(&val8, 1, 1, fp); } } } else { /* ds == 16 */ for (i = 0; i < h; i++) { lines = datas + i * wpls; for (j = 0; j < w; j++) { val16 = GET_DATA_TWO_BYTES(lines, j); fwrite(&val16, 2, 1, fp); } } } } else { /* rgb color */ fprintf(fp, "P6\n# Raw PPM file written by leptonica " "(www.leptonica.com)\n%d %d\n255\n", w, h); if (d == 24) { /* packed, 3 bytes to a pixel */ filebpl = 3 * w; for (i = 0; i < h; i++) { /* write out each raster line */ lines = datas + i * wpls; if (fwrite(lines, 1, filebpl, fp) != filebpl) writeerror = 1; } } else { /* 32 bpp rgb */ for (i = 0; i < h; i++) { lines = datas + i * wpls; for (j = 0; j < wpls; j++) { pword = lines + j; pel[0] = GET_DATA_BYTE(pword, COLOR_RED); pel[1] = GET_DATA_BYTE(pword, COLOR_GREEN); pel[2] = GET_DATA_BYTE(pword, COLOR_BLUE); if (fwrite(pel, 1, 3, fp) != 3) writeerror = 1; } } } } pixDestroy(&pixs); if (writeerror) return ERROR_INT("image write fail", procName, 1); return 0; }
/*! * pixConvertToFPix() * * Input: pix (1, 2, 4, 8, 16 or 32 bpp) * ncomps (number of components: 3 for RGB, 1 otherwise) * Return: fpix, or null on error * * Notes: * (1) If colormapped, remove to grayscale. * (2) If 32 bpp and @ncomps == 3, this is RGB; convert to luminance. * In all other cases the src image is treated as having a single * component of pixel values. */ FPIX * pixConvertToFPix(PIX *pixs, l_int32 ncomps) { l_int32 w, h, d, i, j, val, wplt, wpld; l_uint32 uval; l_uint32 *datat, *linet; l_float32 *datad, *lined; PIX *pixt; FPIX *fpixd; PROCNAME("pixConvertToFPix"); if (!pixs) return (FPIX *)ERROR_PTR("pixs not defined", procName, NULL); if (pixGetColormap(pixs)) pixt = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE); else if (pixGetDepth(pixs) == 32 && ncomps == 3) pixt = pixConvertRGBToLuminance(pixs); else pixt = pixClone(pixs); pixGetDimensions(pixt, &w, &h, &d); if ((fpixd = fpixCreate(w, h)) == NULL) return (FPIX *)ERROR_PTR("fpixd not made", procName, NULL); datat = pixGetData(pixt); wplt = pixGetWpl(pixt); datad = fpixGetData(fpixd); wpld = fpixGetWpl(fpixd); for (i = 0; i < h; i++) { linet = datat + i * wplt; lined = datad + i * wpld; if (d == 1) { for (j = 0; j < w; j++) { val = GET_DATA_BIT(linet, j); lined[j] = (l_float32)val; } } else if (d == 2) { for (j = 0; j < w; j++) { val = GET_DATA_DIBIT(linet, j); lined[j] = (l_float32)val; } } else if (d == 4) { for (j = 0; j < w; j++) { val = GET_DATA_QBIT(linet, j); lined[j] = (l_float32)val; } } else if (d == 8) { for (j = 0; j < w; j++) { val = GET_DATA_BYTE(linet, j); lined[j] = (l_float32)val; } } else if (d == 16) { for (j = 0; j < w; j++) { val = GET_DATA_TWO_BYTES(linet, j); lined[j] = (l_float32)val; } } else if (d == 32) { for (j = 0; j < w; j++) { uval = GET_DATA_FOUR_BYTES(linet, j); lined[j] = (l_float32)uval; } } } pixDestroy(&pixt); return fpixd; }
/*! * pixConvertToDPix() * * Input: pix (1, 2, 4, 8, 16 or 32 bpp) * ncomps (number of components: 3 for RGB, 1 otherwise) * shiftflag (L_NO_SHIFTING or L_WITH_SHIFTING) * Return: dpix, or null on error * * Notes: * (1) If colormapped, remove to grayscale. * (2) If 32 bpp and @ncomps == 3, this is RGB; convert to luminance. * In all other cases the src image is treated as having a single * component of pixel values. * (3) Set @shiftflag to L_WITH_SHIFTING to move the DC of the * the DFT to the center of pix. */ DPIX * pixConvertToDPix(PIX *pixs, l_int32 ncomps, l_int32 shiftflag) { l_int32 w, h, d; l_int32 i, j, val, wplt, wpld; l_uint32 uval; l_uint32 *datat, *linet; l_float64 *datad, *lined; PIX *pixt; DPIX *dpixd; PROCNAME("pixConvertToDPix"); if (!pixs) return (DPIX *)ERROR_PTR("pixs not defined", procName, NULL); if (shiftflag != L_NO_SHIFTING && shiftflag != L_WITH_SHIFTING) return (DPIX *)ERROR_PTR("invalid shiftflag", procName, NULL); if (pixGetColormap(pixs)) pixt = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE); else if (pixGetDepth(pixs) == 32 && ncomps == 3) pixt = pixConvertRGBToLuminance(pixs); else pixt = pixClone(pixs); pixGetDimensions(pixt, &w, &h, &d); if ((dpixd = dpixCreate(w, h)) == NULL) return (DPIX *)ERROR_PTR("dpixd not made", procName, NULL); datat = pixGetData(pixt); wplt = pixGetWpl(pixt); datad = dpixGetData(dpixd); wpld = dpixGetWpl(dpixd); for (i = 0; i < h; i++) { linet = datat + i * wplt; lined = datad + i * wpld; if (d == 1) { for (j = 0; j < w; j++) { val = GET_DATA_BIT(linet, j); lined[j] = shiftflag ? (l_float64)(val * pow(-1, i + j)) : (l_float64)val; } } else if (d == 2) { for (j = 0; j < w; j++) { val = GET_DATA_DIBIT(linet, j); lined[j] = shiftflag ? (l_float64)(val * pow(-1, i + j)) : (l_float64)val; } } else if (d == 4) { for (j = 0; j < w; j++) { val = GET_DATA_QBIT(linet, j); lined[j] = shiftflag ? (l_float64)(val * pow(-1, i + j)) : (l_float64)val; } } else if (d == 8) { for (j = 0; j < w; j++) { val = GET_DATA_BYTE(linet, j); lined[j] = shiftflag ? (l_float64)(val * pow(-1, i + j)) : (l_float64)val; } } else if (d == 16) { for (j = 0; j < w; j++) { val = GET_DATA_TWO_BYTES(linet, j); lined[j] = shiftflag ? (l_float64)(val * pow(-1, i + j)) : (l_float64)val; } } else if (d == 32) { for (j = 0; j < w; j++) { uval = GET_DATA_FOUR_BYTES(linet, j); lined[j] = shiftflag ? (l_float64)(uval * pow(-1, i + j)) : (l_float64)uval; } } } pixDestroy(&pixt); return dpixd; }
/*! * thresholdToValueLow() */ void thresholdToValueLow(l_uint32 *datad, l_int32 w, l_int32 h, l_int32 d, l_int32 wpld, l_int32 threshval, l_int32 setval) { l_int32 i, j, setabove; l_uint32 *lined; if (setval > threshval) setabove = TRUE; else setabove = FALSE; for (i = 0; i < h; i++) { lined = datad + i * wpld; if (setabove == TRUE) { if (d == 8) { for (j = 0; j < w; j++) { if (GET_DATA_BYTE(lined, j) - threshval >= 0) SET_DATA_BYTE(lined, j, setval); } } else if (d == 16) { for (j = 0; j < w; j++) { if (GET_DATA_TWO_BYTES(lined, j) - threshval >= 0) SET_DATA_TWO_BYTES(lined, j, setval); } } else { /* d == 32 */ for (j = 0; j < w; j++) { if (*(lined + j) >= threshval) *(lined + j) = setval; } } } else { /* set if below or at threshold */ if (d == 8) { for (j = 0; j < w; j++) { if (GET_DATA_BYTE(lined, j) - threshval <= 0) SET_DATA_BYTE(lined, j, setval); } } else if (d == 16) { for (j = 0; j < w; j++) { if (GET_DATA_TWO_BYTES(lined, j) - threshval <= 0) SET_DATA_TWO_BYTES(lined, j, setval); } } else { /* d == 32 */ for (j = 0; j < w; j++) { if (*(lined + j) <= threshval) *(lined + j) = setval; } } } } return; }
/*! * accumulateLow() */ void accumulateLow(l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datas, l_int32 d, l_int32 wpls, l_int32 op) { l_int32 i, j; l_uint32 *lines, *lined; switch (d) { case 1: for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + i * wpld; if (op == L_ARITH_ADD) { for (j = 0; j < w; j++) lined[j] += GET_DATA_BIT(lines, j); } else { /* op == L_ARITH_SUBTRACT */ for (j = 0; j < w; j++) lined[j] -= GET_DATA_BIT(lines, j); } } break; case 8: for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + i * wpld; if (op == L_ARITH_ADD) { for (j = 0; j < w; j++) lined[j] += GET_DATA_BYTE(lines, j); } else { /* op == L_ARITH_SUBTRACT */ for (j = 0; j < w; j++) lined[j] -= GET_DATA_BYTE(lines, j); } } break; case 16: for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + i * wpld; if (op == L_ARITH_ADD) { for (j = 0; j < w; j++) lined[j] += GET_DATA_TWO_BYTES(lines, j); } else { /* op == L_ARITH_SUBTRACT */ for (j = 0; j < w; j++) lined[j] -= GET_DATA_TWO_BYTES(lines, j); } } break; case 32: for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + i * wpld; if (op == L_ARITH_ADD) { for (j = 0; j < w; j++) lined[j] += lines[j]; } else { /* op == L_ARITH_SUBTRACT */ for (j = 0; j < w; j++) lined[j] -= lines[j]; } } break; } return; }
/*! * pixSubtractGray() * * Input: pixd (<optional>; this can be null, equal to pixs1, or * different from pixs1) * pixs1 (can be == to pixd) * pixs2 * Return: pixd always * * Notes: * (1) Arithmetic subtraction of two 8, 16 or 32 bpp images. * (2) Source pixs2 is always subtracted from source pixs1. * (3) Do explicit clipping to 0. * (4) Alignment is to UL corner. * (5) There are 3 cases. The result can go to a new dest, * in-place to pixs1, or to an existing input dest: * (a) pixd == null (src1 - src2) --> new pixd * (b) pixd == pixs1 (src1 - src2) --> src1 (in-place) * (d) pixd != pixs1 (src1 - src2) --> input pixd * (6) pixs2 must be different from both pixd and pixs1. */ PIX * pixSubtractGray(PIX *pixd, PIX *pixs1, PIX *pixs2) { l_int32 i, j, w, h, ws, hs, d, wpls, wpld, val, diff; l_uint32 *datas, *datad, *lines, *lined; PROCNAME("pixSubtractGray"); if (!pixs1) return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd); if (!pixs2) return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd); if (pixs2 == pixs1) return (PIX *)ERROR_PTR("pixs2 and pixs1 must differ", procName, pixd); if (pixs2 == pixd) return (PIX *)ERROR_PTR("pixs2 and pixd must differ", procName, pixd); d = pixGetDepth(pixs1); if (d != 8 && d != 16 && d != 32) return (PIX *)ERROR_PTR("pix are not 8, 16 or 32 bpp", procName, pixd); if (pixGetDepth(pixs2) != d) return (PIX *)ERROR_PTR("depths differ (pixs1, pixs2)", procName, pixd); if (pixd && (pixGetDepth(pixd) != d)) return (PIX *)ERROR_PTR("depths differ (pixs1, pixd)", procName, pixd); if (!pixSizesEqual(pixs1, pixs2)) L_WARNING("pixs1 and pixs2 not equal in size\n", procName); if (pixd && !pixSizesEqual(pixs1, pixd)) L_WARNING("pixs1 and pixd not equal in size\n", procName); if (pixs1 != pixd) pixd = pixCopy(pixd, pixs1); /* pixd - pixs2 ==> pixd */ datas = pixGetData(pixs2); datad = pixGetData(pixd); wpls = pixGetWpl(pixs2); wpld = pixGetWpl(pixd); pixGetDimensions(pixs2, &ws, &hs, NULL); pixGetDimensions(pixd, &w, &h, NULL); w = L_MIN(ws, w); h = L_MIN(hs, h); for (i = 0; i < h; i++) { lined = datad + i * wpld; lines = datas + i * wpls; if (d == 8) { for (j = 0; j < w; j++) { diff = GET_DATA_BYTE(lined, j) - GET_DATA_BYTE(lines, j); val = L_MAX(diff, 0); SET_DATA_BYTE(lined, j, val); } } else if (d == 16) { for (j = 0; j < w; j++) { diff = GET_DATA_TWO_BYTES(lined, j) - GET_DATA_TWO_BYTES(lines, j); val = L_MAX(diff, 0); SET_DATA_TWO_BYTES(lined, j, val); } } else { /* d == 32; no clipping */ for (j = 0; j < w; j++) *(lined + j) -= *(lines + j); } } return pixd; }
/*! * pixThresholdToValue() * * Input: pixd (<optional>; if not null, must be equal to pixs) * pixs (8, 16, 32 bpp) * threshval * setval * Return: pixd always * * Notes: * - operation can be in-place (pixs == pixd) or to a new pixd * - if setval > threshval, sets pixels with a value >= threshval to setval * - if setval < threshval, sets pixels with a value <= threshval to setval * - if setval == threshval, no-op */ PIX * pixThresholdToValue(PIX *pixd, PIX *pixs, l_int32 threshval, l_int32 setval) { l_int32 i, j, w, h, d, wpld, setabove; l_uint32 *datad, *lined; PROCNAME("pixThresholdToValue"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, pixd); d = pixGetDepth(pixs); if (d != 8 && d != 16 && d != 32) return (PIX *)ERROR_PTR("pixs not 8, 16 or 32 bpp", procName, pixd); if (pixd && (pixs != pixd)) return (PIX *)ERROR_PTR("pixd exists and is not pixs", procName, pixd); if (threshval < 0 || setval < 0) return (PIX *)ERROR_PTR("threshval & setval not < 0", procName, pixd); if (d == 8 && setval > 255) return (PIX *)ERROR_PTR("setval > 255 for 8 bpp", procName, pixd); if (d == 16 && setval > 0xffff) return (PIX *)ERROR_PTR("setval > 0xffff for 16 bpp", procName, pixd); if (!pixd) pixd = pixCopy(NULL, pixs); if (setval == threshval) { L_WARNING("setval == threshval; no operation\n", procName); return pixd; } datad = pixGetData(pixd); pixGetDimensions(pixd, &w, &h, NULL); wpld = pixGetWpl(pixd); if (setval > threshval) setabove = TRUE; else setabove = FALSE; for (i = 0; i < h; i++) { lined = datad + i * wpld; if (setabove == TRUE) { if (d == 8) { for (j = 0; j < w; j++) { if (GET_DATA_BYTE(lined, j) - threshval >= 0) SET_DATA_BYTE(lined, j, setval); } } else if (d == 16) { for (j = 0; j < w; j++) { if (GET_DATA_TWO_BYTES(lined, j) - threshval >= 0) SET_DATA_TWO_BYTES(lined, j, setval); } } else { /* d == 32 */ for (j = 0; j < w; j++) { if (*(lined + j) >= threshval) *(lined + j) = setval; } } } else { /* set if below or at threshold */ if (d == 8) { for (j = 0; j < w; j++) { if (GET_DATA_BYTE(lined, j) - threshval <= 0) SET_DATA_BYTE(lined, j, setval); } } else if (d == 16) { for (j = 0; j < w; j++) { if (GET_DATA_TWO_BYTES(lined, j) - threshval <= 0) SET_DATA_TWO_BYTES(lined, j, setval); } } else { /* d == 32 */ for (j = 0; j < w; j++) { if (*(lined + j) <= threshval) *(lined + j) = setval; } } } } return pixd; }
/*! * pixAccumulate() * * Input: pixd (32 bpp) * pixs (1, 8, 16 or 32 bpp) * op (L_ARITH_ADD or L_ARITH_SUBTRACT) * Return: 0 if OK; 1 on error * * Notes: * (1) This adds or subtracts each pixs value from pixd. * (2) This clips to the minimum of pixs and pixd, so they * do not need to be the same size. * (3) The alignment is to the origin (UL corner) of pixs & pixd. */ l_int32 pixAccumulate(PIX *pixd, PIX *pixs, l_int32 op) { l_int32 i, j, w, h, d, wd, hd, wpls, wpld; l_uint32 *datas, *datad, *lines, *lined; PROCNAME("pixAccumulate"); if (!pixd || (pixGetDepth(pixd) != 32)) return ERROR_INT("pixd not defined or not 32 bpp", procName, 1); if (!pixs) return ERROR_INT("pixs not defined", procName, 1); d = pixGetDepth(pixs); if (d != 1 && d != 8 && d != 16 && d != 32) return ERROR_INT("pixs not 1, 8, 16 or 32 bpp", procName, 1); if (op != L_ARITH_ADD && op != L_ARITH_SUBTRACT) return ERROR_INT("op must be in {L_ARITH_ADD, L_ARITH_SUBTRACT}", procName, 1); datas = pixGetData(pixs); datad = pixGetData(pixd); wpls = pixGetWpl(pixs); wpld = pixGetWpl(pixd); pixGetDimensions(pixs, &w, &h, NULL); pixGetDimensions(pixd, &wd, &hd, NULL); w = L_MIN(w, wd); h = L_MIN(h, hd); if (d == 1) { for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + i * wpld; if (op == L_ARITH_ADD) { for (j = 0; j < w; j++) lined[j] += GET_DATA_BIT(lines, j); } else { /* op == L_ARITH_SUBTRACT */ for (j = 0; j < w; j++) lined[j] -= GET_DATA_BIT(lines, j); } } } else if (d == 8) { for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + i * wpld; if (op == L_ARITH_ADD) { for (j = 0; j < w; j++) lined[j] += GET_DATA_BYTE(lines, j); } else { /* op == L_ARITH_SUBTRACT */ for (j = 0; j < w; j++) lined[j] -= GET_DATA_BYTE(lines, j); } } } else if (d == 16) { for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + i * wpld; if (op == L_ARITH_ADD) { for (j = 0; j < w; j++) lined[j] += GET_DATA_TWO_BYTES(lines, j); } else { /* op == L_ARITH_SUBTRACT */ for (j = 0; j < w; j++) lined[j] -= GET_DATA_TWO_BYTES(lines, j); } } } else { /* d == 32 */ for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + i * wpld; if (op == L_ARITH_ADD) { for (j = 0; j < w; j++) lined[j] += lines[j]; } else { /* op == L_ARITH_SUBTRACT */ for (j = 0; j < w; j++) lined[j] -= lines[j]; } } } return 0; }
int main(int argc, char **argv) { l_int32 i, j, k, w, h, w2, w4, w8, w16, w32, wpl; l_int32 count1, count2, count3; l_uint32 val32, val1, val2; l_uint32 *data1, *line1, *data2, *line2; void **lines1, **linet1, **linet2; PIX *pixs, *pix1, *pix2; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; pixs = pixRead("feyn-fract.tif"); pixGetDimensions(pixs, &w, &h, NULL); data1 = pixGetData(pixs); wpl = pixGetWpl(pixs); lines1 = pixGetLinePtrs(pixs, NULL); /* Get timing for the 3 different methods */ startTimer(); for (k = 0; k < 10; k++) { count1 = 0; for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { if (GET_DATA_BIT(lines1[i], j)) count1++; } } } fprintf(stderr, "Time with line ptrs = %5.3f sec, count1 = %d\n", stopTimer(), count1); startTimer(); for (k = 0; k < 10; k++) { count2 = 0; for (i = 0; i < h; i++) { line1 = data1 + i * wpl; for (j = 0; j < w; j++) { if (l_getDataBit(line1, j)) count2++; } } } fprintf(stderr, "Time with l_get* = %5.3f sec, count2 = %d\n", stopTimer(), count2); startTimer(); for (k = 0; k < 10; k++) { count3 = 0; for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { pixGetPixel(pixs, j, i, &val32); count3 += val32; } } } fprintf(stderr, "Time with pixGetPixel() = %5.3f sec, count3 = %d\n", stopTimer(), count3); pix1 = pixCreateTemplate(pixs); linet1 = pixGetLinePtrs(pix1, NULL); pix2 = pixCreateTemplate(pixs); data2 = pixGetData(pix2); linet2 = pixGetLinePtrs(pix2, NULL); /* ------------------------------------------------- */ /* Test different methods for 1 bpp */ /* ------------------------------------------------- */ count1 = 0; for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { val1 = GET_DATA_BIT(lines1[i], j); count1 += val1; if (val1) SET_DATA_BIT(linet1[i], j); } } count2 = 0; for (i = 0; i < h; i++) { line1 = data1 + i * wpl; line2 = data2 + i * wpl; for (j = 0; j < w; j++) { val2 = l_getDataBit(line1, j); count2 += val2; if (val2) l_setDataBit(line2, j); } } CompareResults(pixs, pix1, pix2, count1, count2, "1 bpp", rp); /* ------------------------------------------------- */ /* Test different methods for 2 bpp */ /* ------------------------------------------------- */ count1 = 0; w2 = w / 2; for (i = 0; i < h; i++) { for (j = 0; j < w2; j++) { val1 = GET_DATA_DIBIT(lines1[i], j); count1 += val1; val1 += 0xbbbbbbbc; SET_DATA_DIBIT(linet1[i], j, val1); } } count2 = 0; for (i = 0; i < h; i++) { line1 = data1 + i * wpl; line2 = data2 + i * wpl; for (j = 0; j < w2; j++) { val2 = l_getDataDibit(line1, j); count2 += val2; val2 += 0xbbbbbbbc; l_setDataDibit(line2, j, val2); } } CompareResults(pixs, pix1, pix2, count1, count2, "2 bpp", rp); /* ------------------------------------------------- */ /* Test different methods for 4 bpp */ /* ------------------------------------------------- */ count1 = 0; w4 = w / 4; for (i = 0; i < h; i++) { for (j = 0; j < w4; j++) { val1 = GET_DATA_QBIT(lines1[i], j); count1 += val1; val1 += 0xbbbbbbb0; SET_DATA_QBIT(linet1[i], j, val1); } } count2 = 0; for (i = 0; i < h; i++) { line1 = data1 + i * wpl; line2 = data2 + i * wpl; for (j = 0; j < w4; j++) { val2 = l_getDataQbit(line1, j); count2 += val2; val2 += 0xbbbbbbb0; l_setDataQbit(line2, j, val2); } } CompareResults(pixs, pix1, pix2, count1, count2, "4 bpp", rp); /* ------------------------------------------------- */ /* Test different methods for 8 bpp */ /* ------------------------------------------------- */ count1 = 0; w8 = w / 8; for (i = 0; i < h; i++) { for (j = 0; j < w8; j++) { val1 = GET_DATA_BYTE(lines1[i], j); count1 += val1; val1 += 0xbbbbbb00; SET_DATA_BYTE(linet1[i], j, val1); } } count2 = 0; for (i = 0; i < h; i++) { line1 = data1 + i * wpl; line2 = data2 + i * wpl; for (j = 0; j < w8; j++) { val2 = l_getDataByte(line1, j); count2 += val2; val2 += 0xbbbbbb00; l_setDataByte(line2, j, val2); } } CompareResults(pixs, pix1, pix2, count1, count2, "8 bpp", rp); /* ------------------------------------------------- */ /* Test different methods for 16 bpp */ /* ------------------------------------------------- */ count1 = 0; w16 = w / 16; for (i = 0; i < h; i++) { for (j = 0; j < w16; j++) { val1 = GET_DATA_TWO_BYTES(lines1[i], j); count1 += val1; val1 += 0xbbbb0000; SET_DATA_TWO_BYTES(linet1[i], j, val1); } } count2 = 0; for (i = 0; i < h; i++) { line1 = data1 + i * wpl; line2 = data2 + i * wpl; for (j = 0; j < w16; j++) { val2 = l_getDataTwoBytes(line1, j); count2 += val2; val2 += 0xbbbb0000; l_setDataTwoBytes(line2, j, val2); } } CompareResults(pixs, pix1, pix2, count1, count2, "16 bpp", rp); /* ------------------------------------------------- */ /* Test different methods for 32 bpp */ /* ------------------------------------------------- */ count1 = 0; w32 = w / 32; for (i = 0; i < h; i++) { for (j = 0; j < w32; j++) { val1 = GET_DATA_FOUR_BYTES(lines1[i], j); count1 += val1 & 0xfff; SET_DATA_FOUR_BYTES(linet1[i], j, val1); } } count2 = 0; for (i = 0; i < h; i++) { line1 = data1 + i * wpl; line2 = data2 + i * wpl; for (j = 0; j < w32; j++) { val2 = l_getDataFourBytes(line1, j); count2 += val2 & 0xfff; l_setDataFourBytes(line2, j, val2); } } CompareResults(pixs, pix1, pix2, count1, count2, "32 bpp", rp); pixDestroy(&pixs); pixDestroy(&pix1); pixDestroy(&pix2); lept_free(lines1); lept_free(linet1); lept_free(linet2); return regTestCleanup(rp); }
/*! * 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; }