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
RevLine 
[56]1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
[494]4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
[56]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
[512]13#include "common.h"
14
[481]15#include "pcxread.h"
16#include "specs.h"
[2]17
[549]18enum PCX_type { not_PCX, PCX_8, PCX_24 };
19
[2]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
[549]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
[2]51int write_PCX_header(FILE *fp)
52{
[124]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;
[17]57  write_uint16(fp,PCX_header.xmin);
[124]58  write_uint16(fp,PCX_header.ymin);
[17]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);
[2]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;
[124]66  write_uint16(fp,PCX_header.bytes_per_line);
67  write_uint16(fp,PCX_header.palette_type);
[2]68  if (!fwrite(PCX_header.filter,1,58,fp)) return 0;
69  return 1;
70}
71
[549]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
[39]146void write_PCX(image *im, palette *pal, char const *filename)
[2]147{
148  FILE *fp=fopen(filename,"wb");
[124]149  if (!fp)
[2]150    return ;
[124]151
152  PCX_header.manufactururer=10;
153  PCX_header.version=5;
[2]154  PCX_header.encoding=1;
155  PCX_header.bits_per_pixel=8;
156  PCX_header.xmin=0;
157  PCX_header.ymin=0;
[512]158  PCX_header.xmax=im->Size().x-1;
159  PCX_header.ymax=im->Size().y-1;
[2]160  PCX_header.hres=320;
161  PCX_header.vres=200;
162  PCX_header.reserved=0;
163  PCX_header.color_planes=1;
[512]164  PCX_header.bytes_per_line=im->Size().x;
[2]165  PCX_header.palette_type=0;
166  memset(PCX_header.filter,0,58);
167
[124]168  if (!write_PCX_header(fp))
[2]169  {
[523]170    fclose(fp);
171    return;
[2]172  }
[124]173
[2]174  int y,run_length,x;
[124]175  unsigned char *sl,code;
[512]176  for (y=0; y<im->Size().y; y++)
[2]177  {
178    sl=im->scan_line(y);
[512]179    for (x=0; x<im->Size().x; )
[2]180    {
[124]181      run_length=1;
[512]182      while (x+run_length<im->Size().x && sl[x]==sl[x+run_length])
[2]183        run_length++;
[124]184      if (run_length==1 && sl[x]<64)
185        fputc(sl[x],fp);
[2]186      else
187      {
188        if (run_length>=64)
[124]189      run_length=63;
190    code=0xc0 | run_length;
191    fputc(code,fp);
192    fputc(sl[x],fp);
[494]193
[124]194      }
[2]195      x+=run_length;
[124]196
197    }
[2]198  }
199  fputc(12,fp);  // note that there is a palette attached
200  fwrite(pal->addr(),1,256*3,fp);
[124]201  fclose(fp);
[2]202}
203
Note: See TracBrowser for help on using the repository browser.