4 convert.im - image conversions
8 i_convert(outimage, srcimage, coeff, outchans, inchans)
12 Converts images from one format to another, typically in this case for
13 converting from RGBA to greyscale and back.
23 /* channels to copy */
25 int from[MAXCHANNELS];
28 /* channels to zero */
30 int zero[MAXCHANNELS];
32 /* channels to set to maxsample */
38 is_channel_copy(i_img *im, const double *coeff,
39 int outchan, int inchan,
40 struct chan_copy *info);
43 convert_via_copy(i_img *im, i_img *src, struct chan_copy *info);
46 =item i_convert(src, coeff, outchan, inchan)
48 Converts the image src into another image.
50 coeff contains the co-efficients of an outchan x inchan matrix, for
53 coeff[0], coeff[1] ...
54 im[x,y] = [ coeff[inchan], coeff[inchan+1]... ] * [ src[x,y], 1]
55 ... coeff[inchan*outchan-1]
57 If im has the wrong number of channels or is the wrong size then
58 i_convert() will re-create it.
60 Now handles images with more than 8-bits/sample.
66 i_convert(i_img *src, const double *coeff, int outchan, int inchan) {
67 double work[MAXCHANNELS];
73 mm_log((1,"i_convert(src %p, coeff %p,outchan %d, inchan %d)\n",im,src, coeff,outchan, inchan));
78 if (ilimit > src->channels)
79 ilimit = src->channels;
80 if (outchan > MAXCHANNELS) {
81 i_push_error(0, "cannot have outchan > MAXCHANNELS");
85 if (src->type == i_direct_type) {
86 struct chan_copy info;
87 im = i_sametype_chans(src, src->xsize, src->ysize, outchan);
89 if (is_channel_copy(src, coeff, outchan, inchan, &info)) {
90 return convert_via_copy(im, src, &info);
93 #code src->bits <= i_8_bits
96 /* we can always allocate a single scanline of i_color */
97 vals = mymalloc(sizeof(IM_COLOR) * src->xsize); /* checked 04Jul05 tonyc */
98 for (y = 0; y < src->ysize; ++y) {
99 IM_GLIN(src, 0, src->xsize, y, vals);
100 for (x = 0; x < src->xsize; ++x) {
101 for (j = 0; j < outchan; ++j) {
103 for (i = 0; i < ilimit; ++i) {
104 work[j] += coeff[i+inchan*j] * vals[x].channel[i];
107 work[j] += coeff[i+inchan*j] * IM_SAMPLE_MAX;
110 for (j = 0; j < outchan; ++j) {
112 vals[x].channel[j] = 0;
113 else if (work[j] >= IM_SAMPLE_MAX)
114 vals[x].channel[j] = IM_SAMPLE_MAX;
116 vals[x].channel[j] = work[j];
119 IM_PLIN(im, 0, src->xsize, y, vals);
132 im = i_img_pal_new(src->xsize, src->ysize, outchan,
135 /* just translate the color table */
136 count = i_colorcount(src);
137 outcount = i_colorcount(im);
138 /* color table allocated for image, so it must fit */
139 colors = mymalloc(count * sizeof(i_color)); /* check 04Jul05 tonyc */
140 i_getcolors(src, 0, colors, count);
141 for (index = 0; index < count; ++index) {
142 for (j = 0; j < outchan; ++j) {
144 for (i = 0; i < ilimit; ++i) {
145 work[j] += coeff[i+inchan*j] * colors[index].channel[i];
148 work[j] += coeff[i+inchan*j] * 255.9;
151 for (j = 0; j < outchan; ++j) {
153 colors[index].channel[j] = 0;
154 else if (work[j] >= 255)
155 colors[index].channel[j] = 255;
157 colors[index].channel[j] = work[j];
160 if (count < outcount) {
161 i_setcolors(im, 0, colors, count);
164 i_setcolors(im, 0, colors, outcount);
165 i_addcolors(im, colors, count-outcount);
167 /* and copy the indicies */
168 /* i_palidx is always unsigned char and will never be bigger than short
169 and since a line of 4-byte i_colors can fit then a line of i_palidx
171 vals = mymalloc(sizeof(i_palidx) * im->xsize); /* checked 4jul05 tonyc */
172 for (y = 0; y < im->ysize; ++y) {
173 i_gpal(src, 0, im->xsize, y, vals);
174 i_ppal(im, 0, im->xsize, y, vals);
184 =item is_channel_copy(coeff, outchan, inchan, chan_copy_info)
186 Test if the coefficients represent just copying channels around, and
187 initialize lists of the channels to copy, zero or set to max.
193 int is_channel_copy(i_img *im, const double *coeff, int outchan, int inchan,
194 struct chan_copy *info) {
195 int srcchan[MAXCHANNELS];
196 int onechan[MAXCHANNELS];
198 int ilimit = im->channels > inchan ? inchan : im->channels;
200 for (j = 0; j < outchan; ++j) {
205 for (j = 0; j < outchan; ++j) {
206 for (i = 0; i < ilimit; ++i) {
207 if (coeff[i+inchan*j] == 1.0) {
208 if (srcchan[j] != -1) {
209 /* from two or more channels, not a copy */
214 else if (coeff[i+inchan*j]) {
215 /* some other non-zero value, not a copy */
220 if (coeff[i+inchan*j] == 1.0) {
221 if (srcchan[j] != -1) {
227 else if (coeff[i+inchan*j]) {
228 /* some other non-zero value, not a copy */
234 /* build our working data structures */
235 info->copy_count = info->zero_count = info->one_count = 0;
236 for (j = 0; j < outchan; ++j) {
237 if (srcchan[j] != -1) {
238 info->from[info->copy_count] = srcchan[j];
239 info->to[info->copy_count] = j;
242 else if (onechan[j]) {
243 info->one[info->one_count] = j;
247 info->zero[info->zero_count] = j;
254 for (i = 0; i < info->copy_count; ++i) {
255 printf("From %d to %d\n", info->from[i], info->to[i]);
257 for (i = 0; i < info->one_count; ++i) {
258 printf("One %d\n", info->one[i]);
260 for (i = 0; i < info->zero_count; ++i) {
261 printf("Zero %d\n", info->zero[i]);
271 =item convert_via_copy(im, src, chan_copy_info)
273 Perform a convert that only requires channel copies.
279 convert_via_copy(i_img *im, i_img *src, struct chan_copy *info) {
280 #code src->bits <= i_8_bits
281 IM_COLOR *in_line = mymalloc(sizeof(IM_COLOR) * src->xsize);
282 IM_COLOR *out_line = mymalloc(sizeof(IM_COLOR) * src->xsize);
285 IM_COLOR *inp, *outp;
287 for (y = 0; y < src->ysize; ++y) {
288 IM_GLIN(src, 0, src->xsize, y, in_line);
292 for (x = 0; x < src->xsize; ++x) {
293 for (i = 0; i < info->copy_count; ++i) {
294 outp->channel[info->to[i]] = inp->channel[info->from[i]];
296 for (i = 0; i < info->one_count; ++i) {
297 outp->channel[info->one[i]] = IM_SAMPLE_MAX;
299 for (i = 0; i < info->zero_count; ++i) {
300 outp->channel[info->zero[i]] = 0;
306 IM_PLIN(im, 0, src->xsize, y, out_line);
325 Tony Cook <tony@develop-help.com>