Пример #1
0
Imaging
ImagingAllocateBlock(Imaging im)
{
    Py_ssize_t y, i;

    /* overflow check for malloc */
    if (im->linesize &&
        im->ysize > INT_MAX / im->linesize) {
        return (Imaging) ImagingError_MemoryError();
    }

    if (im->ysize * im->linesize <= 0) {
        /* some platforms return NULL for malloc(0); this fix
           prevents MemoryError on zero-sized images on such
           platforms */
        im->block = (char *) malloc(1);
    } else {
        /* malloc check ok, overflow check above */
        im->block = (char *) calloc(im->ysize, im->linesize);
    }

    if ( ! im->block) {
        return (Imaging) ImagingError_MemoryError();
    }

    for (y = i = 0; y < im->ysize; y++) {
        im->image[y] = im->block + i;
        i += im->linesize;
    }

    im->destroy = ImagingDestroyBlock;

    return im;
}
Пример #2
0
int
ImagingPaletteCachePrepare(ImagingPalette palette)
{
    /* Add a colour cache to a palette */

    int i;
    int entries = 64*64*64;

    if (palette->cache == NULL) {

	/* The cache is 512k.  It might be a good idea to break it
	   up into a pointer array (e.g. an 8-bit image?) */

	palette->cache = (INT16*) malloc(entries * sizeof(INT16));
	if (!palette->cache) {
	    (void) ImagingError_MemoryError();
	    return -1;
	}

	/* Mark all entries as empty */
	for (i = 0; i < entries; i++)
	    palette->cache[i] = 0x100;

    }

    return 0;
}
Пример #3
0
ImagingPalette
ImagingPaletteNew(const char* mode)
{
    /* Create a palette object */

    int i;
    ImagingPalette palette;

    if (strcmp(mode, "RGB") && strcmp(mode, "RGBA"))
	return (ImagingPalette) ImagingError_ModeError();

    palette = calloc(1, sizeof(struct ImagingPaletteInstance));
    if (!palette)
	return (ImagingPalette) ImagingError_MemoryError();

    strncpy(palette->mode, mode, IMAGING_MODE_LENGTH);

    /* Initialize to ramp */
    for (i = 0; i < 256; i++) {
	palette->palette[i*4+0] =
	palette->palette[i*4+1] =
	palette->palette[i*4+2] = (UINT8) i;
	palette->palette[i*4+3] = 255; /* opaque */
    }

    return palette;
}
Пример #4
0
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();
}
Пример #5
0
ImagingOutline
ImagingOutlineNew(void)
{
    ImagingOutline outline;

    outline = calloc(1, sizeof(struct ImagingOutlineInstance));
    if (!outline)
        return (ImagingOutline) ImagingError_MemoryError();

    outline->edges = NULL;
    outline->count = outline->size = 0;

    ImagingOutlineMove(outline, 0, 0);

    return outline;
}
Пример #6
0
ImagingAccess
ImagingAccessNew(Imaging im)
{
    /* Create a standard access object */

    ImagingAccess access;

    access = calloc(1, sizeof(struct ImagingAccessInstance));
    if (!access)
	return (ImagingAccess) ImagingError_MemoryError();

    access->im = im;

    access->getline = access_getline;
    access->destroy = access_destroy;

    return access;
}
Пример #7
0
ImagingPalette
ImagingPaletteDuplicate(ImagingPalette palette)
{
    /* Duplicate palette descriptor */

    ImagingPalette new_palette;

    if (!palette)
	return NULL;

    new_palette = malloc(sizeof(struct ImagingPaletteInstance));
    if (!new_palette)
	return (ImagingPalette) ImagingError_MemoryError();

    memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance));

    /* Don't share the cache */
    new_palette->cache = NULL;

    return new_palette;
}
Пример #8
0
int
ImagingDrawPolygon(Imaging im, int count, int* xy, const void* ink_,
                   int fill, int op)
{
    int i, n;
    DRAW* draw;
    INT32 ink;

    if (count <= 0)
        return 0;

    DRAWINIT();

    if (fill) {

        /* Build edge list */
        /* malloc check ok, using calloc */
        Edge* e = calloc(count, sizeof(Edge));
        if (!e) {
            (void) ImagingError_MemoryError();
            return -1;
        }
        for (i = n = 0; i < count-1; i++)
            add_edge(&e[n++], xy[i+i], xy[i+i+1], xy[i+i+2], xy[i+i+3]);
        if (xy[i+i] != xy[0] || xy[i+i+1] != xy[1])
            add_edge(&e[n++], xy[i+i], xy[i+i+1], xy[0], xy[1]);
        draw->polygon(im, n, e, ink, 0);
        free(e);

    } else {

        /* Outline */
        for (i = 0; i < count-1; i++)
            draw->line(im, xy[i+i], xy[i+i+1], xy[i+i+2], xy[i+i+3], ink);
        draw->line(im, xy[i+i], xy[i+i+1], xy[0], xy[1], ink);

    }

    return 0;
}
Пример #9
0
Imaging
ImagingAllocateArray(Imaging im, int dirty, int block_size)
{
    int y, line_in_block, current_block;
    ImagingMemoryArena arena = &ImagingDefaultArena;
    ImagingMemoryBlock block = {NULL, 0};
    int aligned_linesize, lines_per_block, blocks_count;
    char *aligned_ptr = NULL;

    /* 0-width or 0-height image. No need to do anything */
    if ( ! im->linesize || ! im->ysize) {
        return im;
    }

    aligned_linesize = (im->linesize + arena->alignment - 1) & -arena->alignment;
    lines_per_block = (block_size - (arena->alignment - 1)) / aligned_linesize;
    if (lines_per_block == 0)
        lines_per_block = 1;
    blocks_count = (im->ysize + lines_per_block - 1) / lines_per_block;
    // printf("NEW size: %dx%d, ls: %d, lpb: %d, blocks: %d\n",
    //        im->xsize, im->ysize, aligned_linesize, lines_per_block, blocks_count);

    /* One extra ponter is always NULL */
    im->blocks = calloc(sizeof(*im->blocks), blocks_count + 1);
    if ( ! im->blocks) {
        return (Imaging) ImagingError_MemoryError();
    }

    /* Allocate image as an array of lines */
    line_in_block = 0;
    current_block = 0;
    for (y = 0; y < im->ysize; y++) {
        if (line_in_block == 0) {
            int required;
            int lines_remaining = lines_per_block;
            if (lines_remaining > im->ysize - y) {
                lines_remaining = im->ysize - y;
            }
            required = lines_remaining * aligned_linesize + arena->alignment - 1;
            block = memory_get_block(arena, required, dirty);
            if ( ! block.ptr) {
                ImagingDestroyArray(im);
                return (Imaging) ImagingError_MemoryError();
            }
            im->blocks[current_block] = block;
            /* Bulletproof code from libc _int_memalign */
            aligned_ptr = (char *)(
                ((size_t) (block.ptr + arena->alignment - 1)) &
                -((Py_ssize_t) arena->alignment));
        }

        im->image[y] = aligned_ptr + aligned_linesize * line_in_block;

        line_in_block += 1;
        if (line_in_block >= lines_per_block) {
            /* Reset counter and start new block */
            line_in_block = 0;
            current_block += 1;
        }
    }

    im->destroy = ImagingDestroyArray;

    return im;
}
Пример #10
0
static int
ellipse(Imaging im, int x0, int y0, int x1, int y1,
        int start, int end, const void* ink_, int fill,
        int mode, int op)
{
    int i, n;
    int cx, cy;
    int w, h;
    int x = 0, y = 0;
    int lx = 0, ly = 0;
    int sx = 0, sy = 0;
    DRAW* draw;
    INT32 ink;

    w = x1 - x0;
    h = y1 - y0;
    if (w < 0 || h < 0)
        return 0;

    DRAWINIT();

    cx = (x0 + x1) / 2;
    cy = (y0 + y1) / 2;

    while (end < start)
        end += 360;

    if (mode != ARC && fill) {

        /* Build edge list */
        Edge* e = malloc((end - start + 3) * sizeof(Edge));
        if (!e) {
            ImagingError_MemoryError();
            return -1;
        }

        n = 0;

        for (i = start; i <= end; i++) {
            x = FLOOR((cos(i*M_PI/180) * w/2) + cx + 0.5);
            y = FLOOR((sin(i*M_PI/180) * h/2) + cy + 0.5);
            if (i != start)
                add_edge(&e[n++], lx, ly, x, y);
            else
                sx = x, sy = y;
            lx = x, ly = y;
        }

        if (n > 0) {
            /* close and draw polygon */
            if (mode == PIESLICE) {
                if (x != cx || y != cy) {
                    add_edge(&e[n++], x, y, cx, cy);
                    add_edge(&e[n++], cx, cy, sx, sy);
                }
            } else {
                if (x != sx || y != sy)
                    add_edge(&e[n++], x, y, sx, sy);
            }
            draw->polygon(im, n, e, ink, 0);
        }

        free(e);

    } else {

        for (i = start; i <= end; i++) {
            x = FLOOR((cos(i*M_PI/180) * w/2) + cx + 0.5);
            y = FLOOR((sin(i*M_PI/180) * h/2) + cy + 0.5);
            if (i != start)
                draw->line(im, lx, ly, x, y, ink);
            else
                sx = x, sy = y;
            lx = x, ly = y;
        }

        if (i != start) {
            if (mode == PIESLICE) {
                if (x != cx || y != cy) {
                    draw->line(im, x, y, cx, cy, ink);
                    draw->line(im, cx, cy, sx, sy, ink);
                }
            } else if (mode == CHORD) {
                if (x != sx || y != sy)
                    draw->line(im, x, y, sx, sy, ink);
            }
        }
    }

    return 0;
}
Пример #11
0
static Imaging
gblur(Imaging im, Imaging imOut, float floatRadius, int channels, int padding)
{
    ImagingSectionCookie cookie;

    float *maskData = NULL;
    int y = 0;
    int x = 0;
    float z = 0;
    float sum = 0.0;
    float dev = 0.0;

    float *buffer = NULL;

    int *line = NULL;
    UINT8 *line8 = NULL;

    int pix = 0;
    float newPixel[4];
    int channel = 0;
    int offset = 0;
    INT32 newPixelFinals;

    int radius = 0;
    float remainder = 0.0;

    int i;

    /* Do the gaussian blur */

    /* For a symmetrical gaussian blur, instead of doing a radius*radius
       matrix lookup, you get the EXACT same results by doing a radius*1
       transform, followed by a 1*radius transform.  This reduces the
       number of lookups exponentially (10 lookups per pixel for a
       radius of 5 instead of 25 lookups).  So, we blur the lines first,
       then we blur the resulting columns. */

    /* first, round radius off to the next higher integer and hold the
       remainder this is used so we can support float radius values
       properly. */

    remainder = floatRadius - ((int) floatRadius);
    floatRadius = ceil(floatRadius);

    /* Next, double the radius and offset by 2.0... that way "0" returns
       the original image instead of a black one.  We multiply it by 2.0
       so that it is a true "radius", not a diameter (the results match
       other paint programs closer that way too). */
    radius = (int) ((floatRadius * 2.0) + 2.0);

    /* create the maskData for the gaussian curve */
    maskData = malloc(radius * sizeof(float));
    /* FIXME: error checking */
    for (x = 0; x < radius; x++) {
	z = ((float) (x + 2) / ((float) radius));
	dev = 0.5 + (((float) (radius * radius)) * 0.001);
	/* you can adjust this factor to change the shape/center-weighting
	   of the gaussian */
	maskData[x] = (float) pow((1.0 / sqrt(2.0 * 3.14159265359 * dev)),
				  ((-(z - 1.0) * -(x - 1.0)) /
				   (2.0 * dev)));
    }

    /* if there's any remainder, multiply the first/last values in
       MaskData it.  this allows us to support float radius values. */
    if (remainder > 0.0) {
	maskData[0] *= remainder;
	maskData[radius - 1] *= remainder;
    }

    for (x = 0; x < radius; x++) {
	/* this is done separately now due to the correction for float
	   radius values above */
	sum += maskData[x];
    }

    for (i = 0; i < radius; i++) {
	maskData[i] *= (1.0 / sum);
	/* printf("%f\n", maskData[i]); */
    }

    /* create a temporary memory buffer for the data for the first pass
       memset the buffer to 0 so we can use it directly with += */

    /* don't bother about alpha/padding */
    buffer = calloc((size_t) (im->xsize * im->ysize * channels),
		    sizeof(float));
    if (buffer == NULL)
	return ImagingError_MemoryError();

    /* be nice to other threads while you go off to lala land */
    ImagingSectionEnter(&cookie);

    /* memset(buffer, 0, sizeof(buffer)); */

    newPixel[0] = newPixel[1] = newPixel[2] = newPixel[3] = 0;

    /* perform a blur on each line, and place in the temporary storage buffer */
    for (y = 0; y < im->ysize; y++) {
	if (channels == 1 && im->image8 != NULL) {
	    line8 = (UINT8 *) im->image8[y];
	} else {
	    line = im->image32[y];
	}
	for (x = 0; x < im->xsize; x++) {
	    newPixel[0] = newPixel[1] = newPixel[2] = newPixel[3] = 0;
	    /* for each neighbor pixel, factor in its value/weighting to the
	       current pixel */
	    for (pix = 0; pix < radius; pix++) {
		/* figure the offset of this neighbor pixel */
		offset =
		    (int) ((-((float) radius / 2.0) + (float) pix) + 0.5);
		if (x + offset < 0)
		    offset = -x;
		else if (x + offset >= im->xsize)
		    offset = im->xsize - x - 1;

		/* add (neighbor pixel value * maskData[pix]) to the current
		   pixel value */
		if (channels == 1) {
		    buffer[(y * im->xsize) + x] +=
			((float) ((UINT8 *) & line8[x + offset])[0]) *
			(maskData[pix]);
		} else {
		    for (channel = 0; channel < channels; channel++) {
			buffer[(y * im->xsize * channels) +
			       (x * channels) + channel] +=
			    ((float) ((UINT8 *) & line[x + offset])
			     [channel]) * (maskData[pix]);
		    }
		}
	    }
	}
    }

    /* perform a blur on each column in the buffer, and place in the
       output image */
    for (x = 0; x < im->xsize; x++) {
	for (y = 0; y < im->ysize; y++) {
	    newPixel[0] = newPixel[1] = newPixel[2] = newPixel[3] = 0;
	    /* for each neighbor pixel, factor in its value/weighting to the
	       current pixel */
	    for (pix = 0; pix < radius; pix++) {
		/* figure the offset of this neighbor pixel */
		offset =
		    (int) (-((float) radius / 2.0) + (float) pix + 0.5);
		if (y + offset < 0)
		    offset = -y;
		else if (y + offset >= im->ysize)
		    offset = im->ysize - y - 1;
		/* add (neighbor pixel value * maskData[pix]) to the current
		   pixel value */
		for (channel = 0; channel < channels; channel++) {
		    newPixel[channel] +=
			(buffer
			 [((y + offset) * im->xsize * channels) +
			  (x * channels) + channel]) * (maskData[pix]);
		}
	    }
	    /* if the image is RGBX or RGBA, copy the 4th channel data to
	       newPixel, so it gets put in imOut */
	    if (strcmp(im->mode, "RGBX") == 0
		|| strcmp(im->mode, "RGBA") == 0) {
	      newPixel[3] = (float) ((UINT8 *) & line[x + offset])[3];
	    }

	    /* pack the channels into an INT32 so we can put them back in
	       the PIL image */
	    newPixelFinals = 0;
	    if (channels == 1) {
		newPixelFinals = clip(newPixel[0]);
	    } else {
		/* for RGB, the fourth channel isn't used anyways, so just
		   pack a 0 in there, this saves checking the mode for each
		   pixel. */
		/* this doesn't work on little-endian machines... fix it! */
		newPixelFinals =
		    clip(newPixel[0]) | clip(newPixel[1]) << 8 |
		    clip(newPixel[2]) << 16 | clip(newPixel[3]) << 24;
	    }
	    /* set the resulting pixel in imOut */
	    if (channels == 1) {
		imOut->image8[y][x] = (UINT8) newPixelFinals;
	    } else {
		imOut->image32[y][x] = newPixelFinals;
	    }
	}
    }

    /* free the buffer */
    free(buffer);

    /* get the GIL back so Python knows who you are */
    ImagingSectionLeave(&cookie);

    return imOut;
}
Пример #12
0
int
precompute_coeffs(int inSize, float in0, float in1, int outSize,
                  struct filter *filterp, int **boundsp, double **kkp) {
    double support, scale, filterscale;
    double center, ww, ss;
    int xx, x, ksize, xmin, xmax;
    int *bounds;
    double *kk, *k;

    /* prepare for horizontal stretch */
    filterscale = scale = (double) (in1 - in0) / outSize;
    if (filterscale < 1.0) {
        filterscale = 1.0;
    }

    /* determine support size (length of resampling filter) */
    support = filterp->support * filterscale;

    /* maximum number of coeffs */
    ksize = (int) ceil(support) * 2 + 1;

    // check for overflow
    if (outSize > INT_MAX / (ksize * sizeof(double))) {
        ImagingError_MemoryError();
        return 0;
    }

    /* coefficient buffer */
    /* malloc check ok, overflow checked above */
    kk = malloc(outSize * ksize * sizeof(double));
    if ( ! kk) {
        ImagingError_MemoryError();
        return 0;
    }

    /* malloc check ok, ksize*sizeof(double) > 2*sizeof(int) */
    bounds = malloc(outSize * 2 * sizeof(int));
    if ( ! bounds) {
        free(kk);
        ImagingError_MemoryError();
        return 0;
    }

    for (xx = 0; xx < outSize; xx++) {
        center = in0 + (xx + 0.5) * scale;
        ww = 0.0;
        ss = 1.0 / filterscale;
        // Round the value
        xmin = (int) (center - support + 0.5);
        if (xmin < 0)
            xmin = 0;
        // Round the value
        xmax = (int) (center + support + 0.5);
        if (xmax > inSize)
            xmax = inSize;
        xmax -= xmin;
        k = &kk[xx * ksize];
        for (x = 0; x < xmax; x++) {
            double w = filterp->filter((x + xmin - center + 0.5) * ss);
            k[x] = w;
            ww += w;
        }
        for (x = 0; x < xmax; x++) {
            if (ww != 0.0)
                k[x] /= ww;
        }
        // Remaining values should stay empty if they are used despite of xmax.
        for (; x < ksize; x++) {
            k[x] = 0;
        }
        bounds[xx * 2 + 0] = xmin;
        bounds[xx * 2 + 1] = xmax;
    }
    *boundsp = bounds;
    *kkp = kk;
    return ksize;
}
Пример #13
0
static int
ellipse(Imaging im, int x0, int y0, int x1, int y1,
        float start, float end, const void* ink_, int fill,
        int width, int mode, int op)
{
    float i;
    int j;
    int n;
    int cx, cy;
    int w, h;
    int x = 0, y = 0;
    int lx = 0, ly = 0;
    int sx = 0, sy = 0;
    DRAW* draw;
    INT32 ink;

    DRAWINIT();

    if (width == 0) {
        width = 1;
    }

    for (j = 0; j < width; j++) {

        w = x1 - x0;
        h = y1 - y0;
        if (w < 0 || h < 0)
            return 0;

        cx = (x0 + x1) / 2;
        cy = (y0 + y1) / 2;

        while (end < start)
            end += 360;

        if (end - start > 360) {
            /* no need to go in loops */
            end = start + 361;
        }

        if (mode != ARC && fill) {

            /* Build edge list */
            /* malloc check UNDONE, FLOAT? */
            Edge* e = calloc((end - start + 3), sizeof(Edge));
            if (!e) {
                ImagingError_MemoryError();
                return -1;
            }
            n = 0;

            for (i = start; i < end+1; i++) {
                if (i > end) {
                    i = end;
                }
                ellipsePoint(cx, cy, w, h, i, &x, &y);
                if (i != start)
                    add_edge(&e[n++], lx, ly, x, y);
                else
                    sx = x, sy = y;
                lx = x, ly = y;
            }

            if (n > 0) {
                /* close and draw polygon */
                if (mode == PIESLICE) {
                    if (x != cx || y != cy) {
                        add_edge(&e[n++], x, y, cx, cy);
                        add_edge(&e[n++], cx, cy, sx, sy);
                    }
                } else {
                    if (x != sx || y != sy)
                        add_edge(&e[n++], x, y, sx, sy);
                }
                draw->polygon(im, n, e, ink, 0);
            }

            free(e);

        } else {

            for (i = start; i < end+1; i++) {
                if (i > end) {
                    i = end;
                }
                ellipsePoint(cx, cy, w, h, i, &x, &y);
                if (i != start)
                    draw->line(im, lx, ly, x, y, ink);
                else
                    sx = x, sy = y;
                lx = x, ly = y;
            }

            if (i != start) {
                if (mode == PIESLICE) {
                    if (j == 0 && (x != cx || y != cy)) {
                        if (width == 1) {
                            draw->line(im, x, y, cx, cy, ink);
                            draw->line(im, cx, cy, sx, sy, ink);
                        } else {
                            ImagingDrawWideLine(im, x, y, cx, cy, &ink, width, op);
                            ImagingDrawWideLine(im, cx, cy, sx, sy, &ink, width, op);
                        }
                    }
                } else if (mode == CHORD) {
                    if (x != sx || y != sy)
                        draw->line(im, x, y, sx, sy, ink);
                }
            }
        }
        x0++;
        y0++;
        x1--;
        y1--;
    }
    return 0;
}
Пример #14
0
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;
}
Пример #15
0
ImagingDIB
ImagingNewDIB(const char *mode, int xsize, int ysize)
{
    /* Create a Windows bitmap */

    ImagingDIB dib;
    RGBQUAD *palette;
    int i;

    /* Check mode */
    if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 &&
        strcmp(mode, "RGB") != 0)
        return (ImagingDIB) ImagingError_ModeError();

    /* Create DIB context and info header */
    /* malloc check ok, small constant allocation */
    dib = (ImagingDIB) malloc(sizeof(*dib));
    if (!dib)
        return (ImagingDIB) ImagingError_MemoryError();
    /* malloc check ok, small constant allocation */
    dib->info = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) +
                                     256 * sizeof(RGBQUAD));
    if (!dib->info) {
        free(dib);
        return (ImagingDIB) ImagingError_MemoryError();
    }

    memset(dib->info, 0, sizeof(BITMAPINFOHEADER));
    dib->info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    dib->info->bmiHeader.biWidth = xsize;
    dib->info->bmiHeader.biHeight = ysize;
    dib->info->bmiHeader.biPlanes = 1;
    dib->info->bmiHeader.biBitCount = strlen(mode)*8;
    dib->info->bmiHeader.biCompression = BI_RGB;

    /* Create DIB */
    dib->dc = CreateCompatibleDC(NULL);
    if (!dib->dc) {
        free(dib->info);
        free(dib);
        return (ImagingDIB) ImagingError_MemoryError();
    }

    dib->bitmap = CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS,
                                   &dib->bits, NULL, 0);
    if (!dib->bitmap) {
        free(dib->info);
        free(dib);
        return (ImagingDIB) ImagingError_MemoryError();
    }

    strcpy(dib->mode, mode);
    dib->xsize = xsize;
    dib->ysize = ysize;

    dib->pixelsize = strlen(mode);
    dib->linesize = (xsize * dib->pixelsize + 3) & -4;

    if (dib->pixelsize == 1)
        dib->pack = dib->unpack = (ImagingShuffler) memcpy;
    else {
        dib->pack = ImagingPackBGR;
        dib->unpack = ImagingPackBGR;
    }

    /* Bind the DIB to the device context */
    dib->old_bitmap = SelectObject(dib->dc, dib->bitmap);

    palette = dib->info->bmiColors;

    /* Bind a palette to it as well (only required for 8-bit DIBs) */
    if (dib->pixelsize == 1) {
        for (i = 0; i < 256; i++) {
            palette[i].rgbRed =
            palette[i].rgbGreen =
            palette[i].rgbBlue = i;
            palette[i].rgbReserved = 0;
        }
        SetDIBColorTable(dib->dc, 0, 256, palette);
    }

    /* Create an associated palette (for 8-bit displays only) */
    if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) {

        char palbuf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)];
        LPLOGPALETTE pal = (LPLOGPALETTE) palbuf;
        int i, r, g, b;

        /* Load system palette */
        pal->palVersion = 0x300;
        pal->palNumEntries = 256;
        GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry);

        if (strcmp(mode, "L") == 0) {

            /* Greyscale DIB.  Fill all 236 slots with a greyscale ramp
             * (this is usually overkill on Windows since VGA only offers
             * 6 bits greyscale resolution).  Ignore the slots already
             * allocated by Windows */

            i = 10;
            for (r = 0; r < 236; r++) {
                pal->palPalEntry[i].peRed =
                pal->palPalEntry[i].peGreen =
                pal->palPalEntry[i].peBlue = i;
                i++;
            }

            dib->palette = CreatePalette(pal);

        } else if (strcmp(mode, "RGB") == 0) {

#ifdef CUBE216

            /* Colour DIB.  Create a 6x6x6 colour cube (216 entries) and
             * add 20 extra greylevels for best result with greyscale
             * images. */

            i = 10;
            for (r = 0; r < 256; r += 51)
                for (g = 0; g < 256; g += 51)
                    for (b = 0; b < 256; b += 51) {
                        pal->palPalEntry[i].peRed = r;
                        pal->palPalEntry[i].peGreen = g;
                        pal->palPalEntry[i].peBlue = b;
                        i++;
                    }
            for (r = 1; r < 22-1; r++) {
                /* Black and white are already provided by the cube. */
                pal->palPalEntry[i].peRed =
                pal->palPalEntry[i].peGreen =
                pal->palPalEntry[i].peBlue = r * 255 / (22-1);
                i++;
            }

#else

            /* Colour DIB.  Alternate palette. */

            i = 10;
            for (r = 0; r < 256; r += 37)
                for (g = 0; g < 256; g += 32)
                    for (b = 0; b < 256; b += 64) {
                        pal->palPalEntry[i].peRed = r;
                        pal->palPalEntry[i].peGreen = g;
                        pal->palPalEntry[i].peBlue = b;
                        i++;
                    }

#endif

            dib->palette = CreatePalette(pal);

        }

    }

    return dib;
}
Пример #16
0
Imaging
ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
{
    Imaging im;

    /* linesize overflow check, roughly the current largest space req'd */
    if (xsize > (INT_MAX / 4) - 1) {
        return (Imaging) ImagingError_MemoryError();
    }

    im = (Imaging) calloc(1, size);
    if (!im) {
        return (Imaging) ImagingError_MemoryError();
    }

    /* Setup image descriptor */
    im->xsize = xsize;
    im->ysize = ysize;

    im->type = IMAGING_TYPE_UINT8;

    if (strcmp(mode, "1") == 0) {
        /* 1-bit images */
        im->bands = im->pixelsize = 1;
        im->linesize = xsize;

    } else if (strcmp(mode, "P") == 0) {
        /* 8-bit palette mapped images */
        im->bands = im->pixelsize = 1;
        im->linesize = xsize;
        im->palette = ImagingPaletteNew("RGB");

    } else if (strcmp(mode, "PA") == 0) {
        /* 8-bit palette with alpha */
        im->bands = 2;
        im->pixelsize = 4; /* store in image32 memory */
        im->linesize = xsize * 4;
        im->palette = ImagingPaletteNew("RGB");

    } else if (strcmp(mode, "L") == 0) {
        /* 8-bit greyscale (luminance) images */
        im->bands = im->pixelsize = 1;
        im->linesize = xsize;

    } else if (strcmp(mode, "LA") == 0) {
        /* 8-bit greyscale (luminance) with alpha */
        im->bands = 2;
        im->pixelsize = 4; /* store in image32 memory */
        im->linesize = xsize * 4;

    } else if (strcmp(mode, "La") == 0) {
        /* 8-bit greyscale (luminance) with premultiplied alpha */
        im->bands = 2;
        im->pixelsize = 4; /* store in image32 memory */
        im->linesize = xsize * 4;

    } else if (strcmp(mode, "F") == 0) {
        /* 32-bit floating point images */
        im->bands = 1;
        im->pixelsize = 4;
        im->linesize = xsize * 4;
        im->type = IMAGING_TYPE_FLOAT32;

    } else if (strcmp(mode, "I") == 0) {
        /* 32-bit integer images */
        im->bands = 1;
        im->pixelsize = 4;
        im->linesize = xsize * 4;
        im->type = IMAGING_TYPE_INT32;

    } else if (strcmp(mode, "I;16") == 0 || strcmp(mode, "I;16L") == 0 \
                           || strcmp(mode, "I;16B") == 0 || strcmp(mode, "I;16N") == 0)  {
        /* EXPERIMENTAL */
        /* 16-bit raw integer images */
        im->bands = 1;
        im->pixelsize = 2;
        im->linesize = xsize * 2;
        im->type = IMAGING_TYPE_SPECIAL;

    } else if (strcmp(mode, "RGB") == 0) {
        /* 24-bit true colour images */
        im->bands = 3;
        im->pixelsize = 4;
        im->linesize = xsize * 4;

    } else if (strcmp(mode, "BGR;15") == 0) {
        /* EXPERIMENTAL */
        /* 15-bit true colour */
        im->bands = 1;
        im->pixelsize = 2;
        im->linesize = (xsize*2 + 3) & -4;
        im->type = IMAGING_TYPE_SPECIAL;

    } else if (strcmp(mode, "BGR;16") == 0) {
        /* EXPERIMENTAL */
        /* 16-bit reversed true colour */
        im->bands = 1;
        im->pixelsize = 2;
        im->linesize = (xsize*2 + 3) & -4;
        im->type = IMAGING_TYPE_SPECIAL;

    } else if (strcmp(mode, "BGR;24") == 0) {
        /* EXPERIMENTAL */
        /* 24-bit reversed true colour */
        im->bands = 1;
        im->pixelsize = 3;
        im->linesize = (xsize*3 + 3) & -4;
        im->type = IMAGING_TYPE_SPECIAL;

    } else if (strcmp(mode, "BGR;32") == 0) {
        /* EXPERIMENTAL */
        /* 32-bit reversed true colour */
        im->bands = 1;
        im->pixelsize = 4;
        im->linesize = (xsize*4 + 3) & -4;
        im->type = IMAGING_TYPE_SPECIAL;

    } else if (strcmp(mode, "RGBX") == 0) {
        /* 32-bit true colour images with padding */
        im->bands = im->pixelsize = 4;
        im->linesize = xsize * 4;

    } else if (strcmp(mode, "RGBA") == 0) {
        /* 32-bit true colour images with alpha */
        im->bands = im->pixelsize = 4;
        im->linesize = xsize * 4;

    } else if (strcmp(mode, "RGBa") == 0) {
        /* 32-bit true colour images with premultiplied alpha */
        im->bands = im->pixelsize = 4;
        im->linesize = xsize * 4;

    } else if (strcmp(mode, "CMYK") == 0) {
        /* 32-bit colour separation */
        im->bands = im->pixelsize = 4;
        im->linesize = xsize * 4;

    } else if (strcmp(mode, "YCbCr") == 0) {
        /* 24-bit video format */
        im->bands = 3;
        im->pixelsize = 4;
        im->linesize = xsize * 4;

    } else if (strcmp(mode, "LAB") == 0) {
        /* 24-bit color, luminance, + 2 color channels */
        /* L is uint8, a,b are int8 */
        im->bands = 3;
        im->pixelsize = 4;
        im->linesize = xsize * 4;

    } else if (strcmp(mode, "HSV") == 0) {
        /* 24-bit color, luminance, + 2 color channels */
        /* L is uint8, a,b are int8 */
        im->bands = 3;
        im->pixelsize = 4;
        im->linesize = xsize * 4;

    } else {
        free(im);
        return (Imaging) ImagingError_ValueError("unrecognized image mode");
    }

    /* Setup image descriptor */
    strcpy(im->mode, mode);

    /* Pointer array (allocate at least one line, to avoid MemoryError
       exceptions on platforms where calloc(0, x) returns NULL) */
    im->image = (char **) calloc((ysize > 0) ? ysize : 1, sizeof(void *));

    if ( ! im->image) {
        free(im);
        return (Imaging) ImagingError_MemoryError();
    }

    /* Initialize alias pointers to pixel data. */
    switch (im->pixelsize) {
    case 1: case 2: case 3:
        im->image8 = (UINT8 **) im->image;
        break;
    case 4:
        im->image32 = (INT32 **) im->image;
        break;
    }

    ImagingDefaultArena.stats_new_count += 1;

    return im;
}
Пример #17
0
int
ImagingOutlineTransform(ImagingOutline outline, double a[6])
{
    Edge *eIn;
    Edge *eOut;
    int i, n;
    int x0, y0, x1, y1;
    int X0, Y0, X1, Y1;

    double a0 = a[0]; double a1 = a[1]; double a2 = a[2];
    double a3 = a[3]; double a4 = a[4]; double a5 = a[5];

    eIn = outline->edges;
    n = outline->count;

    /* FIXME: ugly! */
    outline->edges = NULL;
    outline->count = outline->size = 0;

    eOut = allocate(outline, n);
    if (!eOut) {
        outline->edges = eIn;
        outline->count = outline->size = n;
        ImagingError_MemoryError();
        return -1;
    }

    for (i = 0; i < n; i++) {

        x0 = eIn->x0;
        y0 = eIn->y0;

        /* FIXME: ouch! */
        if (eIn->x0 == eIn->xmin)
            x1 = eIn->xmax;
        else
            x1 = eIn->xmin;
        if (eIn->y0 == eIn->ymin)
            y1 = eIn->ymax;
        else
            y1 = eIn->ymin;

        /* full moon tonight!  if this doesn't work, you may need to
           upgrade your compiler (make sure you have the right service
           pack) */

        X0 = (int) (a0*x0 + a1*y0 + a2);
        Y0 = (int) (a3*x0 + a4*y0 + a5);
        X1 = (int) (a0*x1 + a1*y1 + a2);
        Y1 = (int) (a3*x1 + a4*y1 + a5);

        add_edge(eOut, X0, Y0, X1, Y1);

        eIn++;
        eOut++;

    }

    free(eIn);

    return 0;
}