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