Imaging ImagingRankFilter(Imaging im, int size, int rank) { Imaging imOut = NULL; int x, y; int i, margin, size2; if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL) return (Imaging) ImagingError_ModeError(); if (!(size & 1)) return (Imaging) ImagingError_ValueError("bad filter size"); size2 = size * size; margin = (size-1) / 2; if (rank < 0 || rank >= size2) return (Imaging) ImagingError_ValueError("bad rank value"); imOut = ImagingNew(im->mode, im->xsize - 2*margin, im->ysize - 2*margin); if (!imOut) return NULL; #define RANK_BODY(type) do {\ type* buf = malloc(size2 * sizeof(type));\ if (!buf)\ goto nomemory;\ for (y = 0; y < imOut->ysize; y++)\ for (x = 0; x < imOut->xsize; x++) {\ for (i = 0; i < size; i++)\ memcpy(buf + i*size, &IMAGING_PIXEL_##type(im, x, y+i),\ size * sizeof(type));\ IMAGING_PIXEL_##type(imOut, x, y) = Rank##type(buf, size2, rank);\ }\ } while (0) if (im->image8) RANK_BODY(UINT8); else if (im->type == IMAGING_TYPE_INT32) RANK_BODY(INT32); else if (im->type == IMAGING_TYPE_FLOAT32) RANK_BODY(FLOAT32); else { /* safety net (we shouldn't end up here) */ ImagingDelete(imOut); return (Imaging) ImagingError_ModeError(); } ImagingCopyInfo(imOut, im); return imOut; nomemory: ImagingDelete(imOut); return (Imaging) ImagingError_MemoryError(); }
Imaging ImagingNewInternal(const char* mode, int xsize, int ysize, int dirty) { Imaging im; if (xsize < 0 || ysize < 0) { return (Imaging) ImagingError_ValueError("bad image size"); } im = ImagingNewPrologue(mode, xsize, ysize); if ( ! im) return NULL; if (ImagingAllocateArray(im, dirty, ImagingDefaultArena.block_size)) { return im; } ImagingError_Clear(); // Try to allocate the image once more with smallest possible block size if (ImagingAllocateArray(im, dirty, IMAGING_PAGE_SIZE)) { return im; } ImagingDelete(im); return NULL; }
Imaging ImagingNewBlock(const char* mode, int xsize, int ysize) { Imaging im; if (xsize < 0 || ysize < 0) { return (Imaging) ImagingError_ValueError("bad image size"); } im = ImagingNewPrologue(mode, xsize, ysize); if ( ! im) return NULL; if (ImagingAllocateBlock(im)) { return im; } ImagingDelete(im); return NULL; }
Imaging ImagingCrop(Imaging imIn, int sx0, int sy0, int sx1, int sy1) { Imaging imOut; int xsize, ysize; int dx0, dy0, dx1, dy1; INT32 zero = 0; if (!imIn) return (Imaging) ImagingError_ModeError(); xsize = sx1 - sx0; if (xsize < 0) xsize = 0; ysize = sy1 - sy0; if (ysize < 0) ysize = 0; imOut = ImagingNew(imIn->mode, xsize, ysize); if (!imOut) return NULL; ImagingCopyInfo(imOut, imIn); if (sx0 < 0 || sy0 < 0 || sx1 > imIn->xsize || sy1 > imIn->ysize) (void) ImagingFill(imOut, &zero); dx0 = -sx0; dy0 = -sy0; dx1 = imIn->xsize - sx0; dy1 = imIn->ysize - sy0; /* paste the source image on top of the output image!!! */ if (ImagingPaste(imOut, imIn, NULL, dx0, dy0, dx1, dy1) < 0) { ImagingDelete(imOut); return NULL; } return imOut; }
Imaging ImagingResampleInner(Imaging imIn, int xsize, int ysize, struct filter *filterp, float box[4], ResampleFunction ResampleHorizontal, ResampleFunction ResampleVertical) { Imaging imTemp = NULL; Imaging imOut = NULL; int i, need_horizontal, need_vertical; int ybox_first, ybox_last; int ksize_horiz, ksize_vert; int *bounds_horiz, *bounds_vert; double *kk_horiz, *kk_vert; need_horizontal = xsize != imIn->xsize || box[0] || box[2] != xsize; need_vertical = ysize != imIn->ysize || box[1] || box[3] != ysize; ksize_horiz = precompute_coeffs(imIn->xsize, box[0], box[2], xsize, filterp, &bounds_horiz, &kk_horiz); if ( ! ksize_horiz) { return NULL; } ksize_vert = precompute_coeffs(imIn->ysize, box[1], box[3], ysize, filterp, &bounds_vert, &kk_vert); if ( ! ksize_vert) { free(bounds_horiz); free(kk_horiz); return NULL; } // First used row in the source image ybox_first = bounds_vert[0]; // Last used row in the source image ybox_last = bounds_vert[ysize*2 - 2] + bounds_vert[ysize*2 - 1]; /* two-pass resize, horizontal pass */ if (need_horizontal) { // Shift bounds for vertical pass for (i = 0; i < ysize; i++) { bounds_vert[i * 2] -= ybox_first; } imTemp = ImagingNewDirty(imIn->mode, xsize, ybox_last - ybox_first); if (imTemp) { ResampleHorizontal(imTemp, imIn, ybox_first, ksize_horiz, bounds_horiz, kk_horiz); } free(bounds_horiz); free(kk_horiz); if ( ! imTemp) { free(bounds_vert); free(kk_vert); return NULL; } imOut = imIn = imTemp; } else { // Free in any case free(bounds_horiz); free(kk_horiz); } /* vertical pass */ if (need_vertical) { imOut = ImagingNewDirty(imIn->mode, imIn->xsize, ysize); if (imOut) { /* imIn can be the original image or horizontally resampled one */ ResampleVertical(imOut, imIn, 0, ksize_vert, bounds_vert, kk_vert); } /* it's safe to call ImagingDelete with empty value if previous step was not performed. */ ImagingDelete(imTemp); free(bounds_vert); free(kk_vert); if ( ! imOut) { return NULL; } } else { // Free in any case free(bounds_vert); free(kk_vert); } /* none of the previous steps are performed, copying */ if ( ! imOut) { imOut = ImagingCopy(imIn); } return imOut; }
Imaging ImagingPointTransform(Imaging imIn, double scale, double offset) { /* scale/offset transform */ ImagingSectionCookie cookie; Imaging imOut; int x, y; if (!imIn || (strcmp(imIn->mode, "I") != 0 && strcmp(imIn->mode, "I;16") != 0 && strcmp(imIn->mode, "F") != 0)) return (Imaging) ImagingError_ModeError(); imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize); if (!imOut) return NULL; ImagingCopyInfo(imOut, imIn); switch (imIn->type) { case IMAGING_TYPE_INT32: ImagingSectionEnter(&cookie); for (y = 0; y < imIn->ysize; y++) { INT32* in = imIn->image32[y]; INT32* out = imOut->image32[y]; /* FIXME: add clipping? */ for (x = 0; x < imIn->xsize; x++) out[x] = in[x] * scale + offset; } ImagingSectionLeave(&cookie); break; case IMAGING_TYPE_FLOAT32: ImagingSectionEnter(&cookie); for (y = 0; y < imIn->ysize; y++) { FLOAT32* in = (FLOAT32*) imIn->image32[y]; FLOAT32* out = (FLOAT32*) imOut->image32[y]; for (x = 0; x < imIn->xsize; x++) out[x] = in[x] * scale + offset; } ImagingSectionLeave(&cookie); break; case IMAGING_TYPE_SPECIAL: if (strcmp(imIn->mode,"I;16") == 0) { ImagingSectionEnter(&cookie); for (y = 0; y < imIn->ysize; y++) { UINT16* in = (UINT16 *)imIn->image[y]; UINT16* out = (UINT16 *)imOut->image[y]; /* FIXME: add clipping? */ for (x = 0; x < imIn->xsize; x++) out[x] = in[x] * scale + offset; } ImagingSectionLeave(&cookie); break; } /* FALL THROUGH */ default: ImagingDelete(imOut); return (Imaging) ImagingError_ValueError("internal error"); } return imOut; }