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

Last change on this file since 90 was 56, checked in by Sam Hocevar, 12 years ago
  • Add licensing terms to most C / C++ files (Ref #5).
File size: 5.5 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *
5 *  This software was released into the Public Domain. As with most public
6 *  domain software, no warranty is made or implied by Crack dot Com or
7 *  Jonathan Clark.
8 */
9
10#include "config.h"
11
12#include "pcxread.hpp"
13#include "specs.hpp"
14
15struct PCX_header_type
16{
17  char manufactururer,version,encoding,bits_per_pixel;
18  short xmin,ymin,xmax,ymax,hres,vres;
19  char palette[48];
20  char reserved,color_planes;
21  short bytes_per_line,palette_type;
22  char filter[58];
23} PCX_header;
24
25int read_PCX_header(FILE *fp)
26{
27  if (!fread(&PCX_header.manufactururer,1,1,fp)) return 0; 
28  if (!fread(&PCX_header.version,1,1,fp)) return 0; 
29  if (!fread(&PCX_header.encoding,1,1,fp)) return 0; 
30  if (!fread(&PCX_header.bits_per_pixel,1,1,fp)) return 0; 
31  PCX_header.xmin=read_uint16(fp);
32  PCX_header.ymin=read_uint16(fp); 
33  PCX_header.xmax=read_uint16(fp);
34  PCX_header.ymax=read_uint16(fp);
35  PCX_header.hres=read_uint16(fp);
36  PCX_header.vres=read_uint16(fp);
37  if (!fread(PCX_header.palette,1,48,fp)) return 0;
38  if (!fread(&PCX_header.reserved,1,1,fp)) return 0;
39  if (!fread(&PCX_header.color_planes,1,1,fp)) return 0;
40  PCX_header.bytes_per_line=read_uint16(fp);
41  PCX_header.palette_type=read_uint16(fp);
42  if (!fread(PCX_header.filter,1,58,fp)) return 0;
43  return 1;
44}
45
46int write_PCX_header(FILE *fp)
47{
48  if (!fwrite(&PCX_header.manufactururer,1,1,fp)) return 0; 
49  if (!fwrite(&PCX_header.version,1,1,fp)) return 0; 
50  if (!fwrite(&PCX_header.encoding,1,1,fp)) return 0; 
51  if (!fwrite(&PCX_header.bits_per_pixel,1,1,fp)) return 0; 
52  write_uint16(fp,PCX_header.xmin);
53  write_uint16(fp,PCX_header.ymin); 
54  write_uint16(fp,PCX_header.xmax);
55  write_uint16(fp,PCX_header.ymax);
56  write_uint16(fp,PCX_header.hres);
57  write_uint16(fp,PCX_header.vres);
58  if (!fwrite(PCX_header.palette,1,48,fp)) return 0;
59  if (!fwrite(&PCX_header.reserved,1,1,fp)) return 0;
60  if (!fwrite(&PCX_header.color_planes,1,1,fp)) return 0;
61  write_uint16(fp,PCX_header.bytes_per_line);
62  write_uint16(fp,PCX_header.palette_type);
63  if (!fwrite(PCX_header.filter,1,58,fp)) return 0;
64  return 1;
65}
66
67
68
69PCX_type PCX_file_type(char const *filename)
70{
71  FILE *fp=fopen(filename,"rb"); 
72  if (!fp)
73  { set_error(imREAD_ERROR); 
74    return not_PCX;
75  }
76 
77  if (!read_PCX_header(fp))     
78  {
79    fclose(fp);   
80    set_error(imREAD_ERROR); 
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
120
121image24 *read_PCX24(char const *filename)
122{
123  if (PCX_file_type(filename)!=PCX_24) return NULL; 
124  FILE *fp=fopen(filename,"rb");
125  read_PCX_header(fp); 
126  image24 *im=new image24(PCX_header.xmax-PCX_header.xmin+1,
127                          PCX_header.ymax-PCX_header.ymin+1);
128  int y;
129  for (y=0;y<im->height();y++)
130  {
131    read_PCX_line(fp,im->scan_line(y),3,PCX_header.bytes_per_line);
132    read_PCX_line(fp,im->scan_line(y)+1,3,PCX_header.bytes_per_line);
133    read_PCX_line(fp,im->scan_line(y)+2,3,PCX_header.bytes_per_line);   
134  }
135  fclose(fp);
136  return im; 
137}
138
139image *read_PCX(char const *filename, palette *&pal)
140{
141  if (PCX_file_type(filename)!=PCX_8) return NULL; 
142  FILE *fp=fopen(filename,"rb");
143  read_PCX_header(fp);
144 
145  image *im=new image(PCX_header.xmax-PCX_header.xmin+1,
146                      PCX_header.ymax-PCX_header.ymin+1);
147  int y;
148  for (y=0;y<im->height();y++)
149    read_PCX_line(fp,im->scan_line(y),1,PCX_header.bytes_per_line);
150  unsigned char palette_confirm; 
151  if (!fread(&palette_confirm,1,1,fp) || palette_confirm!=12)
152  {   
153    pal=new palette;
154    pal->defaults();
155  }
156  else
157  {
158    pal=new palette;
159    fread(pal->addr(),1,256*3,fp);
160  }
161  fclose(fp);
162  return im; 
163
164
165void write_PCX(image *im, palette *pal, char const *filename)
166{
167  FILE *fp=fopen(filename,"wb");
168  if (!fp)
169  {
170    set_error(imWRITE_ERROR);
171    return ;
172  }
173 
174 
175  PCX_header.manufactururer=10; 
176  PCX_header.version=5; 
177  PCX_header.encoding=1;
178  PCX_header.bits_per_pixel=8;
179  PCX_header.xmin=0;
180  PCX_header.ymin=0;
181  PCX_header.xmax=im->width()-1;
182  PCX_header.ymax=im->height()-1;
183  PCX_header.hres=320;
184  PCX_header.vres=200;
185  PCX_header.reserved=0;
186  PCX_header.color_planes=1;
187  PCX_header.bytes_per_line=im->width();
188  PCX_header.palette_type=0;
189  memset(PCX_header.filter,0,58);
190
191
192  if (!write_PCX_header(fp))
193  {
194    set_error( imWRITE_ERROR);
195    return ; 
196  }
197 
198  int y,run_length,x;
199  unsigned char *sl,code; 
200  for (y=0;y<im->height();y++)
201  {
202    sl=im->scan_line(y);
203    for (x=0;x<im->width();)
204    {
205      run_length=1;     
206      while (x+run_length<im->width() && sl[x]==sl[x+run_length])
207        run_length++;
208      if (run_length==1 && sl[x]<64)
209        fputc(sl[x],fp);     
210      else
211      {
212        if (run_length>=64)
213          run_length=63;
214        code=0xc0 | run_length;
215        fputc(code,fp);
216        fputc(sl[x],fp);
217       
218      }     
219      x+=run_length;
220     
221    }   
222  }
223  fputc(12,fp);  // note that there is a palette attached
224  fwrite(pal->addr(),1,256*3,fp);
225  fclose(fp);   
226}
227
228
229
Note: See TracBrowser for help on using the repository browser.