source: golgotha/src/i4/loaders/bmp_load.cc @ 608

Last change on this file since 608 was 80, checked in by Sam Hocevar, 15 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 5.6 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "loaders/load.hh"
10#include "image/image.hh"
11
12#include "error/error.hh"
13#include "palette/pal.hh"
14#include "status/status.hh"
15#include "file/file.hh"
16#include "memory/malloc.hh"
17#include "error/error.hh"
18
19#include <string.h>
20#include <stdio.h>
21
22class i4_bmp_loader_class : public i4_image_loader_class
23{
24
25  public :
26  w16 get_short(w32 offset, void *data)
27  {
28    w8 buf[2];
29    buf[0]=*(((w8 *)data)+offset);
30    buf[1]=*(((w8 *)data)+offset+1);
31    return (buf[1]<<8)|buf[0];
32  }
33
34  w32 get_long(w32 offset, void *data)
35  {
36    w8 buf[4];
37    buf[0]=*(((w8 *)data)+offset);
38    buf[1]=*(((w8 *)data)+offset+1);
39    buf[2]=*(((w8 *)data)+offset+2);
40    buf[3]=*(((w8 *)data)+offset+3);
41    return (buf[3]<<24)|(buf[2]<<16)|(buf[1]<<8)|buf[0];
42  }
43
44
45  public :
46  virtual w16 max_header_size() { return 2; }
47  virtual i4_bool recognize_header(w8 *buf) { return (i4_bool)(buf[0]=='B' && buf[1]=='M'); }
48  virtual i4_image_class *load(i4_file_class *fp,
49                               i4_status_class *status)
50  {
51    void *buf[54];
52    if (fp->read(buf,54)!=54) return 0;
53    w32 width   =get_long (18,buf);
54
55    //width=(width+3)&(~3);
56
57    w32 fsize   =get_long (2,buf);
58    w32 offset  =get_long (10,buf);
59    w32 height  =get_long (22,buf);
60    w16 planes  =get_short(26,buf);
61    w16 bits    =get_short(28,buf);
62    w32 compress=get_long (30,buf);
63    w32 colors  =get_long (46,buf);
64
65
66    if (bits==8 && planes==1)
67    {
68      w32 pdata[256],i;
69
70      colors = (colors>0)? colors : 256;
71      memset(pdata,0,sizeof(pdata));
72      for (i=0;i<colors;i++)
73      {
74        w8 b[4];
75        fp->read(b,4);
76        pdata[i]=(b[2]<<16)|(b[1]<<8)|b[0];
77      }
78
79      i4_pixel_format fmt;
80      fmt.pixel_depth=I4_8BIT;
81      fmt.lookup=pdata;
82
83      const i4_pal *pal=i4_pal_man.register_pal(&fmt);
84      i4_image_class *im=i4_create_image(width,height,pal);
85     
86      if (compress==0)
87      {
88        int end_of_line_skip=(fsize-54-colors*4)/height - width;
89        fp->seek(offset);
90
91        for (i=0;i<height;i++) 
92        {
93          if (status)
94            status->update(i/(float)height);
95
96          w32 read_amount=fp->read((w8 *)im->data+(height-i-1)*width,width);
97          if (read_amount!=width)
98          {
99            i4_warning("bmp file short by %d scan_lines & %d bytes\n",
100                       height-i-1,
101                       width-read_amount);
102            delete im;
103            return 0;
104          }
105
106          if (end_of_line_skip)   // each row is 0-padded to a 4-byte boundary
107            fp->read(buf, end_of_line_skip);
108         
109        }
110        return im;
111      } else if (compress==1)
112      {
113        i4_bool done=i4_F;
114        w8 *d=(w8 *)im->data;
115        w32 x=0,y=height-1;
116
117        while (!done)
118        {
119          w8 pair[2];
120          fp->read(pair,2);
121          if (*pair==0)                   // escaped
122          {         
123            if (pair[1]==0)               // end of line
124            {
125              x=0;
126              y--;
127              d=(w8 *)im->data+y*width;
128
129              if (status)
130                status->update((height-y)/(float)height);
131
132
133            } else if (pair[1]==1)        // end of bitmap
134              done=i4_T;
135            else if (pair[1]==2)          // goto xy
136            {
137              fp->read(pair,2);
138              x+=pair[0];
139
140              y-=pair[1];
141              d=(w8 *)im->data+y*width+x;                   
142            } else         // run of data (even padded)
143            {             
144              fp->read(d,pair[1]);
145             
146              if (pair[1]&1)
147                fp->read(pair,1);
148
149              d+=pair[1];
150              x+=pair[1];
151            }
152          } else                          // run of colors
153          {
154            memset(d,pair[1],pair[0]);
155            d+=pair[0];
156            x+=pair[0];
157          }
158        }
159        return im;
160      }
161      else
162        delete im;
163    } else if (bits==24 && planes==1)
164    {
165      i4_pixel_format fmt;
166      fmt.default_format();
167
168      fmt.alpha_mask=0;           // no alpha info
169      fmt.calc_shift();
170
171   
172      w16 x,y;
173      const i4_pal *pal32=i4_pal_man.register_pal(&fmt);
174      i4_image_class *im=i4_create_image(width,height,pal32);
175      memset(im->data, 0, width*height*4);
176
177      w32 *sl=(w32 *)((w8*)im->data + (height-1)*im->bpl);
178
179      int end_of_line_skip=(fsize-54)/height - width*3;
180      fp->seek(offset);
181
182      for (y=height;y;y--)
183      {
184        if (status)
185          status->update((height-y)/(float)height);
186
187
188        for (x=0;x<width;x++)
189        {
190          w8 d[3];           
191          if (fp->read(d,3)!=3)
192          {
193            delete im;
194            return 0;
195          }
196          // d[0] == blue
197          // d[1] == green
198          // d[2] == red
199
200          *sl=d[0]|(d[1]<<8)|(d[2]<<16);
201          ++sl;
202        }
203        sl+=(-(width*2));
204
205        if (end_of_line_skip)   // each row is 0-padded to a 4-byte boundary
206          fp->read(buf, end_of_line_skip);
207
208
209
210      }
211      return im;
212
213    }
214
215    return 0;
216  }
217} bmp_loader_instance;
218
219
Note: See TracBrowser for help on using the repository browser.