Imaging ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha) { Imaging imOut; int x, y; /* Check arguments */ if (!imIn1 || !imIn2 || imIn1->type != IMAGING_TYPE_UINT8) return ImagingError_ModeError(); if (imIn1->type != imIn2->type || imIn1->bands != imIn2->bands || imIn1->xsize != imIn2->xsize || imIn1->ysize != imIn2->ysize) return ImagingError_Mismatch(); /* Shortcuts */ if (alpha == 0.0) return ImagingCopy(imIn1); else if (alpha == 1.0) return ImagingCopy(imIn2); imOut = ImagingNew(imIn1->mode, imIn1->xsize, imIn1->ysize); if (!imOut) return NULL; ImagingCopyInfo(imOut, imIn1); if (alpha >= 0 && alpha <= 1.0) { /* Interpolate between bands */ for (y = 0; y < imIn1->ysize; y++) { UINT8* in1 = (UINT8*) imIn1->image[y]; UINT8* in2 = (UINT8*) imIn2->image[y]; UINT8* out = (UINT8*) imOut->image[y]; for (x = 0; x < imIn1->linesize; x++) out[x] = (UINT8) ((int) in1[x] + alpha * ((int) in2[x] - (int) in1[x])); } } else { /* Extrapolation; must make sure to clip resulting values */ for (y = 0; y < imIn1->ysize; y++) { UINT8* in1 = (UINT8*) imIn1->image[y]; UINT8* in2 = (UINT8*) imIn2->image[y]; UINT8* out = (UINT8*) imOut->image[y]; for (x = 0; x < imIn1->linesize; x++) { float temp = ((int) in1[x] + alpha * ((int) in2[x] - (int) in1[x])); if (temp <= 0.0) out[x] = 0; else if (temp >= 255.0) out[x] = 255; else out[x] = (UINT8) temp; } } } return imOut; }
Imaging ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel, FLOAT32 offset) { Imaging imOut; ImagingSectionCookie cookie; if ( ! im || im->type != IMAGING_TYPE_UINT8) return (Imaging) ImagingError_ModeError(); if (im->xsize < xsize || im->ysize < ysize) return ImagingCopy(im); if ((xsize != 3 && xsize != 5) || xsize != ysize) return (Imaging) ImagingError_ValueError("bad kernel size"); imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); if (!imOut) return NULL; ImagingSectionEnter(&cookie); if (xsize == 3) { /* 3x3 kernel. */ ImagingFilter3x3(imOut, im, kernel, offset); } else { /* 5x5 kernel. */ ImagingFilter5x5(imOut, im, kernel, offset); } ImagingSectionLeave(&cookie); return imOut; }
Imaging ImagingGetBand(Imaging imIn, int band) { Imaging imOut; int x, y; /* Check arguments */ if (!imIn || imIn->type != IMAGING_TYPE_UINT8) return (Imaging) ImagingError_ModeError(); if (band < 0 || band >= imIn->bands) return (Imaging) ImagingError_ValueError("band index out of range"); /* Shortcuts */ if (imIn->bands == 1) return ImagingCopy(imIn); /* Special case for LXXA etc */ if (imIn->bands == 2 && band == 1) band = 3; imOut = ImagingNew("L", imIn->xsize, imIn->ysize); if (!imOut) return NULL; /* Extract band from image */ for (y = 0; y < imIn->ysize; y++) { UINT8* in = (UINT8*) imIn->image[y] + band; UINT8* out = imOut->image8[y]; for (x = 0; x < imIn->xsize; x++) { out[x] = *in; in += 4; } } 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 ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel, FLOAT32 offset, FLOAT32 divisor) { Imaging imOut; int x, y; FLOAT32 sum; if (!im || strcmp(im->mode, "L") != 0) return (Imaging) ImagingError_ModeError(); if (im->xsize < xsize || im->ysize < ysize) return ImagingCopy(im); if ((xsize != 3 && xsize != 5) || xsize != ysize) return (Imaging) ImagingError_ValueError("bad kernel size"); imOut = ImagingNew(im->mode, im->xsize, im->ysize); if (!imOut) return NULL; /* brute force kernel implementations */ #define KERNEL3x3(image, kernel, d) ( \ (int) image[y+1][x-d] * kernel[0] + \ (int) image[y+1][x] * kernel[1] + \ (int) image[y+1][x+d] * kernel[2] + \ (int) image[y][x-d] * kernel[3] + \ (int) image[y][x] * kernel[4] + \ (int) image[y][x+d] * kernel[5] + \ (int) image[y-1][x-d] * kernel[6] + \ (int) image[y-1][x] * kernel[7] + \ (int) image[y-1][x+d] * kernel[8]) #define KERNEL5x5(image, kernel, d) ( \ (int) image[y+2][x-d-d] * kernel[0] + \ (int) image[y+2][x-d] * kernel[1] + \ (int) image[y+2][x] * kernel[2] + \ (int) image[y+2][x+d] * kernel[3] + \ (int) image[y+2][x+d+d] * kernel[4] + \ (int) image[y+1][x-d-d] * kernel[5] + \ (int) image[y+1][x-d] * kernel[6] + \ (int) image[y+1][x] * kernel[7] + \ (int) image[y+1][x+d] * kernel[8] + \ (int) image[y+1][x+d+d] * kernel[9] + \ (int) image[y][x-d-d] * kernel[10] + \ (int) image[y][x-d] * kernel[11] + \ (int) image[y][x] * kernel[12] + \ (int) image[y][x+d] * kernel[13] + \ (int) image[y][x+d+d] * kernel[14] + \ (int) image[y-1][x-d-d] * kernel[15] + \ (int) image[y-1][x-d] * kernel[16] + \ (int) image[y-1][x] * kernel[17] + \ (int) image[y-1][x+d] * kernel[18] + \ (int) image[y-1][x+d+d] * kernel[19] + \ (int) image[y-2][x-d-d] * kernel[20] + \ (int) image[y-2][x-d] * kernel[21] + \ (int) image[y-2][x] * kernel[22] + \ (int) image[y-2][x+d] * kernel[23] + \ (int) image[y-2][x+d+d] * kernel[24]) if (xsize == 3) { /* 3x3 kernel. */ for (x = 0; x < im->xsize; x++) imOut->image[0][x] = im->image8[0][x]; for (y = 1; y < im->ysize-1; y++) { imOut->image[y][0] = im->image8[y][0]; for (x = 1; x < im->xsize-1; x++) { sum = KERNEL3x3(im->image8, kernel, 1) / divisor + offset; if (sum <= 0) imOut->image8[y][x] = 0; else if (sum >= 255) imOut->image8[y][x] = 255; else imOut->image8[y][x] = (UINT8) sum; } imOut->image8[y][x] = im->image8[y][x]; } for (x = 0; x < im->xsize; x++) imOut->image8[y][x] = im->image8[y][x]; } else { /* 5x5 kernel. */ for (y = 0; y < 2; y++) for (x = 0; x < im->xsize; x++) imOut->image8[y][x] = im->image8[y][x]; for (; y < im->ysize-2; y++) { for (x = 0; x < 2; x++) imOut->image8[y][x] = im->image8[y][x]; for (; x < im->xsize-2; x++) { sum = KERNEL5x5(im->image8, kernel, 1) / divisor + offset; if (sum <= 0) imOut->image8[y][x] = 0; else if (sum >= 255) imOut->image8[y][x] = 255; else imOut->image8[y][x] = (UINT8) sum; } for (; x < im->xsize; x++) imOut->image8[y][x] = im->image8[y][x]; } for (; y < im->ysize; y++) for (x = 0; x < im->xsize; x++) imOut->image8[y][x] = im->image8[y][x]; } return imOut; }