Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Imaging/libImaging/GetBBox.c
diff options
context:
space:
mode:
Diffstat (limited to 'Imaging/libImaging/GetBBox.c')
-rw-r--r--Imaging/libImaging/GetBBox.c322
1 files changed, 322 insertions, 0 deletions
diff --git a/Imaging/libImaging/GetBBox.c b/Imaging/libImaging/GetBBox.c
new file mode 100644
index 0000000..c06d0eb
--- /dev/null
+++ b/Imaging/libImaging/GetBBox.c
@@ -0,0 +1,322 @@
+/*
+ * The Python Imaging Library
+ * $Id: GetBBox.c 2298 2005-02-17 21:17:29Z fredrik $
+ *
+ * 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) {
+ 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];
+ }
+ }
+ ((INT32*) extrema)[0] = imin;
+ ((INT32*) extrema)[1] = 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];
+ }
+ }
+ ((FLOAT32*) extrema)[0] = fmin;
+ ((FLOAT32*) extrema)[1] = fmax;
+ break;
+ case IMAGING_TYPE_SPECIAL:
+ if (strcmp(im->mode, "I;16") == 0) {
+ imin = imax = ((UINT16*) im->image8[0])[0];
+ for (y = 0; y < im->ysize; y++) {
+ UINT16* in = (UINT16 *) im->image[y];
+ for (x = 0; x < im->xsize; x++) {
+ if (imin > in[x])
+ imin = in[x];
+ else if (imax < in[x])
+ imax = in[x];
+ }
+ }
+ ((UINT16*) extrema)[0] = (UINT16) imin;
+ ((UINT16*) extrema)[1] = (UINT16) imax;
+ break;
+ }
+ /* FALL THROUGH */
+ default:
+ 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) {
+ ImagingError_MemoryError(); /* just give up */
+ return NULL;
+ }
+
+ if (!im->image32) {
+ ImagingError_ModeError();
+ return NULL;
+ }
+
+ table = calloc(code_size + 1, sizeof(ImagingColorItem));
+ if (!table) {
+ ImagingError_MemoryError();
+ return NULL;
+ }
+
+ 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;
+}