~ubuntu-branches/ubuntu/intrepid/nethack/intrepid

« back to all changes in this revision

Viewing changes to win/gem/bitmfile.c

  • Committer: Bazaar Package Importer
  • Author(s): Joshua Kwan
  • Date: 2004-04-28 22:20:28 UTC
  • Revision ID: james.westby@ubuntu.com-20040428222028-xxg55fuf5dxiaogu
Tags: upstream-3.4.3
ImportĀ upstreamĀ versionĀ 3.4.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
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
 
 
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
 
 
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