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 | ||
8d14daab TC |
73 | mm_log((1, "i_readraw(ig %p,x %" i_DF ",y %" i_DF ",datachannels %d,storechannels %d,intrl %d)\n", |
74 | ig, i_DFc(x), i_DFc(y), datachannels, storechannels, intrl)); | |
500888da TC |
75 | |
76 | if (intrl != 0 && intrl != 1) { | |
77 | i_push_error(0, "raw_interleave must be 0 or 1"); | |
78 | return NULL; | |
79 | } | |
80 | if (storechannels < 1 || storechannels > 4) { | |
81 | i_push_error(0, "raw_storechannels must be between 1 and 4"); | |
82 | return NULL; | |
83 | } | |
02d1d628 | 84 | |
895dbd34 | 85 | im = i_img_empty_ch(NULL,x,y,storechannels); |
50dc291e TC |
86 | if (!im) |
87 | return NULL; | |
02d1d628 | 88 | |
895dbd34 AMH |
89 | inbuflen = im->xsize*datachannels; |
90 | ilbuflen = inbuflen; | |
91 | exbuflen = im->xsize*storechannels; | |
92 | inbuffer = (unsigned char*)mymalloc(inbuflen); | |
8d14daab TC |
93 | mm_log((1,"inbuflen: %ld, ilbuflen: %ld, exbuflen: %ld.\n", |
94 | (long)inbuflen, (long)ilbuflen, (long)exbuflen)); | |
02d1d628 | 95 | |
5473b91d AMH |
96 | if (intrl==0) ilbuffer = inbuffer; |
97 | else ilbuffer=mymalloc(inbuflen); | |
02d1d628 | 98 | |
5473b91d AMH |
99 | if (datachannels==storechannels) exbuffer=ilbuffer; |
100 | else exbuffer= mymalloc(exbuflen); | |
101 | ||
02d1d628 | 102 | k=0; |
5473b91d | 103 | while( k<im->ysize ) { |
6d5c85a2 | 104 | rc = i_io_read(ig, inbuffer, inbuflen); |
5f8f8e17 TC |
105 | if (rc != inbuflen) { |
106 | if (rc < 0) | |
107 | i_push_error(0, "error reading file"); | |
108 | else | |
109 | i_push_error(0, "premature end of file"); | |
110 | i_img_destroy(im); | |
111 | myfree(inbuffer); | |
112 | if (intrl != 0) myfree(ilbuffer); | |
113 | if (datachannels != storechannels) myfree(exbuffer); | |
114 | return NULL; | |
115 | } | |
02d1d628 AMH |
116 | interleave(inbuffer,ilbuffer,im->xsize,datachannels); |
117 | expandchannels(ilbuffer,exbuffer,im->xsize,datachannels,storechannels); | |
5473b91d | 118 | /* FIXME: Do we ever want to save to a virtual image? */ |
faa9b3e7 | 119 | memcpy(&(im->idata[im->xsize*storechannels*k]),exbuffer,exbuflen); |
02d1d628 AMH |
120 | k++; |
121 | } | |
122 | ||
123 | myfree(inbuffer); | |
5473b91d AMH |
124 | if (intrl != 0) myfree(ilbuffer); |
125 | if (datachannels != storechannels) myfree(exbuffer); | |
50dc291e TC |
126 | |
127 | i_tags_add(&im->tags, "i_format", 0, "raw", -1, 0); | |
128 | ||
02d1d628 AMH |
129 | return im; |
130 | } | |
131 | ||
132 | ||
133 | ||
134 | undef_int | |
895dbd34 | 135 | i_writeraw_wiol(i_img* im, io_glue *ig) { |
8d14daab | 136 | ssize_t rc; |
faa9b3e7 | 137 | |
faa9b3e7 | 138 | i_clear_error(); |
895dbd34 | 139 | mm_log((1,"writeraw(im %p,ig %p)\n", im, ig)); |
02d1d628 AMH |
140 | |
141 | if (im == NULL) { mm_log((1,"Image is empty\n")); return(0); } | |
faa9b3e7 | 142 | if (!im->virtual) { |
6d5c85a2 | 143 | rc = i_io_write(ig,im->idata,im->bytes); |
5473b91d | 144 | if (rc != im->bytes) { |
faa9b3e7 TC |
145 | i_push_error(errno, "Could not write to file"); |
146 | mm_log((1,"i_writeraw: Couldn't write to file\n")); | |
147 | return(0); | |
148 | } | |
5473b91d | 149 | } else { |
faa9b3e7 TC |
150 | if (im->type == i_direct_type) { |
151 | /* just save it as 8-bits, maybe support saving higher bit count | |
152 | raw images later */ | |
8d14daab | 153 | size_t line_size = im->xsize * im->channels; |
faa9b3e7 | 154 | unsigned char *data = mymalloc(line_size); |
a73aeb5f | 155 | |
8d14daab | 156 | i_img_dim y = 0; |
a73aeb5f AMH |
157 | rc = line_size; |
158 | while (rc == line_size && y < im->ysize) { | |
159 | i_gsamp(im, 0, im->xsize, y, data, NULL, im->channels); | |
6d5c85a2 | 160 | rc = i_io_write(ig, data, line_size); |
a73aeb5f | 161 | ++y; |
faa9b3e7 TC |
162 | } |
163 | if (rc != line_size) { | |
164 | i_push_error(errno, "write error"); | |
165 | return 0; | |
166 | } | |
a73aeb5f | 167 | myfree(data); |
5473b91d | 168 | } else { |
faa9b3e7 TC |
169 | /* paletted image - assumes the caller puts the palette somewhere |
170 | else | |
171 | */ | |
8d14daab | 172 | size_t line_size = sizeof(i_palidx) * im->xsize; |
faa9b3e7 | 173 | i_palidx *data = mymalloc(sizeof(i_palidx) * im->xsize); |
a73aeb5f | 174 | |
8d14daab | 175 | i_img_dim y = 0; |
a73aeb5f AMH |
176 | rc = line_size; |
177 | while (rc == line_size && y < im->ysize) { | |
178 | i_gpal(im, 0, im->xsize, y, data); | |
6d5c85a2 | 179 | rc = i_io_write(ig, data, line_size); |
a73aeb5f | 180 | ++y; |
faa9b3e7 | 181 | } |
a73aeb5f | 182 | myfree(data); |
faa9b3e7 TC |
183 | if (rc != line_size) { |
184 | i_push_error(errno, "write error"); | |
185 | return 0; | |
186 | } | |
187 | } | |
895dbd34 | 188 | } |
10461f9a | 189 | |
6d5c85a2 TC |
190 | if (i_io_close(ig)) |
191 | return 0; | |
10461f9a | 192 | |
02d1d628 AMH |
193 | return(1); |
194 | } |