mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 09:57:43 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			170 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * 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->histogram)
 | 
						|
	free(h->histogram);
 | 
						|
    free(h);
 | 
						|
}
 | 
						|
 | 
						|
ImagingHistogram
 | 
						|
ImagingHistogramNew(Imaging im)
 | 
						|
{
 | 
						|
    ImagingHistogram h;
 | 
						|
 | 
						|
    /* Create histogram descriptor */
 | 
						|
    h = calloc(1, sizeof(struct ImagingHistogramInstance));
 | 
						|
    strncpy(h->mode, im->mode, IMAGING_MODE_LENGTH);
 | 
						|
    h->bands = im->bands;
 | 
						|
    h->histogram = calloc(im->pixelsize, 256 * sizeof(long));
 | 
						|
 | 
						|
    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 (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)
 | 
						|
                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)
 | 
						|
                    return ImagingError_ValueError("min/max not given");
 | 
						|
                if (!im->xsize || !im->ysize)
 | 
						|
                    break;
 | 
						|
                imin = ((INT32*) minmax)[0];
 | 
						|
                imax = ((INT32*) minmax)[1];
 | 
						|
                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)
 | 
						|
                    return ImagingError_ValueError("min/max not given");
 | 
						|
                if (!im->xsize || !im->ysize)
 | 
						|
                    break;
 | 
						|
                fmin = ((FLOAT32*) minmax)[0];
 | 
						|
                fmax = ((FLOAT32*) minmax)[1];
 | 
						|
                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;
 | 
						|
}
 |