/* * The Python Imaging Library * $Id$ * * histogram support * * history: * 1995-06-15 fl Created. * 1996-04-05 fl Fixed histogram for multiband images. * 1997-02-23 fl Added mask support * 1998-07-01 fl Added basic 32-bit float/integer support * * Copyright (c) 1997-2003 by Secret Labs AB. * Copyright (c) 1995-2003 by Fredrik Lundh. * * See the README file for information on usage and redistribution. */ #include "Imaging.h" /* HISTOGRAM */ /* -------------------------------------------------------------------- * Take a histogram of an image. Returns a histogram object containing * 256 slots per band in the input image. */ void ImagingHistogramDelete(ImagingHistogram h) { if (h) { if (h->histogram) { free(h->histogram); } free(h); } } ImagingHistogram ImagingHistogramNew(Imaging im) { ImagingHistogram h; /* Create histogram descriptor */ h = calloc(1, sizeof(struct ImagingHistogramInstance)); if (!h) { return (ImagingHistogram)ImagingError_MemoryError(); } strncpy(h->mode, im->mode, IMAGING_MODE_LENGTH - 1); h->mode[IMAGING_MODE_LENGTH - 1] = 0; h->bands = im->bands; h->histogram = calloc(im->pixelsize, 256 * sizeof(long)); if (!h->histogram) { free(h); return (ImagingHistogram)ImagingError_MemoryError(); } return h; } ImagingHistogram ImagingGetHistogram(Imaging im, Imaging imMask, void *minmax) { ImagingSectionCookie cookie; int x, y, i; ImagingHistogram h; INT32 imin, imax; FLOAT32 fmin, fmax, scale; if (!im) { return ImagingError_ModeError(); } if (imMask) { /* Validate mask */ if (im->xsize != imMask->xsize || im->ysize != imMask->ysize) { return ImagingError_Mismatch(); } if (strcmp(imMask->mode, "1") != 0 && strcmp(imMask->mode, "L") != 0) { return ImagingError_ValueError("bad transparency mask"); } } h = ImagingHistogramNew(im); if (!h) { return NULL; } if (imMask) { /* mask */ if (im->image8) { ImagingSectionEnter(&cookie); for (y = 0; y < im->ysize; y++) { for (x = 0; x < im->xsize; x++) { if (imMask->image8[y][x] != 0) { h->histogram[im->image8[y][x]]++; } } } ImagingSectionLeave(&cookie); } else { /* yes, we need the braces. C isn't Python! */ if (im->type != IMAGING_TYPE_UINT8) { ImagingHistogramDelete(h); return ImagingError_ModeError(); } ImagingSectionEnter(&cookie); for (y = 0; y < im->ysize; y++) { UINT8 *in = (UINT8 *)im->image32[y]; for (x = 0; x < im->xsize; x++) { if (imMask->image8[y][x] != 0) { h->histogram[(*in++)]++; h->histogram[(*in++) + 256]++; h->histogram[(*in++) + 512]++; h->histogram[(*in++) + 768]++; } else { in += 4; } } } ImagingSectionLeave(&cookie); } } else { /* mask not given; process pixels in image */ if (im->image8) { ImagingSectionEnter(&cookie); for (y = 0; y < im->ysize; y++) { for (x = 0; x < im->xsize; x++) { h->histogram[im->image8[y][x]]++; } } ImagingSectionLeave(&cookie); } else { switch (im->type) { case IMAGING_TYPE_UINT8: ImagingSectionEnter(&cookie); for (y = 0; y < im->ysize; y++) { UINT8 *in = (UINT8 *)im->image[y]; for (x = 0; x < im->xsize; x++) { h->histogram[(*in++)]++; h->histogram[(*in++) + 256]++; h->histogram[(*in++) + 512]++; h->histogram[(*in++) + 768]++; } } ImagingSectionLeave(&cookie); break; case IMAGING_TYPE_INT32: if (!minmax) { ImagingHistogramDelete(h); return ImagingError_ValueError("min/max not given"); } if (!im->xsize || !im->ysize) { break; } memcpy(&imin, minmax, sizeof(imin)); memcpy(&imax, ((char *)minmax) + sizeof(imin), sizeof(imax)); if (imin >= imax) { break; } ImagingSectionEnter(&cookie); scale = 255.0F / (imax - imin); for (y = 0; y < im->ysize; y++) { INT32 *in = im->image32[y]; for (x = 0; x < im->xsize; x++) { i = (int)(((*in++) - imin) * scale); if (i >= 0 && i < 256) { h->histogram[i]++; } } } ImagingSectionLeave(&cookie); break; case IMAGING_TYPE_FLOAT32: if (!minmax) { ImagingHistogramDelete(h); return ImagingError_ValueError("min/max not given"); } if (!im->xsize || !im->ysize) { break; } memcpy(&fmin, minmax, sizeof(fmin)); memcpy(&fmax, ((char *)minmax) + sizeof(fmin), sizeof(fmax)); if (fmin >= fmax) { break; } ImagingSectionEnter(&cookie); scale = 255.0F / (fmax - fmin); for (y = 0; y < im->ysize; y++) { FLOAT32 *in = (FLOAT32 *)im->image32[y]; for (x = 0; x < im->xsize; x++) { i = (int)(((*in++) - fmin) * scale); if (i >= 0 && i < 256) { h->histogram[i]++; } } } ImagingSectionLeave(&cookie); break; } } } return h; }