Added map.c which implements mapping images through tables.
[imager.git] / map.c
1 /*
2 =head1 NAME
3
4   map.c - inplace image mapping and related functionality
5
6 =head1 SYNOPSIS
7
8   i_map(srcimage, coeffs, outchans, inchans)
9
10 =head1 DESCRIPTION
11
12 Converts images from one format to another, typically in this case for
13 converting from RGBA to greyscale and back.
14
15 =over
16
17 =cut
18 */
19
20 #include "image.h"
21
22
23 /*
24 =item i_map(im, mapcount, maps, chmasks)
25
26 maps im inplace into another image.
27
28   Each map is a unsigned char array of 256 entries, its corresponding
29   channel mask is the same numbered entry in the chmasks array.
30   If two maps apply to the same channel then the second one is used.
31   If no map applies to a channel then that channel is not altered.
32   mapcount is the number of maps.
33
34 =cut
35 */
36
37 void
38 i_map(i_img *im, int mapcount, unsigned char (*maps)[256], unsigned int *chmasks) {
39   i_color *vals;
40   int x, y;
41   int mapno, i, ch;
42   unsigned int mask = 0;
43   unsigned char (**cmaps)[256];
44   int minset = -1, maxset;
45
46   mm_log((1,"i_map(im %p, mapcount %d, maps %p, chmasks %p)\n", im, mapcount, maps, chmasks));
47
48
49   for(mapno=0; mapno<mapcount; mapno++) mask |=chmasks[mapno];
50   if (!mask) return; /* nothing to do here */
51
52
53
54   for(i=0; i<im->channels; i++)
55     if (mask & (1<<i)) {
56       if (minset == -1) minset = i;
57       maxset = i;
58     }
59
60   cmaps = mymalloc(sizeof(unsigned char (*)[256])*im->channels);
61   memset(cmaps, 0, sizeof(unsigned char (*)[256])*im->channels);
62   for(mapno=0; mapno<mapcount; mapno++)
63     for(ch=0; ch<im->channels; ch++) 
64       if (chmasks[i] & (1<<ch)) cmaps[ch] = &maps[mapno];
65   
66   vals = mymalloc(sizeof(i_color) * im->xsize);
67   for (y = 0; y < im->ysize; ++y) {
68     i_glin(im, 0, im->xsize, y, vals);
69     for (x = 0; x < im->xsize; ++x) {
70       int lidx = x * im->channels;
71       for(ch = minset; ch<=maxset; ch++) {
72         if (!cmaps[ch]) continue;
73         vals[lidx].channel[ch] = (*cmaps[ch])[vals[lidx].channel[ch]];
74       }
75     }
76     i_plin(im, 0, im->xsize, y, vals);
77   }
78   myfree(cmaps);
79   myfree(vals);
80 }
81
82 /*
83 =back
84
85 =head1 SEE ALSO
86
87 Imager(3)
88
89 =head1 AUTHOR
90
91 Arnar M. Hrafnkelsson <addi@umich.edu>
92
93 =cut
94 */