1 /****************************\
2 * Bitmap mit Farbtabelle als *
3 * Graphik-Datei speichern *
4 * Autor: Gabriel Schmidt *
5 * (c) 1992 by MAXON-Computer *
6 * Modifiziert von Sebastian *
7 * Bieber, Dez. 1994 *
8 * -> Programmcode *
9 \****************************/
10
11 #include <errno.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16
17 #include "bitmfile.h"
18
19 /* --- (X) IMG-Implementation ----------------- */
20
21 #define IMG_COMPRESSED
22
23 typedef struct
24 {
25 UWORD img_version;
26 UWORD img_headlen;
27 UWORD img_nplanes;
28 UWORD img_patlen;
29 UWORD img_pixw;
30 UWORD img_pixh;
31 UWORD img_w;
32 UWORD img_h;
33 } IMG_HEADER;
34
35 typedef enum {NONE, SOLID0, SOLID1, PATRUN, BITSTR} IMG_MODE;
36
37 typedef UBYTE IMG_SOLID;
38
39 typedef enum { RGB=0, CMY=1, Pantone=2 } XIMG_COLMODEL;
40
41 typedef struct
42 {
43 ULONG img_ximg;
44 XIMG_COLMODEL img_colmodel;
45 } XIMG_HEADER;
46
47 typedef struct RGB XIMG_RGB;
48
49
bitmap_to_img(FILE_TYP typ,int ww,int wh,unsigned int pixw,unsigned int pixh,unsigned int planes,unsigned int colors,const char * filename,void (* get_color)(unsigned int colind,struct RGB * rgb),void (* get_pixel)(int x,int y,unsigned int * colind))50 int bitmap_to_img(FILE_TYP typ, int ww, int wh,
51 unsigned int pixw, unsigned int pixh,
52 unsigned int planes, unsigned int colors,
53 const char *filename,
54 void(*get_color)(unsigned int colind, struct RGB *rgb),
55 void(*get_pixel)(int x, int y, unsigned int *colind) )
56 {
57 int file, error, cnt;
58 IMG_HEADER header;
59 XIMG_HEADER xheader;
60 XIMG_RGB xrgb;
61 IMG_MODE mode;
62 UBYTE *line_buf, *write_buf;
63 register UBYTE *startpnt, *bufpnt;
64 unsigned int colind, line_len, line, bit;
65 register unsigned int byte;
66 register UBYTE count;
67
68 /* fill in (X) IMG-Header */
69
70 header.img_version = 1;
71 header.img_headlen = (UWORD) sizeof(header) /2;
72 if (typ == XIMG)
73 header.img_headlen += (UWORD)(sizeof(xheader)+colors*sizeof(xrgb))/2;
74
75 header.img_nplanes = planes;
76 header.img_patlen = 2;
77 header.img_pixw = pixw;
78 header.img_pixh = pixh;
79 header.img_w = ww;
80 header.img_h = wh;
81
82 xheader.img_ximg = XIMG_MAGIC;
83 xheader.img_colmodel= RGB;
84
85 /* calculate linelength, allocate buffer. */
86
87 line_len = (ww+7)/8;
88
89 line_buf = malloc((size_t)planes*line_len);
90 if (line_buf == NULL)
91 return(ENOMEM);
92
93 /* Worst case: the bufferd line could grow to max. 3 times the length */
94 /* of the original! */
95
96 write_buf = malloc((size_t)3*line_len);
97 if (write_buf == NULL)
98 {
99 free(line_buf);
100 return(ENOMEM);
101 };
102
103 /* open file */
104
105 file = open(filename, O_WRONLY | O_CREAT | O_TRUNC);
106 if (file<0)
107 {
108 error = errno;
109 free(line_buf);
110 free(write_buf);
111 return(error);
112 };
113
114 /* write Header */
115
116 if (write (file, &header, sizeof(header)) != sizeof(header) ||
117 (typ == XIMG && write (file, &xheader, sizeof(xheader) ) != sizeof(xheader)))
118 {
119 error = errno;
120 close(file);
121 free(line_buf);
122 free(write_buf);
123 return(error);
124 };
125
126 /* save the colortable if possible */
127
128 if ( typ == XIMG )
129 for (cnt=0; cnt<colors; cnt++)
130 {
131 get_color(cnt,&xrgb);
132 if (write(file,&xrgb,sizeof(xrgb)) != sizeof(xrgb))
133 {
134 error = errno;
135 close(file);
136 free(line_buf);
137 free(write_buf);
138 return(error);
139 };
140 };
141
142 /* And now line by line ... */
143
144 for (line=0; line<wh; line++)
145 {
146 /* get pixel, split it up and */
147 /* store it as planes in buffer */
148
149 for (byte=0; byte<line_len; byte++)
150 {
151 for (cnt=0; cnt<planes; cnt++)
152 line_buf[cnt*line_len+byte] = 0x00;
153
154 for (bit=0; bit<8; bit++)
155 {
156 if (8*byte+bit < ww)
157 get_pixel(8*byte+bit, line, &colind);
158
159 for (cnt=0; cnt<planes; cnt++)
160 {
161 line_buf[cnt*line_len+byte] <<= 1;
162 line_buf[cnt*line_len+byte] |= colind & 0x01;
163 colind >>= 1;
164 };
165 };
166 };
167
168 /* compress bitstrings in buffer */
169 /* and write it to file */
170
171 for (cnt=0; cnt<planes; cnt++)
172 {
173 /* Bitstringpointer to start of plane */
174
175 startpnt = &line_buf[cnt*line_len];
176 bufpnt = write_buf;
177
178 while (startpnt < &line_buf[(cnt+1)*line_len])
179 {
180 /*********************************************/
181 /* Which _new_ compression-mode "fits" the */
182 /* the current byte? */
183 /* Note: the compressing modes get choosen */
184 /* "positive". The non compressing BITSTR- */
185 /* mode is choosen only if nothing else */
186 /* "fits" ... */
187 /*********************************************/
188
189 switch (*startpnt)
190 {
191 case 0x00:
192 mode = SOLID0;
193 break;
194 case 0xFF:
195 mode = SOLID1;
196 break;
197 default:
198 if ( startpnt < &line_buf[(cnt+1)*line_len-3] &&
199 *(startpnt) == *(startpnt+2) &&
200 *(startpnt+1) == *(startpnt+3) )
201 mode = PATRUN;
202 else
203 mode = BITSTR;
204 };
205
206 /************************************************/
207 /* The mode is choosen, now work with it. */
208 /* The compressing modi stay current as long as */
209 /* possible. */
210 /************************************************/
211
212 count = 0;
213
214 switch (mode)
215 {
216 case SOLID0:
217 while ( (startpnt < &line_buf[(cnt+1)*line_len]) &&
218 (*(startpnt)==0x00) &&
219 (count < 0x7F) )
220 {
221 startpnt++;
222 count++;
223 };
224 *(bufpnt++) = count;
225 break;
226
227 case SOLID1:
228 while ( (startpnt < &line_buf[(cnt+1)*line_len]) &&
229 (*(startpnt)==0xFF) &&
230 (count < 0x7F) )
231 {
232 startpnt++;
233 count++;
234 };
235 *(bufpnt++) = 0x80 | count;
236 break;
237
238 case PATRUN:
239 *(bufpnt++) = 0x00;
240 startpnt += 2;
241 count = 1;
242 while ( startpnt < &line_buf[(cnt+1)*line_len-1] &&
243 *(startpnt) == *(startpnt-2) &&
244 *(startpnt+1) == *(startpnt-1) &&
245 (count < 0xFF) )
246 {
247 count++;
248 startpnt += 2;
249 };
250 *(bufpnt++) = count;
251 *(bufpnt++) = *(startpnt-2);
252 *(bufpnt++) = *(startpnt-1);
253 break;
254
255 /************************************************/
256 /* The while Condition is ment as follows: */
257 /* */
258 /* while ( NOT(2-Byte-Solidrun possible) && */
259 /* NOT(6-Byte-Patternrun possible) && */
260 /* count < 0xFF && */
261 /* still Bytes remaining ) */
262 /* */
263 /* As soon as a _compressing_ alternative shows */
264 /* up, BITSTR gets cancelled! */
265 /************************************************/
266
267 case BITSTR:
268 *(bufpnt++) = 0x80;
269 while ( !(((startpnt+count)<&line_buf[(cnt+1)*line_len-1])&&
270 (((*(startpnt+count)==0xFF) && (*(startpnt+count+1)==0xFF))||
271 ((*(startpnt+count)==0x00) && (*(startpnt+count+1)==0x00)))) &&
272 !(((startpnt+count)<&line_buf[(cnt+1)*line_len-5])&&
273 (*(startpnt+count) == *(startpnt+count+2))&&
274 (*(startpnt+count+1) == *(startpnt+count+3))&&
275 (*(startpnt+count) == *(startpnt+count+4))&&
276 (*(startpnt+count+1) == *(startpnt+count+5))) &&
277 (count < 0xFF) &&
278 ((startpnt+count) < &line_buf[(cnt+1)*line_len]) )
279 count++;
280 *(bufpnt++) = count;
281 for(; count>0; count--)
282 *(bufpnt++) = *(startpnt++);
283 break;
284 };
285 };
286
287 if (write(file,write_buf,bufpnt-write_buf) != (bufpnt-write_buf))
288 {
289 error = errno;
290 close(file);
291 free(line_buf);
292 free(write_buf);
293 return(error);
294 };
295
296 };
297 };
298
299 /*close file, free buffer. */
300
301 close(file);
302 free(line_buf);
303 free(write_buf);
304 return(0);
305
306 }
307
308 /*---filetype-dispatcher--------------------*/
309
get_file_ext(FILE_TYP typ)310 const char *get_file_ext(FILE_TYP typ)
311 {
312 switch (typ)
313 {
314 case IMG:
315 case XIMG:
316 return("IMG");
317 default:
318 return("");
319 };
320 }
321
322
bitmap_to_file(FILE_TYP typ,int ww,int wh,unsigned int pwx,unsigned int pwy,unsigned int planes,unsigned int colors,const char * filename,void (* get_color)(unsigned int colind,struct RGB * rgb),void (* get_pixel)(int x,int y,unsigned int * colind))323 int bitmap_to_file(FILE_TYP typ, int ww, int wh,
324 unsigned int pwx, unsigned int pwy,
325 unsigned int planes, unsigned int colors,
326 const char *filename,
327 void (*get_color)(unsigned int colind, struct RGB *rgb),
328 void (*get_pixel)(int x, int y, unsigned int *colind))
329 {
330
331 switch (typ)
332 {
333 case IMG:
334 case XIMG:
335 return(bitmap_to_img(typ,ww,wh,pwx,pwy,planes,colors,filename,get_color,get_pixel));
336 default:
337 return(-1);
338 };
339 }
340
341