123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- /*
- * The Python Imaging Library
- * $Id$
- *
- * helpers to bounding boxes, min/max values, number of colors, etc.
- *
- * history:
- * 1996-07-22 fl Created
- * 1996-12-30 fl Added projection stuff
- * 1998-07-12 fl Added extrema stuff
- * 2004-09-17 fl Added colors stuff
- *
- * Copyright (c) 1997-2004 by Secret Labs AB.
- * Copyright (c) 1996-2004 by Fredrik Lundh.
- *
- * See the README file for details on usage and redistribution.
- */
- #include "Imaging.h"
- int
- ImagingGetBBox(Imaging im, int bbox[4])
- {
- /* Get the bounding box for any non-zero data in the image.*/
- int x, y;
- int has_data;
- /* Initialize bounding box to max values */
- bbox[0] = im->xsize;
- bbox[1] = -1;
- bbox[2] = bbox[3] = 0;
- #define GETBBOX(image, mask)\
- for (y = 0; y < im->ysize; y++) {\
- has_data = 0;\
- for (x = 0; x < im->xsize; x++)\
- if (im->image[y][x] & mask) {\
- has_data = 1;\
- if (x < bbox[0])\
- bbox[0] = x;\
- if (x >= bbox[2])\
- bbox[2] = x+1;\
- }\
- if (has_data) {\
- if (bbox[1] < 0)\
- bbox[1] = y;\
- bbox[3] = y+1;\
- }\
- }
- if (im->image8) {
- GETBBOX(image8, 0xff);
- } else {
- INT32 mask = 0xffffffff;
- if (im->bands == 3)
- ((UINT8*) &mask)[3] = 0;
- GETBBOX(image32, mask);
- }
- /* Check that we got a box */
- if (bbox[1] < 0)
- return 0; /* no data */
- return 1; /* ok */
- }
- int
- ImagingGetProjection(Imaging im, UINT8* xproj, UINT8* yproj)
- {
- /* Get projection arrays for non-zero data in the image.*/
- int x, y;
- int has_data;
- /* Initialize projection arrays */
- memset(xproj, 0, im->xsize);
- memset(yproj, 0, im->ysize);
- #define GETPROJ(image, mask)\
- for (y = 0; y < im->ysize; y++) {\
- has_data = 0;\
- for (x = 0; x < im->xsize; x++)\
- if (im->image[y][x] & mask) {\
- has_data = 1;\
- xproj[x] = 1;\
- }\
- if (has_data)\
- yproj[y] = 1;\
- }
- if (im->image8) {
- GETPROJ(image8, 0xff);
- } else {
- INT32 mask = 0xffffffff;
- if (im->bands == 3)
- ((UINT8*) &mask)[3] = 0;
- GETPROJ(image32, mask);
- }
- return 1; /* ok */
- }
- int
- ImagingGetExtrema(Imaging im, void *extrema)
- {
- int x, y;
- INT32 imin, imax;
- FLOAT32 fmin, fmax;
- if (im->bands != 1) {
- (void) ImagingError_ModeError();
- return -1; /* mismatch */
- }
- if (!im->xsize || !im->ysize)
- return 0; /* zero size */
- switch (im->type) {
- case IMAGING_TYPE_UINT8:
- imin = imax = im->image8[0][0];
- for (y = 0; y < im->ysize; y++) {
- UINT8* in = im->image8[y];
- for (x = 0; x < im->xsize; x++) {
- if (imin > in[x])
- imin = in[x];
- else if (imax < in[x])
- imax = in[x];
- }
- }
- ((UINT8*) extrema)[0] = (UINT8) imin;
- ((UINT8*) extrema)[1] = (UINT8) imax;
- break;
- case IMAGING_TYPE_INT32:
- imin = imax = im->image32[0][0];
- for (y = 0; y < im->ysize; y++) {
- INT32* in = im->image32[y];
- for (x = 0; x < im->xsize; x++) {
- if (imin > in[x])
- imin = in[x];
- else if (imax < in[x])
- imax = in[x];
- }
- }
- memcpy(extrema, &imin, sizeof(imin));
- memcpy(((char*)extrema) + sizeof(imin), &imax, sizeof(imax));
- break;
- case IMAGING_TYPE_FLOAT32:
- fmin = fmax = ((FLOAT32*) im->image32[0])[0];
- for (y = 0; y < im->ysize; y++) {
- FLOAT32* in = (FLOAT32*) im->image32[y];
- for (x = 0; x < im->xsize; x++) {
- if (fmin > in[x])
- fmin = in[x];
- else if (fmax < in[x])
- fmax = in[x];
- }
- }
- memcpy(extrema, &fmin, sizeof(fmin));
- memcpy(((char*)extrema) + sizeof(fmin), &fmax, sizeof(fmax));
- break;
- case IMAGING_TYPE_SPECIAL:
- if (strcmp(im->mode, "I;16") == 0) {
- UINT16 v;
- memcpy(&v, *im->image8, sizeof(v));
- imin = imax = v;
- for (y = 0; y < im->ysize; y++) {
- for (x = 0; x < im->xsize; x++) {
- memcpy(&v, im->image[y] + x * sizeof(v), sizeof(v));
- if (imin > v)
- imin = v;
- else if (imax < v)
- imax = v;
- }
- }
- v = (UINT16) imin;
- memcpy(extrema, &v, sizeof(v));
- v = (UINT16) imax;
- memcpy(((char*)extrema) + sizeof(v), &v, sizeof(v));
- break;
- }
- /* FALL THROUGH */
- default:
- (void) ImagingError_ModeError();
- return -1;
- }
- return 1; /* ok */
- }
- /* static ImagingColorItem* getcolors8(Imaging im, int maxcolors, int* size);*/
- static ImagingColorItem* getcolors32(Imaging im, int maxcolors, int* size);
- ImagingColorItem*
- ImagingGetColors(Imaging im, int maxcolors, int* size)
- {
- /* FIXME: add support for 8-bit images */
- return getcolors32(im, maxcolors, size);
- }
- static ImagingColorItem*
- getcolors32(Imaging im, int maxcolors, int* size)
- {
- unsigned int h;
- unsigned int i, incr;
- int colors;
- INT32 pixel_mask;
- int x, y;
- ImagingColorItem* table;
- ImagingColorItem* v;
- unsigned int code_size;
- unsigned int code_poly;
- unsigned int code_mask;
- /* note: the hash algorithm used here is based on the dictionary
- code in Python 2.1.3; the exact implementation is borrowed from
- Python's Unicode property database (written by yours truly) /F */
- static int SIZES[] = {
- 4,3, 8,3, 16,3, 32,5, 64,3, 128,3, 256,29, 512,17, 1024,9, 2048,5,
- 4096,83, 8192,27, 16384,43, 32768,3, 65536,45, 131072,9, 262144,39,
- 524288,39, 1048576,9, 2097152,5, 4194304,3, 8388608,33, 16777216,27,
- 33554432,9, 67108864,71, 134217728,39, 268435456,9, 536870912,5,
- 1073741824,83, 0
- };
- code_size = code_poly = code_mask = 0;
- for (i = 0; SIZES[i]; i += 2) {
- if (SIZES[i] > maxcolors) {
- code_size = SIZES[i];
- code_poly = SIZES[i+1];
- code_mask = code_size - 1;
- break;
- }
- }
- /* printf("code_size=%d\n", code_size); */
- /* printf("code_poly=%d\n", code_poly); */
- if (!code_size)
- return ImagingError_MemoryError(); /* just give up */
- if (!im->image32)
- return ImagingError_ModeError();
- table = calloc(code_size + 1, sizeof(ImagingColorItem));
- if (!table)
- return ImagingError_MemoryError();
- pixel_mask = 0xffffffff;
- if (im->bands == 3)
- ((UINT8*) &pixel_mask)[3] = 0;
- colors = 0;
- for (y = 0; y < im->ysize; y++) {
- INT32* p = im->image32[y];
- for (x = 0; x < im->xsize; x++) {
- INT32 pixel = p[x] & pixel_mask;
- h = (pixel); /* null hashing */
- i = (~h) & code_mask;
- v = &table[i];
- if (!v->count) {
- /* add to table */
- if (colors++ == maxcolors)
- goto overflow;
- v->x = x; v->y = y;
- v->pixel = pixel;
- v->count = 1;
- continue;
- } else if (v->pixel == pixel) {
- v->count++;
- continue;
- }
- incr = (h ^ (h >> 3)) & code_mask;
- if (!incr)
- incr = code_mask;
- for (;;) {
- i = (i + incr) & code_mask;
- v = &table[i];
- if (!v->count) {
- /* add to table */
- if (colors++ == maxcolors)
- goto overflow;
- v->x = x; v->y = y;
- v->pixel = pixel;
- v->count = 1;
- break;
- } else if (v->pixel == pixel) {
- v->count++;
- break;
- }
- incr = incr << 1;
- if (incr > code_mask)
- incr = incr ^ code_poly;
- }
- }
- }
- overflow:
- /* pack the table */
- for (x = y = 0; x < (int) code_size; x++)
- if (table[x].count) {
- if (x != y)
- table[y] = table[x];
- y++;
- }
- table[y].count = 0; /* mark end of table */
- *size = colors;
- return table;
- }
|