]> git.imager.perl.org - imager.git/blob - convert.c
- add scaleX/scaleY to the method index and gives them some examples
[imager.git] / convert.c
1 /*
2 =head1 NAME
3
4   convert.c - image conversions
5
6 =head1 SYNOPSIS
7
8   i_convert(outimage, srcimage, coeff, 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_convert(im, src, coeff, outchan, inchan)
25
26 Converts the image src into another image.
27
28 coeff contains the co-efficients of an outchan x inchan matrix, for
29 each output pixel:
30
31               coeff[0], coeff[1] ...
32   im[x,y] = [ coeff[inchan], coeff[inchan+1]...        ] * [ src[x,y], 1]
33               ...              coeff[inchan*outchan-1]
34
35 If im has the wrong number of channels or is the wrong size then
36 i_convert() will re-create it.
37
38 Now handles images with more than 8-bits/sample.
39
40 =cut
41 */
42
43 int
44 i_convert(i_img *im, i_img *src, float *coeff, int outchan, int inchan) {
45   int x, y;
46   int i, j;
47   int ilimit;
48   double work[MAXCHANNELS];
49
50   mm_log((1,"i_convert(im %p, src, %p, coeff %p,outchan %d, inchan %d)\n",im,src, coeff,outchan, inchan));
51  
52   i_clear_error();
53
54   ilimit = inchan;
55   if (ilimit > src->channels)
56     ilimit = src->channels;
57   if (outchan > MAXCHANNELS) {
58     i_push_error(0, "cannot have outchan > MAXCHANNELS");
59     return 0;
60   }
61
62   if (im->type == i_direct_type || src->type == i_direct_type) {
63     /* first check the output image */
64     if (im->channels != outchan || im->xsize != src->xsize 
65         || im->ysize != src->ysize) {
66       i_img_exorcise(im);
67       i_img_empty_ch(im, src->xsize, src->ysize, outchan);
68     }
69     if (im->bits == i_8_bits && src->bits == i_8_bits) {
70       i_color *vals;
71       
72       vals = mymalloc(sizeof(i_color) * src->xsize);
73       for (y = 0; y < src->ysize; ++y) {
74         i_glin(src, 0, src->xsize, y, vals);
75         for (x = 0; x < src->xsize; ++x) {
76           for (j = 0; j < outchan; ++j) {
77             work[j] = 0;
78             for (i = 0; i < ilimit; ++i) {
79               work[j] += coeff[i+inchan*j] * vals[x].channel[i];
80             }
81             if (i < inchan) {
82               work[j] += coeff[i+inchan*j] * 255.9;
83             }
84           }
85           for (j = 0; j < outchan; ++j) {
86             if (work[j] < 0)
87               vals[x].channel[j] = 0;
88             else if (work[j] >= 256)
89               vals[x].channel[j] = 255;
90             else
91               vals[x].channel[j] = work[j];
92           }
93         }
94         i_plin(im, 0, src->xsize, y, vals);
95       }
96       myfree(vals);
97     }
98     else {
99       i_fcolor *vals;
100       
101       vals = mymalloc(sizeof(i_fcolor) * src->xsize);
102       for (y = 0; y < src->ysize; ++y) {
103         i_glinf(src, 0, src->xsize, y, vals);
104         for (x = 0; x < src->xsize; ++x) {
105           for (j = 0; j < outchan; ++j) {
106             work[j] = 0;
107             for (i = 0; i < ilimit; ++i) {
108               work[j] += coeff[i+inchan*j] * vals[x].channel[i];
109             }
110             if (i < inchan) {
111               work[j] += coeff[i+inchan*j];
112             }
113           }
114           for (j = 0; j < outchan; ++j) {
115             if (work[j] < 0)
116               vals[x].channel[j] = 0;
117             else if (work[j] >= 1)
118               vals[x].channel[j] = 1;
119             else
120               vals[x].channel[j] = work[j];
121           }
122         }
123         i_plinf(im, 0, src->xsize, y, vals);
124       }
125       myfree(vals);
126     }
127   }
128   else {
129     int count;
130     int outcount;
131     int index;
132     i_color *colors;
133     i_palidx *vals;
134
135     if (im->channels != outchan || im->xsize != src->xsize 
136         || im->ysize != src->ysize
137         || i_maxcolors(im) < i_colorcount(src)) {
138       i_img_exorcise(im);
139       i_img_pal_new_low(im, src->xsize, src->ysize, outchan, 
140                         i_maxcolors(src));
141     }
142     /* just translate the color table */
143     count = i_colorcount(src);
144     outcount = i_colorcount(im);
145     colors = mymalloc(count * sizeof(i_color));
146     i_getcolors(src, 0, colors, count);
147     for (index = 0; index < count; ++index) {
148       for (j = 0; j < outchan; ++j) {
149         work[j] = 0;
150         for (i = 0; i < ilimit; ++i) {
151           work[j] += coeff[i+inchan*j] * colors[index].channel[i];
152         }
153         if (i < inchan) {
154           work[j] += coeff[i+inchan*j] * 255.9;
155         }
156       }
157       for (j = 0; j < outchan; ++j) {
158         if (work[j] < 0)
159           colors[index].channel[j] = 0;
160         else if (work[j] >= 255)
161           colors[index].channel[j] = 255;
162         else
163           colors[index].channel[j] = work[j];
164       }
165     }
166     if (count < outcount) {
167       i_setcolors(im, 0, colors, count);
168     }
169     else {
170       i_setcolors(im, 0, colors, outcount);
171       i_addcolors(im, colors, count-outcount);
172     }
173     /* and copy the indicies */
174     vals = mymalloc(sizeof(i_palidx) * im->xsize);
175     for (y = 0; y < im->ysize; ++y) {
176       i_gpal(src, 0, im->xsize, y, vals);
177       i_ppal(im, 0, im->xsize, y, vals);
178     }
179     myfree(vals);
180     myfree(colors);
181   }
182
183   return 1;
184 }
185
186 /*
187 =back
188
189 =head1 SEE ALSO
190
191 Imager(3)
192
193 =head1 AUTHOR
194
195 Tony Cook <tony@develop-help.com>
196
197 =cut
198 */