source: abuse/trunk/src/imlib/pcxread.cpp @ 549

Last change on this file since 549 was 549, checked in by Sam Hocevar, 11 years ago

imlib: bring back the old PCX reading code.

File size: 4.8 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com or
8 *  Jonathan Clark.
9 */
10
11#include "config.h"
12
13#include "common.h"
14
15#include "pcxread.h"
16#include "specs.h"
17
18enum PCX_type { not_PCX, PCX_8, PCX_24 };
19
20struct PCX_header_type
21{
22  char manufactururer,version,encoding,bits_per_pixel;
23  short xmin,ymin,xmax,ymax,hres,vres;
24  char palette[48];
25  char reserved,color_planes;
26  short bytes_per_line,palette_type;
27  char filter[58];
28} PCX_header;
29
30int read_PCX_header(FILE *fp)
31{
32  if (!fread(&PCX_header.manufactururer,1,1,fp)) return 0;
33  if (!fread(&PCX_header.version,1,1,fp)) return 0;
34  if (!fread(&PCX_header.encoding,1,1,fp)) return 0;
35  if (!fread(&PCX_header.bits_per_pixel,1,1,fp)) return 0;
36  PCX_header.xmin=read_uint16(fp);
37  PCX_header.ymin=read_uint16(fp);
38  PCX_header.xmax=read_uint16(fp);
39  PCX_header.ymax=read_uint16(fp);
40  PCX_header.hres=read_uint16(fp);
41  PCX_header.vres=read_uint16(fp);
42  if (!fread(PCX_header.palette,1,48,fp)) return 0;
43  if (!fread(&PCX_header.reserved,1,1,fp)) return 0;
44  if (!fread(&PCX_header.color_planes,1,1,fp)) return 0;
45  PCX_header.bytes_per_line=read_uint16(fp);
46  PCX_header.palette_type=read_uint16(fp);
47  if (!fread(PCX_header.filter,1,58,fp)) return 0;
48  return 1;
49}
50
51int write_PCX_header(FILE *fp)
52{
53  if (!fwrite(&PCX_header.manufactururer,1,1,fp)) return 0;
54  if (!fwrite(&PCX_header.version,1,1,fp)) return 0;
55  if (!fwrite(&PCX_header.encoding,1,1,fp)) return 0;
56  if (!fwrite(&PCX_header.bits_per_pixel,1,1,fp)) return 0;
57  write_uint16(fp,PCX_header.xmin);
58  write_uint16(fp,PCX_header.ymin);
59  write_uint16(fp,PCX_header.xmax);
60  write_uint16(fp,PCX_header.ymax);
61  write_uint16(fp,PCX_header.hres);
62  write_uint16(fp,PCX_header.vres);
63  if (!fwrite(PCX_header.palette,1,48,fp)) return 0;
64  if (!fwrite(&PCX_header.reserved,1,1,fp)) return 0;
65  if (!fwrite(&PCX_header.color_planes,1,1,fp)) return 0;
66  write_uint16(fp,PCX_header.bytes_per_line);
67  write_uint16(fp,PCX_header.palette_type);
68  if (!fwrite(PCX_header.filter,1,58,fp)) return 0;
69  return 1;
70}
71
72PCX_type PCX_file_type(char const *filename)
73{
74  FILE *fp=fopen(filename,"rb");
75  if (!fp)
76    return not_PCX;
77
78  if (!read_PCX_header(fp))
79  {
80    fclose(fp);
81    return not_PCX;
82  }
83  fclose(fp);
84  if (PCX_header.manufactururer!=10)
85    return not_PCX;
86  if (PCX_header.color_planes==3 && PCX_header.bits_per_pixel==8)
87    return PCX_24;
88  else if (PCX_header.color_planes==1 && PCX_header.bits_per_pixel==8)
89    return PCX_8;
90  else return not_PCX;
91}
92
93void read_PCX_line(FILE *fp, unsigned char *start, short skip, int width)
94{
95  int c,n=0,i;
96
97  do
98  {
99    c=fgetc(fp)&0xff;
100    if ((c&0xc0)==0xc0)
101    {
102      i=c&0x3f;
103      c=fgetc(fp);
104      while (i--)
105      {
106    *start=c;
107    start+=skip;
108        n++;
109      }
110    }
111    else
112    {
113      *start=c;
114      start+=skip;
115      n++;
116    }
117  } while (n<width);
118}
119
120image *read_PCX(char const *filename, palette *&pal)
121{
122  if (PCX_file_type(filename)!=PCX_8) return NULL;
123  FILE *fp=fopen(filename,"rb");
124  read_PCX_header(fp);
125
126  image *im=new image(vec2i(PCX_header.xmax-PCX_header.xmin+1,
127                            PCX_header.ymax-PCX_header.ymin+1));
128  int y;
129  for (y=0;y<im->Size().y;y++)
130    read_PCX_line(fp,im->scan_line(y),1,PCX_header.bytes_per_line);
131  unsigned char palette_confirm;
132  if (!fread(&palette_confirm,1,1,fp) || palette_confirm!=12)
133  {
134    pal=new palette;
135    pal->defaults();
136  }
137  else
138  {
139    pal=new palette;
140    fread(pal->addr(),1,256*3,fp);
141  }
142  fclose(fp);
143  return im;
144}
145
146void write_PCX(image *im, palette *pal, char const *filename)
147{
148  FILE *fp=fopen(filename,"wb");
149  if (!fp)
150    return ;
151
152  PCX_header.manufactururer=10;
153  PCX_header.version=5;
154  PCX_header.encoding=1;
155  PCX_header.bits_per_pixel=8;
156  PCX_header.xmin=0;
157  PCX_header.ymin=0;
158  PCX_header.xmax=im->Size().x-1;
159  PCX_header.ymax=im->Size().y-1;
160  PCX_header.hres=320;
161  PCX_header.vres=200;
162  PCX_header.reserved=0;
163  PCX_header.color_planes=1;
164  PCX_header.bytes_per_line=im->Size().x;
165  PCX_header.palette_type=0;
166  memset(PCX_header.filter,0,58);
167
168  if (!write_PCX_header(fp))
169  {
170    fclose(fp);
171    return;
172  }
173
174  int y,run_length,x;
175  unsigned char *sl,code;
176  for (y=0; y<im->Size().y; y++)
177  {
178    sl=im->scan_line(y);
179    for (x=0; x<im->Size().x; )
180    {
181      run_length=1;
182      while (x+run_length<im->Size().x && sl[x]==sl[x+run_length])
183        run_length++;
184      if (run_length==1 && sl[x]<64)
185        fputc(sl[x],fp);
186      else
187      {
188        if (run_length>=64)
189      run_length=63;
190    code=0xc0 | run_length;
191    fputc(code,fp);
192    fputc(sl[x],fp);
193
194      }
195      x+=run_length;
196
197    }
198  }
199  fputc(12,fp);  // note that there is a palette attached
200  fwrite(pal->addr(),1,256*3,fp);
201  fclose(fp);
202}
203
Note: See TracBrowser for help on using the repository browser.