By preferring access via the functions we can reduce the possibility
of incorrect access to the image data.
-If an image interface function pointer isn't implemented, it should be set to NULL rather than being left uninitialized. This is so that use of the ununsed pointer results in an immediate crash rather than possibly calling the wrong function and crashing at some later point.
+If an image interface function pointer isn't implemented, it should be
+set to NULL rather than being left uninitialized. This is so that use
+of the ununsed pointer results in an immediate crash rather than
+possibly calling the wrong function and crashing at some later point.
In a debug build of Imager the image interface functions should check
that the correct type of image pointer is being passed in. This means
--- /dev/null
+/*
+=head1 NAME
+
+ map.c - inplace image mapping and related functionality
+
+=head1 SYNOPSIS
+
+ i_map(srcimage, coeffs, outchans, inchans)
+
+=head1 DESCRIPTION
+
+Converts images from one format to another, typically in this case for
+converting from RGBA to greyscale and back.
+
+=over
+
+=cut
+*/
+
+#include "image.h"
+
+
+/*
+=item i_map(im, mapcount, maps, chmasks)
+
+maps im inplace into another image.
+
+ Each map is a unsigned char array of 256 entries, its corresponding
+ channel mask is the same numbered entry in the chmasks array.
+ If two maps apply to the same channel then the second one is used.
+ If no map applies to a channel then that channel is not altered.
+ mapcount is the number of maps.
+
+=cut
+*/
+
+void
+i_map(i_img *im, int mapcount, unsigned char (*maps)[256], unsigned int *chmasks) {
+ i_color *vals;
+ int x, y;
+ int mapno, i, ch;
+ unsigned int mask = 0;
+ unsigned char (**cmaps)[256];
+ int minset = -1, maxset;
+
+ mm_log((1,"i_map(im %p, mapcount %d, maps %p, chmasks %p)\n", im, mapcount, maps, chmasks));
+
+
+ for(mapno=0; mapno<mapcount; mapno++) mask |=chmasks[mapno];
+ if (!mask) return; /* nothing to do here */
+
+
+
+ for(i=0; i<im->channels; i++)
+ if (mask & (1<<i)) {
+ if (minset == -1) minset = i;
+ maxset = i;
+ }
+
+ cmaps = mymalloc(sizeof(unsigned char (*)[256])*im->channels);
+ memset(cmaps, 0, sizeof(unsigned char (*)[256])*im->channels);
+ for(mapno=0; mapno<mapcount; mapno++)
+ for(ch=0; ch<im->channels; ch++)
+ if (chmasks[i] & (1<<ch)) cmaps[ch] = &maps[mapno];
+
+ vals = mymalloc(sizeof(i_color) * im->xsize);
+ for (y = 0; y < im->ysize; ++y) {
+ i_glin(im, 0, im->xsize, y, vals);
+ for (x = 0; x < im->xsize; ++x) {
+ int lidx = x * im->channels;
+ for(ch = minset; ch<=maxset; ch++) {
+ if (!cmaps[ch]) continue;
+ vals[lidx].channel[ch] = (*cmaps[ch])[vals[lidx].channel[ch]];
+ }
+ }
+ i_plin(im, 0, im->xsize, y, vals);
+ }
+ myfree(cmaps);
+ myfree(vals);
+}
+
+/*
+=back
+
+=head1 SEE ALSO
+
+Imager(3)
+
+=head1 AUTHOR
+
+Arnar M. Hrafnkelsson <addi@umich.edu>
+
+=cut
+*/