Commit | Line | Data |
---|---|---|
92bda632 | 1 | #include "imager.h" |
02d1d628 | 2 | #include <stdio.h> |
895dbd34 | 3 | #include "iolayer.h" |
02d1d628 AMH |
4 | #ifndef _MSC_VER |
5 | #include <unistd.h> | |
6 | #endif | |
7 | #include <string.h> | |
faa9b3e7 | 8 | #include <errno.h> |
02d1d628 | 9 | |
895dbd34 | 10 | |
02d1d628 AMH |
11 | |
12 | /* | |
13 | ||
14 | Image loader for raw files. | |
15 | ||
16 | This is a barebones raw loader... | |
17 | ||
18 | fd: filedescriptor | |
19 | x: xsize | |
20 | y: ysize | |
21 | datachannels: the number of channels the file contains | |
22 | storechannels: the bitmap of channels we will read | |
23 | intrl: interlace flag, | |
24 | 0 = sample interleaving | |
25 | 1 = line interleaving | |
500888da | 26 | 2 = image interleaving (not implemented) |
02d1d628 AMH |
27 | |
28 | */ | |
29 | ||
5473b91d | 30 | static |
02d1d628 | 31 | void |
8d14daab TC |
32 | interleave(unsigned char *inbuffer,unsigned char *outbuffer,i_img_dim rowsize,int channels) { |
33 | i_img_dim ind,i; | |
34 | int ch; | |
5473b91d AMH |
35 | i=0; |
36 | if (inbuffer == outbuffer) return; /* Check if data is already in interleaved format */ | |
37 | for (ind=0; ind<rowsize; ind++) | |
38 | for (ch=0; ch<channels; ch++) | |
39 | outbuffer[i++] = inbuffer[rowsize*ch+ind]; | |
40 | } | |
41 | ||
42 | static | |
43 | void | |
44 | expandchannels(unsigned char *inbuffer, unsigned char *outbuffer, | |
8d14daab TC |
45 | i_img_dim xsize, int datachannels, int storechannels) { |
46 | i_img_dim x; | |
47 | int ch; | |
500888da TC |
48 | int copy_chans = storechannels > datachannels ? datachannels : storechannels; |
49 | if (inbuffer == outbuffer) | |
50 | return; /* Check if data is already in expanded format */ | |
51 | for(x = 0; x < xsize; x++) { | |
52 | for (ch = 0; ch < copy_chans; ch++) | |
53 | outbuffer[x*storechannels+ch] = inbuffer[x*datachannels+ch]; | |
54 | for (; ch < storechannels; ch++) | |
55 | outbuffer[x*storechannels+ch] = 0; | |
56 | } | |
02d1d628 AMH |
57 | } |
58 | ||
59 | i_img * | |
8d14daab | 60 | i_readraw_wiol(io_glue *ig, i_img_dim x, i_img_dim y, int datachannels, int storechannels, int intrl) { |
02d1d628 | 61 | i_img* im; |
8d14daab TC |
62 | ssize_t rc; |
63 | i_img_dim k; | |
5f8f8e17 | 64 | |
02d1d628 AMH |
65 | unsigned char *inbuffer; |
66 | unsigned char *ilbuffer; | |
67 | unsigned char *exbuffer; | |
68 | ||
8d14daab | 69 | size_t inbuflen,ilbuflen,exbuflen; |
02d1d628 | 70 | |
885e13c5 TC |
71 | i_clear_error(); |
72 | ||
895dbd34 | 73 | io_glue_commit_types(ig); |
8d14daab TC |
74 | mm_log((1, "i_readraw(ig %p,x %" i_DF ",y %" i_DF ",datachannels %d,storechannels %d,intrl %d)\n", |
75 | ig, i_DFc(x), i_DFc(y), datachannels, storechannels, intrl)); | |
500888da TC |
76 | |
77 | if (intrl != 0 && intrl != 1) { | |
78 | i_push_error(0, "raw_interleave must be 0 or 1"); | |
79 | return NULL; | |
80 | } | |
81 | if (storechannels < 1 || storechannels > 4) { | |
82 | i_push_error(0, "raw_storechannels must be between 1 and 4"); | |
83 | return NULL; | |
84 | } | |
02d1d628 | 85 | |
895dbd34 | 86 | im = i_img_empty_ch(NULL,x,y,storechannels); |
50dc291e TC |
87 | if (!im) |
88 | return NULL; | |
02d1d628 | 89 | |
895dbd34 AMH |
90 | inbuflen = im->xsize*datachannels; |
91 | ilbuflen = inbuflen; | |
92 | exbuflen = im->xsize*storechannels; | |
93 | inbuffer = (unsigned char*)mymalloc(inbuflen); | |
8d14daab TC |
94 | mm_log((1,"inbuflen: %ld, ilbuflen: %ld, exbuflen: %ld.\n", |
95 | (long)inbuflen, (long)ilbuflen, (long)exbuflen)); | |
02d1d628 | 96 | |
5473b91d AMH |
97 | if (intrl==0) ilbuffer = inbuffer; |
98 | else ilbuffer=mymalloc(inbuflen); | |
02d1d628 | 99 | |
5473b91d AMH |
100 | if (datachannels==storechannels) exbuffer=ilbuffer; |
101 | else exbuffer= mymalloc(exbuflen); | |
102 | ||
02d1d628 | 103 | k=0; |
5473b91d | 104 | while( k<im->ysize ) { |
895dbd34 | 105 | rc = ig->readcb(ig, inbuffer, inbuflen); |
5f8f8e17 TC |
106 | if (rc != inbuflen) { |
107 | if (rc < 0) | |
108 | i_push_error(0, "error reading file"); | |
109 | else | |
110 | i_push_error(0, "premature end of file"); | |
111 | i_img_destroy(im); | |
112 | myfree(inbuffer); | |
113 | if (intrl != 0) myfree(ilbuffer); | |
114 | if (datachannels != storechannels) myfree(exbuffer); | |
115 | return NULL; | |
116 | } | |
02d1d628 AMH |
117 | interleave(inbuffer,ilbuffer,im->xsize,datachannels); |
118 | expandchannels(ilbuffer,exbuffer,im->xsize,datachannels,storechannels); | |
5473b91d | 119 | /* FIXME: Do we ever want to save to a virtual image? */ |
faa9b3e7 | 120 | memcpy(&(im->idata[im->xsize*storechannels*k]),exbuffer,exbuflen); |
02d1d628 AMH |
121 | k++; |
122 | } | |
123 | ||
124 | myfree(inbuffer); | |
5473b91d AMH |
125 | if (intrl != 0) myfree(ilbuffer); |
126 | if (datachannels != storechannels) myfree(exbuffer); | |
50dc291e TC |
127 | |
128 | i_tags_add(&im->tags, "i_format", 0, "raw", -1, 0); | |
129 | ||
02d1d628 AMH |
130 | return im; |
131 | } | |
132 | ||
133 | ||
134 | ||
135 | undef_int | |
895dbd34 | 136 | i_writeraw_wiol(i_img* im, io_glue *ig) { |
8d14daab | 137 | ssize_t rc; |
faa9b3e7 | 138 | |
895dbd34 | 139 | io_glue_commit_types(ig); |
faa9b3e7 | 140 | i_clear_error(); |
895dbd34 | 141 | mm_log((1,"writeraw(im %p,ig %p)\n", im, ig)); |
02d1d628 AMH |
142 | |
143 | if (im == NULL) { mm_log((1,"Image is empty\n")); return(0); } | |
faa9b3e7 | 144 | if (!im->virtual) { |
5473b91d AMH |
145 | rc = ig->writecb(ig,im->idata,im->bytes); |
146 | if (rc != im->bytes) { | |
faa9b3e7 TC |
147 | i_push_error(errno, "Could not write to file"); |
148 | mm_log((1,"i_writeraw: Couldn't write to file\n")); | |
149 | return(0); | |
150 | } | |
5473b91d | 151 | } else { |
faa9b3e7 TC |
152 | if (im->type == i_direct_type) { |
153 | /* just save it as 8-bits, maybe support saving higher bit count | |
154 | raw images later */ | |
8d14daab | 155 | size_t line_size = im->xsize * im->channels; |
faa9b3e7 | 156 | unsigned char *data = mymalloc(line_size); |
a73aeb5f | 157 | |
8d14daab | 158 | i_img_dim y = 0; |
a73aeb5f AMH |
159 | rc = line_size; |
160 | while (rc == line_size && y < im->ysize) { | |
161 | i_gsamp(im, 0, im->xsize, y, data, NULL, im->channels); | |
162 | rc = ig->writecb(ig, data, line_size); | |
163 | ++y; | |
faa9b3e7 TC |
164 | } |
165 | if (rc != line_size) { | |
166 | i_push_error(errno, "write error"); | |
167 | return 0; | |
168 | } | |
a73aeb5f | 169 | myfree(data); |
5473b91d | 170 | } else { |
faa9b3e7 TC |
171 | /* paletted image - assumes the caller puts the palette somewhere |
172 | else | |
173 | */ | |
8d14daab | 174 | size_t line_size = sizeof(i_palidx) * im->xsize; |
faa9b3e7 | 175 | i_palidx *data = mymalloc(sizeof(i_palidx) * im->xsize); |
a73aeb5f | 176 | |
8d14daab | 177 | i_img_dim y = 0; |
a73aeb5f AMH |
178 | rc = line_size; |
179 | while (rc == line_size && y < im->ysize) { | |
180 | i_gpal(im, 0, im->xsize, y, data); | |
181 | rc = ig->writecb(ig, data, line_size); | |
182 | ++y; | |
faa9b3e7 | 183 | } |
a73aeb5f | 184 | myfree(data); |
faa9b3e7 TC |
185 | if (rc != line_size) { |
186 | i_push_error(errno, "write error"); | |
187 | return 0; | |
188 | } | |
189 | } | |
895dbd34 | 190 | } |
10461f9a TC |
191 | |
192 | ig->closecb(ig); | |
193 | ||
02d1d628 AMH |
194 | return(1); |
195 | } |