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

Last change on this file since 682 was 682, checked in by Sam Hocevar, 8 years ago

core: rename vec2i to ivec2 and update matrix.h from Lol Engine.

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