mlib_status mlib_ImageAffine_alltypes(mlib_image *dst, const mlib_image *src, const mlib_d64 *mtx, mlib_filter filter, mlib_edge edge, const void *colormap) { mlib_affine_param param[1]; mlib_status res; mlib_type type; mlib_s32 nchan, t_ind, kw, kw1; mlib_addr align; mlib_d64 buff_lcl[BUFF_SIZE / 8]; mlib_u8 **lineAddr = NULL; /* check for obvious errors */ MLIB_IMAGE_TYPE_EQUAL(src, dst); MLIB_IMAGE_CHAN_EQUAL(src, dst); type = mlib_ImageGetType(dst); nchan = mlib_ImageGetChannels(dst); switch (filter) { case MLIB_NEAREST: kw = 1; kw1 = 0; break; case MLIB_BILINEAR: kw = 2; kw1 = 0; break; case MLIB_BICUBIC: case MLIB_BICUBIC2: kw = 4; kw1 = 1; break; default: return MLIB_FAILURE; } STORE_PARAM(param, lineAddr); STORE_PARAM(param, filter); res = mlib_AffineEdges(param, dst, src, buff_lcl, BUFF_SIZE, kw, kw, kw1, kw1, edge, mtx, MLIB_SHIFT, MLIB_SHIFT); if (res != MLIB_SUCCESS) return res; lineAddr = param->lineAddr; if (type == MLIB_BYTE) t_ind = 0; else if (type == MLIB_SHORT) t_ind = 1; else if (type == MLIB_INT) t_ind = 2; else if (type == MLIB_USHORT) t_ind = 3; else if (type == MLIB_FLOAT) t_ind = 4; else if (type == MLIB_DOUBLE) t_ind = 5; if (colormap != NULL && filter != MLIB_NEAREST) { if (t_ind != 0 && t_ind != 1) return MLIB_FAILURE; if (mlib_ImageGetLutType(colormap) == MLIB_SHORT) t_ind += 2; t_ind = 2 * t_ind; if (mlib_ImageGetLutChannels(colormap) == 4) t_ind++; } if (type == MLIB_BIT) { mlib_s32 s_bitoff = mlib_ImageGetBitOffset(src); mlib_s32 d_bitoff = mlib_ImageGetBitOffset(dst); if (nchan != 1 || filter != MLIB_NEAREST) return MLIB_FAILURE; mlib_ImageAffine_bit_1ch_nn(param, s_bitoff, d_bitoff); } else { switch (filter) { case MLIB_NEAREST: if (t_ind >= 3) t_ind -= 2; /* correct types USHORT, FLOAT, DOUBLE; new values: 1, 2, 3 */ /* two channels as one channel of next type */ align = (mlib_addr) (param->dstData) | (mlib_addr) lineAddr[0]; align |= param->dstYStride | param->srcYStride; while (((nchan | (align >> t_ind)) & 1) == 0 && t_ind < MAX_T_IND) { nchan >>= 1; t_ind++; } res = mlib_AffineFunArr_nn[4 * t_ind + (nchan - 1)] (param); break; case MLIB_BILINEAR: if (colormap != NULL) { res = mlib_AffineFunArr_bl_i[t_ind] (param, colormap); } else { res = mlib_AffineFunArr_bl[4 * t_ind + (nchan - 1)] (param); } break; case MLIB_BICUBIC: case MLIB_BICUBIC2: if (colormap != NULL) { res = mlib_AffineFunArr_bc_i[t_ind] (param, colormap); } else { res = mlib_AffineFunArr_bc[4 * t_ind + (nchan - 1)] (param); } break; } if (res != MLIB_SUCCESS) { if (param->buff_malloc != NULL) mlib_free(param->buff_malloc); return res; } } if (edge == MLIB_EDGE_SRC_PADDED) edge = MLIB_EDGE_DST_NO_WRITE; if (filter != MLIB_NEAREST && edge != MLIB_EDGE_DST_NO_WRITE) { mlib_affine_param param_e[1]; mlib_d64 buff_lcl1[BUFF_SIZE / 8]; STORE_PARAM(param_e, lineAddr); STORE_PARAM(param_e, filter); res = mlib_AffineEdges(param_e, dst, src, buff_lcl1, BUFF_SIZE, kw, kw, kw1, kw1, -1, mtx, MLIB_SHIFT, MLIB_SHIFT); if (res != MLIB_SUCCESS) { if (param->buff_malloc != NULL) mlib_free(param->buff_malloc); return res; } switch (edge) { case MLIB_EDGE_DST_FILL_ZERO: mlib_ImageAffineEdgeZero(param, param_e, colormap); break; case MLIB_EDGE_OP_NEAREST: mlib_ImageAffineEdgeNearest(param, param_e); break; case MLIB_EDGE_SRC_EXTEND: if (filter == MLIB_BILINEAR) { res = mlib_ImageAffineEdgeExtend_BL(param, param_e, colormap); } else { res = mlib_ImageAffineEdgeExtend_BC(param, param_e, colormap); } break; } if (param_e->buff_malloc != NULL) mlib_free(param_e->buff_malloc); } if (param->buff_malloc != NULL) mlib_free(param->buff_malloc); return res; }
mlib_status __mlib_ImageZoomTranslateTableBlend( mlib_image *dst, const mlib_image *src, mlib_d64 zoomx, mlib_d64 zoomy, mlib_d64 tx, mlib_d64 ty, const void *table, mlib_edge edge, mlib_blend blend, mlib_s32 cmask) { mlib_affine_param param[1]; mlib_affine_param *cur_param; mlib_zoom_workspace ws[1]; mlib_d64 buff_lcl[BUFF_SIZE / 8]; mlib_type type; mlib_u8 *srcData, *dstData; mlib_s32 srcWidth, dstWidth, srcHeight, dstHeight; mlib_s32 srcStride, dstStride, schan, dchan; mlib_s32 *leftEdges, *rightEdges, *xStarts, *yStarts; mlib_s32 *p_x_ind = NULL, *x_ind, *x_tab = NULL, xpos; mlib_u8 **lineAddr = NULL; mlib_s32 kw, kh, kw1, kh1; mlib_status res = MLIB_SUCCESS; fun_type_nw fun_nw = NULL; mlib_interp_table *tbl = (mlib_interp_table *) table; mlib_d64 mtx[6], dxs, tmp_dxs, div; mlib_s32 i, x_shift, y_shift; mlib_s32 affine = 0, yStart; mlib_s32 xLeft_e, xRight_e, xLeft, xRight, dx; mtx[0] = zoomx; mtx[1] = 0; mtx[2] = tx; mtx[3] = 0; mtx[4] = zoomy; mtx[5] = ty; ws->zoomx = zoomx; ws->zoomy = zoomy; /* check for obvious errors */ MLIB_IMAGE_CHECK(src); MLIB_IMAGE_CHECK(dst); MLIB_IMAGE_TYPE_EQUAL(src, dst); MLIB_IMAGE_HAVE_TYPE(src, MLIB_BYTE); if (zoomx <= 0 || zoomy <= 0) return (MLIB_OUTOFRANGE); if (mlib_ImageGetWidth(src) >= (1 << 15) || mlib_ImageGetHeight(src) >= (1 << 15)) { return (MLIB_FAILURE); } MLIB_IMAGE_GET_ALL_PARAMS(src, type, schan, srcWidth, srcHeight, srcStride, srcData); MLIB_IMAGE_GET_ALL_PARAMS(dst, type, dchan, dstWidth, dstHeight, dstStride, dstData); if ((schan == 4 || dchan == 4) && cmask != 1 && cmask != 8) return (MLIB_OUTOFRANGE); if (schan < 3 || schan > 4 || dchan < 3 || dchan > 4) { return (MLIB_FAILURE); } if ((blend == MLIB_BLEND_GTK_SRC) && (schan == 3) && (dchan == 3)) return __mlib_ImageZoomTranslateTable(dst, src, zoomx, zoomy, tx, ty, table, edge); kw = tbl->width; kh = tbl->height; kw1 = tbl->leftPadding; kh1 = tbl->topPadding; x_shift = INT_BITS - mlib_ilogb(srcWidth + kw); y_shift = INT_BITS - mlib_ilogb(srcHeight + kh); ws->type = type; ws->srcData = srcData; ws->dstData = dstData; ws->srcWidth = srcWidth; ws->srcHeight = srcHeight; ws->srcStride = srcStride; ws->dstStride = dstStride; ws->nchan = schan; ws->dchan = dchan; ws->blend = blend; ws->alpha_shift = 1; ws->edge = edge; ws->x_shift = x_shift; ws->y_shift = y_shift; ws->x_move = (kw1 << x_shift); ws->y_move = (kh1 << y_shift); if (cmask == 1) ws->alpha_shift = -3; /* VIS version of non NULL */ fun_nw = mlib_ImageZoomTranslate_GetFunc(ws, table); if (fun_nw == NULL) { fun_nw = mlib_ImageZoomTranslateTableBlend_8nw; } /* NULL */ STORE_PARAM(param, affine); STORE_PARAM(param, lineAddr); param->buff_malloc = NULL; /* process internal pixels */ res = mlib_AffineEdges(param, dst, src, buff_lcl, BUFF_SIZE, kw, kh, kw1, kh1, edge, mtx, x_shift, y_shift); if (res != MLIB_SUCCESS) return (res); ws->yStart = param->yStart; ws->yFinish = param->yFinish; ws->max_xsize = param->max_xsize; ws->dx = param->dX; ws->dy = param->dY; LOAD_PARAM(param, lineAddr); LOAD_PARAM(param, leftEdges); LOAD_PARAM(param, rightEdges); LOAD_PARAM(param, xStarts); LOAD_PARAM(param, yStarts); if (edge == MLIB_EDGE_SRC_EXTEND) ws->y_move += (1 << (y_shift - 1)); if ((ws->max_xsize) > 0) { /* RTC */ yStarts[(ws->yFinish) + 1] = 0; res = fun_nw(param->dstData, lineAddr, leftEdges, rightEdges, xStarts, yStarts, ws, tbl); if (res != MLIB_SUCCESS) { if (param->buff_malloc != NULL) __mlib_free(param->buff_malloc); return (res); } } /* process edge pixels */ if (edge != MLIB_EDGE_DST_NO_WRITE && edge != MLIB_EDGE_SRC_PADDED) { mlib_affine_param param_e[1]; param_e->buff_malloc = NULL; if (edge == MLIB_EDGE_DST_FILL_ZERO || edge == MLIB_EDGE_OP_NEAREST) { x_shift = 16; y_shift = 16; } STORE_PARAM(param_e, lineAddr); if (edge != MLIB_EDGE_SRC_EXTEND_INDEF) { res = mlib_AffineEdges(param_e, dst, src, NULL, 0, kw, kh, kw1, kh1, -1, mtx, x_shift, y_shift); } if (res == MLIB_SUCCESS) switch (edge) { case MLIB_EDGE_DST_FILL_ZERO: mlib_ImageZoomTranslateTableBlendEdgeZero (param, param_e, dchan, schan, ws->alpha_shift, blend); break; case MLIB_EDGE_OP_NEAREST: mlib_ImageZoomTranslateTableBlendEdgeNearest (param, param_e, dchan, schan, ws->alpha_shift, blend); break; case MLIB_EDGE_SRC_EXTEND: case MLIB_EDGE_SRC_EXTEND_INDEF: ws->x_shift = x_shift; ws->x_move += (1 << (x_shift - 1)); if (edge == MLIB_EDGE_SRC_EXTEND) { ws->yStart = param_e->yStart; ws->yFinish = param_e->yFinish; yStart = ws->yStart; ws->dx = param_e->dX; xLeft_e = param_e->leftEdges[yStart]; xRight_e = param_e->rightEdges[yStart]; cur_param = param_e; } else { cur_param = param; ws->yStart = param->yStart; yStart = ws->yStart; xLeft_e = 0; xRight_e = dstWidth - 1; } xLeft = param->leftEdges[param->yStart]; xRight = param->rightEdges[param->yStart]; if ((xLeft > xRight) || (param->yStart > param->yFinish)) { xLeft = xRight_e + 1; xRight = xRight_e; } if (((xRight_e - xLeft_e + 1) > 0) && (ws->yStart <= ws->yFinish)) { CREATE_X_IND(); LOAD_PARAM(cur_param, lineAddr); LOAD_PARAM(cur_param, leftEdges); LOAD_PARAM(cur_param, xStarts); LOAD_PARAM(cur_param, yStarts); /* RTC */ yStarts[(ws->yFinish) + 1] = 0; if (edge == MLIB_EDGE_SRC_EXTEND) { CREATE_X_EXT() } ws->max_xsize = xLeft - xLeft_e; if ((ws->max_xsize) > 0) { if (edge != MLIB_EDGE_SRC_EXTEND) { CREATE_X(xLeft_e, xLeft - 1); } leftEdges[0] = ws->max_xsize; leftEdges[1] = xLeft_e; res = FUNCNAME_EXT (cur_param->dstData, lineAddr, x_ind, leftEdges, x_tab, xStarts, yStarts, ws, tbl); } ws->max_xsize = xRight_e - xRight; if ((ws->max_xsize) > 0) { mlib_s32 shift = 0; if (edge != MLIB_EDGE_SRC_EXTEND) { CREATE_X(xRight + 1, xRight_e); } else { shift = xRight + 1 - xLeft_e; } leftEdges[0] = ws->max_xsize; leftEdges[1] = xRight + 1; res = FUNCNAME_EXT (cur_param->dstData, lineAddr, x_ind, leftEdges, x_tab + shift, xStarts, yStarts, ws, tbl); } __mlib_free(p_x_ind); if (x_tab != NULL) __mlib_free(x_tab); } break; default: res = MLIB_FAILURE; break; }