void ImagingResampleHorizontal_32bpc(Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk) { ImagingSectionCookie cookie; double ss; int xx, yy, x, xmin, xmax; double *k; ImagingSectionEnter(&cookie); switch(imIn->type) { case IMAGING_TYPE_INT32: for (yy = 0; yy < imOut->ysize; yy++) { for (xx = 0; xx < imOut->xsize; xx++) { xmin = bounds[xx * 2 + 0]; xmax = bounds[xx * 2 + 1]; k = &kk[xx * ksize]; ss = 0.0; for (x = 0; x < xmax; x++) ss += IMAGING_PIXEL_I(imIn, x + xmin, yy + offset) * k[x]; IMAGING_PIXEL_I(imOut, xx, yy) = ROUND_UP(ss); } } break; case IMAGING_TYPE_FLOAT32: for (yy = 0; yy < imOut->ysize; yy++) { for (xx = 0; xx < imOut->xsize; xx++) { xmin = bounds[xx * 2 + 0]; xmax = bounds[xx * 2 + 1]; k = &kk[xx * ksize]; ss = 0.0; for (x = 0; x < xmax; x++) ss += IMAGING_PIXEL_F(imIn, x + xmin, yy + offset) * k[x]; IMAGING_PIXEL_F(imOut, xx, yy) = ss; } } break; } ImagingSectionLeave(&cookie); }
void ImagingResampleVertical_32bpc(Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk) { ImagingSectionCookie cookie; double ss; int xx, yy, y, ymin, ymax; double *k; ImagingSectionEnter(&cookie); switch(imIn->type) { case IMAGING_TYPE_INT32: for (yy = 0; yy < imOut->ysize; yy++) { ymin = bounds[yy * 2 + 0]; ymax = bounds[yy * 2 + 1]; k = &kk[yy * ksize]; for (xx = 0; xx < imOut->xsize; xx++) { ss = 0.0; for (y = 0; y < ymax; y++) ss += IMAGING_PIXEL_I(imIn, xx, y + ymin) * k[y]; IMAGING_PIXEL_I(imOut, xx, yy) = ROUND_UP(ss); } } break; case IMAGING_TYPE_FLOAT32: for (yy = 0; yy < imOut->ysize; yy++) { ymin = bounds[yy * 2 + 0]; ymax = bounds[yy * 2 + 1]; k = &kk[yy * ksize]; for (xx = 0; xx < imOut->xsize; xx++) { ss = 0.0; for (y = 0; y < ymax; y++) ss += IMAGING_PIXEL_F(imIn, xx, y + ymin) * k[y]; IMAGING_PIXEL_F(imOut, xx, yy) = ss; } } break; } ImagingSectionLeave(&cookie); }
Imaging ImagingStretch(Imaging imOut, Imaging imIn, int filter) { /* FIXME: this is a quick and straightforward translation from a python prototype. might need some further C-ification... */ ImagingSectionCookie cookie; struct filter *filterp; float support, scale, filterscale; float center, ww, ss, ymin, ymax, xmin, xmax; int xx, yy, x, y, b; float *k; /* check modes */ if (!imOut || !imIn || strcmp(imIn->mode, imOut->mode) != 0) return (Imaging) ImagingError_ModeError(); /* check filter */ switch (filter) { case IMAGING_TRANSFORM_NEAREST: filterp = &NEAREST; break; case IMAGING_TRANSFORM_ANTIALIAS: filterp = &ANTIALIAS; break; case IMAGING_TRANSFORM_BILINEAR: filterp = &BILINEAR; break; case IMAGING_TRANSFORM_BICUBIC: filterp = &BICUBIC; break; default: return (Imaging) ImagingError_ValueError( "unsupported resampling filter" ); } if (imIn->ysize == imOut->ysize) { /* prepare for horizontal stretch */ filterscale = scale = (float) imIn->xsize / imOut->xsize; } else if (imIn->xsize == imOut->xsize) { /* prepare for vertical stretch */ filterscale = scale = (float) imIn->ysize / imOut->ysize; } else return (Imaging) ImagingError_Mismatch(); /* determine support size (length of resampling filter) */ support = filterp->support; if (filterscale < 1.0) { filterscale = 1.0; support = 0.5; } support = support * filterscale; /* coefficient buffer (with rounding safety margin) */ k = malloc(((int) support * 2 + 10) * sizeof(float)); if (!k) return (Imaging) ImagingError_MemoryError(); ImagingSectionEnter(&cookie); if (imIn->xsize == imOut->xsize) { /* vertical stretch */ for (yy = 0; yy < imOut->ysize; yy++) { center = (yy + 0.5) * scale; ww = 0.0; ss = 1.0 / filterscale; /* calculate filter weights */ ymin = floor(center - support); if (ymin < 0.0) ymin = 0.0; ymax = ceil(center + support); if (ymax > (float) imIn->ysize) ymax = (float) imIn->ysize; for (y = (int) ymin; y < (int) ymax; y++) { float w = filterp->filter((y - center + 0.5) * ss) * ss; k[y - (int) ymin] = w; ww = ww + w; } if (ww == 0.0) ww = 1.0; else ww = 1.0 / ww; if (imIn->image8) { /* 8-bit grayscale */ for (xx = 0; xx < imOut->xsize; xx++) { ss = 0.0; for (y = (int) ymin; y < (int) ymax; y++) ss = ss + imIn->image8[y][xx] * k[y - (int) ymin]; ss = ss * ww + 0.5; if (ss < 0.5) imOut->image8[yy][xx] = 0; else if (ss >= 255.0) imOut->image8[yy][xx] = 255; else imOut->image8[yy][xx] = (UINT8) ss; } } else switch(imIn->type) { case IMAGING_TYPE_UINT8: /* n-bit grayscale */ for (xx = 0; xx < imOut->xsize*4; xx++) { /* FIXME: skip over unused pixels */ ss = 0.0; for (y = (int) ymin; y < (int) ymax; y++) ss = ss + (UINT8) imIn->image[y][xx] * k[y-(int) ymin]; ss = ss * ww + 0.5; if (ss < 0.5) imOut->image[yy][xx] = (UINT8) 0; else if (ss >= 255.0) imOut->image[yy][xx] = (UINT8) 255; else imOut->image[yy][xx] = (UINT8) ss; } break; case IMAGING_TYPE_INT32: /* 32-bit integer */ for (xx = 0; xx < imOut->xsize; xx++) { ss = 0.0; for (y = (int) ymin; y < (int) ymax; y++) ss = ss + IMAGING_PIXEL_I(imIn, xx, y) * k[y - (int) ymin]; IMAGING_PIXEL_I(imOut, xx, yy) = (int) ss * ww; } break; case IMAGING_TYPE_FLOAT32: /* 32-bit float */ for (xx = 0; xx < imOut->xsize; xx++) { ss = 0.0; for (y = (int) ymin; y < (int) ymax; y++) ss = ss + IMAGING_PIXEL_F(imIn, xx, y) * k[y - (int) ymin]; IMAGING_PIXEL_F(imOut, xx, yy) = ss * ww; } break; default: ImagingSectionLeave(&cookie); return (Imaging) ImagingError_ModeError(); } } } else { /* horizontal stretch */ for (xx = 0; xx < imOut->xsize; xx++) { center = (xx + 0.5) * scale; ww = 0.0; ss = 1.0 / filterscale; xmin = floor(center - support); if (xmin < 0.0) xmin = 0.0; xmax = ceil(center + support); if (xmax > (float) imIn->xsize) xmax = (float) imIn->xsize; for (x = (int) xmin; x < (int) xmax; x++) { float w = filterp->filter((x - center + 0.5) * ss) * ss; k[x - (int) xmin] = w; ww = ww + w; } if (ww == 0.0) ww = 1.0; else ww = 1.0 / ww; if (imIn->image8) { /* 8-bit grayscale */ for (yy = 0; yy < imOut->ysize; yy++) { ss = 0.0; for (x = (int) xmin; x < (int) xmax; x++) ss = ss + imIn->image8[yy][x] * k[x - (int) xmin]; ss = ss * ww + 0.5; if (ss < 0.5) imOut->image8[yy][xx] = (UINT8) 0; else if (ss >= 255.0) imOut->image8[yy][xx] = (UINT8) 255; else imOut->image8[yy][xx] = (UINT8) ss; } } else switch(imIn->type) { case IMAGING_TYPE_UINT8: /* n-bit grayscale */ for (yy = 0; yy < imOut->ysize; yy++) { for (b = 0; b < imIn->bands; b++) { if (imIn->bands == 2 && b) b = 3; /* hack to deal with LA images */ ss = 0.0; for (x = (int) xmin; x < (int) xmax; x++) ss = ss + (UINT8) imIn->image[yy][x*4+b] * k[x - (int) xmin]; ss = ss * ww + 0.5; if (ss < 0.5) imOut->image[yy][xx*4+b] = (UINT8) 0; else if (ss >= 255.0) imOut->image[yy][xx*4+b] = (UINT8) 255; else imOut->image[yy][xx*4+b] = (UINT8) ss; } } break; case IMAGING_TYPE_INT32: /* 32-bit integer */ for (yy = 0; yy < imOut->ysize; yy++) { ss = 0.0; for (x = (int) xmin; x < (int) xmax; x++) ss = ss + IMAGING_PIXEL_I(imIn, x, yy) * k[x - (int) xmin]; IMAGING_PIXEL_I(imOut, xx, yy) = (int) ss * ww; } break; case IMAGING_TYPE_FLOAT32: /* 32-bit float */ for (yy = 0; yy < imOut->ysize; yy++) { ss = 0.0; for (x = (int) xmin; x < (int) xmax; x++) ss = ss + IMAGING_PIXEL_F(imIn, x, yy) * k[x - (int) xmin]; IMAGING_PIXEL_F(imOut, xx, yy) = ss * ww; } break; default: ImagingSectionLeave(&cookie); return (Imaging) ImagingError_ModeError(); } } } ImagingSectionLeave(&cookie); free(k); return imOut; }