df5df969838ccef5bd987173a866dbb2e2a0c825
[imager.git] / imgdouble.c
1 /*
2 =head1 NAME
3
4 imgdouble.c - implements double per sample images
5
6 =head1 SYNOPSIS
7
8   i_img *im = i_img_double_new(int x, int y, int channels);
9   # use like a normal image
10
11 =head1 DESCRIPTION
12
13 Implements double/sample images.
14
15 This basic implementation is required so that we have some larger 
16 sample image type to work with.
17
18 =over
19
20 =cut
21 */
22
23 #include "image.h"
24 #include "imagei.h"
25
26 static int i_ppix_ddoub(i_img *im, int x, int y, i_color *val);
27 static int i_gpix_ddoub(i_img *im, int x, int y, i_color *val);
28 static int i_glin_ddoub(i_img *im, int l, int r, int y, i_color *vals);
29 static int i_plin_ddoub(i_img *im, int l, int r, int y, i_color *vals);
30 static int i_ppixf_ddoub(i_img *im, int x, int y, i_fcolor *val);
31 static int i_gpixf_ddoub(i_img *im, int x, int y, i_fcolor *val);
32 static int i_glinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals);
33 static int i_plinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals);
34 static int i_gsamp_ddoub(i_img *im, int l, int r, int y, i_sample_t *samps, 
35                        int *chans, int chan_count);
36 static int i_gsampf_ddoub(i_img *im, int l, int r, int y, i_fsample_t *samps, 
37                         int *chans, int chan_count);
38
39 /*
40 =item IIM_base_16bit_direct
41
42 Base structure used to initialize a 16-bit/sample image.
43
44 Internal.
45
46 =cut
47 */
48 static i_img IIM_base_double_direct =
49 {
50   0, /* channels set */
51   0, 0, 0, /* xsize, ysize, bytes */
52   ~0, /* ch_mask */
53   i_double_bits, /* bits */
54   i_direct_type, /* type */
55   0, /* virtual */
56   NULL, /* idata */
57   { 0, 0, NULL }, /* tags */
58   NULL, /* ext_data */
59
60   i_ppix_ddoub, /* i_f_ppix */
61   i_ppixf_ddoub, /* i_f_ppixf */
62   i_plin_ddoub, /* i_f_plin */
63   i_plinf_ddoub, /* i_f_plinf */
64   i_gpix_ddoub, /* i_f_gpix */
65   i_gpixf_ddoub, /* i_f_gpixf */
66   i_glin_ddoub, /* i_f_glin */
67   i_glinf_ddoub, /* i_f_glinf */
68   i_gsamp_ddoub, /* i_f_gsamp */
69   i_gsampf_ddoub, /* i_f_gsampf */
70
71   NULL, /* i_f_gpal */
72   NULL, /* i_f_ppal */
73   NULL, /* i_f_addcolor */
74   NULL, /* i_f_getcolor */
75   NULL, /* i_f_colorcount */
76   NULL, /* i_f_findcolor */
77
78   NULL, /* i_f_destroy */
79 };
80
81 /*
82 =item i_img_double_new(int x, int y, int ch)
83
84 Creates a new double per sample image.
85
86 =cut
87 */
88 i_img *i_img_double_new_low(i_img *im, int x, int y, int ch) {
89   mm_log((1,"i_img_double_new(x %d, y %d, ch %d)\n", x, y, ch));
90   
91   *im = IIM_base_double_direct;
92   i_tags_new(&im->tags);
93   im->xsize = x;
94   im->ysize = y;
95   im->channels = ch;
96   im->bytes = x * y * ch * sizeof(double);
97   im->ext_data = NULL;
98   im->idata = mymalloc(im->bytes);
99   if (im->idata) {
100     memset(im->idata, 0, im->bytes);
101   }
102   else {
103     i_tags_destroy(&im->tags);
104     im = NULL;
105   }
106   
107   return im;
108 }
109
110 i_img *i_img_double_new(int x, int y, int ch) {
111   i_img *im;
112
113   im = mymalloc(sizeof(i_img));
114   if (im) {
115     if (!i_img_double_new_low(im, x, y, ch)) {
116       myfree(im);
117       im = NULL;
118     }
119   }
120   
121   mm_log((1, "(%p) <- i_img_double_new\n", im));
122   
123   return im;
124 }
125
126 static int i_ppix_ddoub(i_img *im, int x, int y, i_color *val) {
127   int off, ch;
128
129   if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize) 
130     return -1;
131
132   off = (x + y * im->xsize) * im->channels;
133   for (ch = 0; ch < im->channels; ++ch)
134     ((double*)im->idata)[off+ch] = Sample8ToF(val->channel[ch]);
135
136   return 0;
137 }
138
139 static int i_gpix_ddoub(i_img *im, int x, int y, i_color *val) {
140   int off, ch;
141
142   if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize) 
143     return -1;
144
145   off = (x + y * im->xsize) * im->channels;
146   for (ch = 0; ch < im->channels; ++ch)
147     val->channel[ch] = SampleFTo8(((double *)im->idata)[off+ch]);
148
149   return 0;
150 }
151
152 static int i_ppixf_ddoub(i_img *im, int x, int y, i_fcolor *val) {
153   int off, ch;
154
155   if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize) 
156     return -1;
157
158   off = (x + y * im->xsize) * im->channels;
159   for (ch = 0; ch < im->channels; ++ch)
160     ((double *)im->idata)[off+ch] = val->channel[ch];;
161
162   return 0;
163 }
164
165 static int i_gpixf_ddoub(i_img *im, int x, int y, i_fcolor *val) {
166   int off, ch;
167
168   if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize) 
169     return -1;
170
171   off = (x + y * im->xsize) * im->channels;
172   for (ch = 0; ch < im->channels; ++ch)
173     val->channel[ch] = ((double *)im->idata)[off+ch];
174
175   return 0;
176 }
177
178 static int i_glin_ddoub(i_img *im, int l, int r, int y, i_color *vals) {
179   int ch, count, i;
180   int off;
181   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
182     if (r > im->xsize)
183       r = im->xsize;
184     off = (l+y*im->xsize) * im->channels;
185     count = r - l;
186     for (i = 0; i < count; ++i) {
187       for (ch = 0; ch < im->channels; ++ch) {
188         vals[i].channel[ch] = SampleFTo8(((double *)im->idata)[off]);
189         ++off;
190       }
191     }
192     return count;
193   }
194   else {
195     return 0;
196   }
197 }
198
199 static int i_plin_ddoub(i_img *im, int l, int r, int y, i_color *vals) {
200   int ch, count, i;
201   int off;
202   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
203     if (r > im->xsize)
204       r = im->xsize;
205     off = (l+y*im->xsize) * im->channels;
206     count = r - l;
207     for (i = 0; i < count; ++i) {
208       for (ch = 0; ch < im->channels; ++ch) {
209         ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]);
210         ++off;
211       }
212     }
213     return count;
214   }
215   else {
216     return 0;
217   }
218 }
219
220 static int i_glinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals) {
221   int ch, count, i;
222   int off;
223   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
224     if (r > im->xsize)
225       r = im->xsize;
226     off = (l+y*im->xsize) * im->channels;
227     count = r - l;
228     for (i = 0; i < count; ++i) {
229       for (ch = 0; ch < im->channels; ++ch) {
230         vals[i].channel[ch] = ((double *)im->idata)[off];
231         ++off;
232       }
233     }
234     return count;
235   }
236   else {
237     return 0;
238   }
239 }
240
241 static int i_plinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals) {
242   int ch, count, i;
243   int off;
244   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
245     if (r > im->xsize)
246       r = im->xsize;
247     off = (l+y*im->xsize) * im->channels;
248     count = r - l;
249     for (i = 0; i < count; ++i) {
250       for (ch = 0; ch < im->channels; ++ch) {
251         ((double *)im->idata)[off] = vals[i].channel[ch];
252         ++off;
253       }
254     }
255     return count;
256   }
257   else {
258     return 0;
259   }
260 }
261
262 static int i_gsamp_ddoub(i_img *im, int l, int r, int y, i_sample_t *samps, 
263                        int *chans, int chan_count) {
264   int ch, count, i, w;
265   int off;
266
267   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
268     if (r > im->xsize)
269       r = im->xsize;
270     off = (l+y*im->xsize) * im->channels;
271     w = r - l;
272     count = 0;
273
274     if (chans) {
275       /* make sure we have good channel numbers */
276       for (ch = 0; ch < chan_count; ++ch) {
277         if (chans[ch] < 0 || chans[ch] >= im->channels) {
278           i_push_errorf(0, "No channel %d in this image", chans[ch]);
279           return 0;
280         }
281       }
282       for (i = 0; i < w; ++i) {
283         for (ch = 0; ch < chan_count; ++ch) {
284           *samps++ = SampleFTo8(((double *)im->idata)[off+chans[ch]]);
285           ++count;
286         }
287         off += im->channels;
288       }
289     }
290     else {
291       for (i = 0; i < w; ++i) {
292         for (ch = 0; ch < chan_count; ++ch) {
293           *samps++ = SampleFTo8(((double *)im->idata)[off+ch]);
294           ++count;
295         }
296         off += im->channels;
297       }
298     }
299
300     return count;
301   }
302   else {
303     return 0;
304   }
305 }
306
307 static int i_gsampf_ddoub(i_img *im, int l, int r, int y, i_fsample_t *samps, 
308                         int *chans, int chan_count) {
309   int ch, count, i, w;
310   int off;
311
312   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
313     if (r > im->xsize)
314       r = im->xsize;
315     off = (l+y*im->xsize) * im->channels;
316     w = r - l;
317     count = 0;
318
319     if (chans) {
320       /* make sure we have good channel numbers */
321       for (ch = 0; ch < chan_count; ++ch) {
322         if (chans[ch] < 0 || chans[ch] >= im->channels) {
323           i_push_errorf(0, "No channel %d in this image", chans[ch]);
324           return 0;
325         }
326       }
327       for (i = 0; i < w; ++i) {
328         for (ch = 0; ch < chan_count; ++ch) {
329           *samps++ = ((double *)im->idata)[off+chans[ch]];
330           ++count;
331         }
332         off += im->channels;
333       }
334     }
335     else {
336       for (i = 0; i < w; ++i) {
337         for (ch = 0; ch < chan_count; ++ch) {
338           *samps++ = ((double *)im->idata)[off+ch];
339           ++count;
340         }
341         off += im->channels;
342       }
343     }
344
345     return count;
346   }
347   else {
348     return 0;
349   }
350 }
351