histogram Tcl_Obj* imageObj /* * This operation is a general histogram generator */ crimp_image* image; int x, y, c, i, count, maxv, largegrey; int* histogram; Tcl_Obj* d; /* dict of histograms, indexed by channel name */ Tcl_Obj* h; /* histogram dict, indexed by pixel value */ Tcl_Obj* k; /* channel name as Tcl_Obj, for the main dict */ crimp_input_any (imageObj, image); ASSERT_NOTIMGTYPE(image,grey32); /* * Actually NOT any. The code below is not able to handle grey32, as images * with these types can have 4G possible values, for which we cannot allocate * a full counter array. * * XXX This needs fixing. Use of a hashtable to allocate only pixel values * actually seen. Will still run into trouble for extreme images which do * contain all the possible values. */ largegrey = image->itype == crimp_imagetype_find ("crimp::image::grey16"); if (largegrey) { maxv = 65536; } else { maxv = 256; } histogram = NALLOC (maxv * image->itype->channels, int); memset (histogram, '\0', maxv * image->itype->channels * sizeof (int)); /* * Count the pixel values. */ #define BUCKET(c,v) histogram [((c) * maxv + (v))] if (largegrey) { for (y = 0; y < image->h; y++) { for (x = 0; x < image->w; x++) { BUCKET (0, GREY16 (image, x, y)) ++; } } } else { for (y = 0; y < image->h; y++) { for (x = 0; x < image->w; x++) { for (c = 0; c < image->itype->channels; c++) { BUCKET (c, CH (image, c, x, y)) ++; } } } } /* * Convert the data into a dictionary to return. * * XXX: For the very large histograms of grey32 (4GB possible values) it would * be sensible to suppress the entries for all pixel values which are not * used, i.e. have a count of zero. */ d = Tcl_NewDictObj (); for (c = 0; c < image->itype->channels; c++) { k = Tcl_NewStringObj (image->itype->cname [c],-1); h = Tcl_NewDictObj (); for (i = 0; i < maxv; i++) { count = BUCKET (c, i); /* * XXX future optimization: keep a hash table of the Int objects, and * share them as much a is possible. */ Tcl_DictObjPut (interp, h, Tcl_NewIntObj (i), Tcl_NewIntObj (count)); } Tcl_DictObjPut (interp, d, k, h); } ckfree ((char*) histogram); Tcl_SetObjResult(interp, d); return TCL_OK; /* vim: set sts=4 sw=4 tw=80 et ft=c: */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */