Pillow
356 строк · 10.5 Кб
1/*
2* The Python Imaging Library
3* $Id$
4*
5* helpers to bounding boxes, min/max values, number of colors, etc.
6*
7* history:
8* 1996-07-22 fl Created
9* 1996-12-30 fl Added projection stuff
10* 1998-07-12 fl Added extrema stuff
11* 2004-09-17 fl Added colors stuff
12*
13* Copyright (c) 1997-2004 by Secret Labs AB.
14* Copyright (c) 1996-2004 by Fredrik Lundh.
15*
16* See the README file for details on usage and redistribution.
17*/
18
19#include "Imaging.h"20
21int
22ImagingGetBBox(Imaging im, int bbox[4], int alpha_only) {23/* Get the bounding box for any non-zero data in the image.*/24
25int x, y;26int has_data;27
28/* Initialize bounding box to max values */29bbox[0] = im->xsize;30bbox[1] = -1;31bbox[2] = bbox[3] = 0;32
33#define GETBBOX(image, mask) \34for (y = 0; y < im->ysize; y++) { \35has_data = 0; \36for (x = 0; x < im->xsize; x++) { \37if (im->image[y][x] & mask) { \38has_data = 1; \39if (x < bbox[0]) { \40bbox[0] = x; \41} \42if (x >= bbox[2]) { \43bbox[2] = x + 1; \44} \45} \46} \47if (has_data) { \48if (bbox[1] < 0) { \49bbox[1] = y; \50} \51bbox[3] = y + 1; \52} \53}54
55if (im->image8) {56GETBBOX(image8, 0xff);57} else {58INT32 mask = 0xffffffff;59if (im->bands == 3) {60((UINT8 *)&mask)[3] = 0;61} else if (alpha_only &&62(strcmp(im->mode, "RGBa") == 0 || strcmp(im->mode, "RGBA") == 0 ||63strcmp(im->mode, "La") == 0 || strcmp(im->mode, "LA") == 0 ||64strcmp(im->mode, "PA") == 0)) {65#ifdef WORDS_BIGENDIAN66mask = 0x000000ff;67#else68mask = 0xff000000;69#endif70}71GETBBOX(image32, mask);72}73
74/* Check that we got a box */75if (bbox[1] < 0) {76return 0; /* no data */77}78
79return 1; /* ok */80}
81
82int
83ImagingGetProjection(Imaging im, UINT8 *xproj, UINT8 *yproj) {84/* Get projection arrays for non-zero data in the image.*/85
86int x, y;87int has_data;88
89/* Initialize projection arrays */90memset(xproj, 0, im->xsize);91memset(yproj, 0, im->ysize);92
93#define GETPROJ(image, mask) \94for (y = 0; y < im->ysize; y++) { \95has_data = 0; \96for (x = 0; x < im->xsize; x++) { \97if (im->image[y][x] & mask) { \98has_data = 1; \99xproj[x] = 1; \100} \101} \102if (has_data) { \103yproj[y] = 1; \104} \105}106
107if (im->image8) {108GETPROJ(image8, 0xff);109} else {110INT32 mask = 0xffffffff;111if (im->bands == 3) {112((UINT8 *)&mask)[3] = 0;113}114GETPROJ(image32, mask);115}116
117return 1; /* ok */118}
119
120int
121ImagingGetExtrema(Imaging im, void *extrema) {122int x, y;123INT32 imin, imax;124FLOAT32 fmin, fmax;125
126if (im->bands != 1) {127(void)ImagingError_ModeError();128return -1; /* mismatch */129}130
131if (!im->xsize || !im->ysize) {132return 0; /* zero size */133}134
135switch (im->type) {136case IMAGING_TYPE_UINT8:137imin = imax = im->image8[0][0];138for (y = 0; y < im->ysize; y++) {139UINT8 *in = im->image8[y];140for (x = 0; x < im->xsize; x++) {141if (imin > in[x]) {142imin = in[x];143} else if (imax < in[x]) {144imax = in[x];145}146}147}148((UINT8 *)extrema)[0] = (UINT8)imin;149((UINT8 *)extrema)[1] = (UINT8)imax;150break;151case IMAGING_TYPE_INT32:152imin = imax = im->image32[0][0];153for (y = 0; y < im->ysize; y++) {154INT32 *in = im->image32[y];155for (x = 0; x < im->xsize; x++) {156if (imin > in[x]) {157imin = in[x];158} else if (imax < in[x]) {159imax = in[x];160}161}162}163memcpy(extrema, &imin, sizeof(imin));164memcpy(((char *)extrema) + sizeof(imin), &imax, sizeof(imax));165break;166case IMAGING_TYPE_FLOAT32:167fmin = fmax = ((FLOAT32 *)im->image32[0])[0];168for (y = 0; y < im->ysize; y++) {169FLOAT32 *in = (FLOAT32 *)im->image32[y];170for (x = 0; x < im->xsize; x++) {171if (fmin > in[x]) {172fmin = in[x];173} else if (fmax < in[x]) {174fmax = in[x];175}176}177}178memcpy(extrema, &fmin, sizeof(fmin));179memcpy(((char *)extrema) + sizeof(fmin), &fmax, sizeof(fmax));180break;181case IMAGING_TYPE_SPECIAL:182if (strcmp(im->mode, "I;16") == 0) {183UINT16 v;184UINT8 *pixel = *im->image8;185#ifdef WORDS_BIGENDIAN186v = pixel[0] + (pixel[1] << 8);187#else188memcpy(&v, pixel, sizeof(v));189#endif190imin = imax = v;191for (y = 0; y < im->ysize; y++) {192for (x = 0; x < im->xsize; x++) {193pixel = (UINT8 *)im->image[y] + x * sizeof(v);194#ifdef WORDS_BIGENDIAN195v = pixel[0] + (pixel[1] << 8);196#else197memcpy(&v, pixel, sizeof(v));198#endif199if (imin > v) {200imin = v;201} else if (imax < v) {202imax = v;203}204}205}206v = (UINT16)imin;207memcpy(extrema, &v, sizeof(v));208v = (UINT16)imax;209memcpy(((char *)extrema) + sizeof(v), &v, sizeof(v));210break;211}212/* FALL THROUGH */213default:214(void)ImagingError_ModeError();215return -1;216}217return 1; /* ok */218}
219
220/* static ImagingColorItem* getcolors8(Imaging im, int maxcolors, int* size);*/
221static ImagingColorItem *222getcolors32(Imaging im, int maxcolors, int *size);223
224ImagingColorItem *225ImagingGetColors(Imaging im, int maxcolors, int *size) {226/* FIXME: add support for 8-bit images */227return getcolors32(im, maxcolors, size);228}
229
230static ImagingColorItem *231getcolors32(Imaging im, int maxcolors, int *size) {232unsigned int h;233unsigned int i, incr;234int colors;235INT32 pixel_mask;236int x, y;237ImagingColorItem *table;238ImagingColorItem *v;239
240unsigned int code_size;241unsigned int code_poly;242unsigned int code_mask;243
244/* note: the hash algorithm used here is based on the dictionary245code in Python 2.1.3; the exact implementation is borrowed from
246Python's Unicode property database (written by yours truly) /F */
247
248static int SIZES[] = {4, 3, 8, 3, 16, 3, 32, 5,24964, 3, 128, 3, 256, 29, 512, 17,2501024, 9, 2048, 5, 4096, 83, 8192, 27,25116384, 43, 32768, 3, 65536, 45, 131072, 9,252262144, 39, 524288, 39, 1048576, 9, 2097152, 5,2534194304, 3, 8388608, 33, 16777216, 27, 33554432, 9,25467108864, 71, 134217728, 39, 268435456, 9, 536870912, 5,2551073741824, 83, 0};256
257code_size = code_poly = code_mask = 0;258
259for (i = 0; SIZES[i]; i += 2) {260if (SIZES[i] > maxcolors) {261code_size = SIZES[i];262code_poly = SIZES[i + 1];263code_mask = code_size - 1;264break;265}266}267
268/* printf("code_size=%d\n", code_size); */269/* printf("code_poly=%d\n", code_poly); */270
271if (!code_size) {272return ImagingError_MemoryError(); /* just give up */273}274
275if (!im->image32) {276return ImagingError_ModeError();277}278
279table = calloc(code_size + 1, sizeof(ImagingColorItem));280if (!table) {281return ImagingError_MemoryError();282}283
284pixel_mask = 0xffffffff;285if (im->bands == 3) {286((UINT8 *)&pixel_mask)[3] = 0;287}288
289colors = 0;290
291for (y = 0; y < im->ysize; y++) {292INT32 *p = im->image32[y];293for (x = 0; x < im->xsize; x++) {294INT32 pixel = p[x] & pixel_mask;295h = (pixel); /* null hashing */296i = (~h) & code_mask;297v = &table[i];298if (!v->count) {299/* add to table */300if (colors++ == maxcolors) {301goto overflow;302}303v->x = x;304v->y = y;305v->pixel = pixel;306v->count = 1;307continue;308} else if (v->pixel == pixel) {309v->count++;310continue;311}312incr = (h ^ (h >> 3)) & code_mask;313if (!incr) {314incr = code_mask;315}316for (;;) {317i = (i + incr) & code_mask;318v = &table[i];319if (!v->count) {320/* add to table */321if (colors++ == maxcolors) {322goto overflow;323}324v->x = x;325v->y = y;326v->pixel = pixel;327v->count = 1;328break;329} else if (v->pixel == pixel) {330v->count++;331break;332}333incr = incr << 1;334if (incr > code_mask) {335incr = incr ^ code_poly;336}337}338}339}340
341overflow:342
343/* pack the table */344for (x = y = 0; x < (int)code_size; x++)345if (table[x].count) {346if (x != y) {347table[y] = table[x];348}349y++;350}351table[y].count = 0; /* mark end of table */352
353*size = colors;354
355return table;356}
357