/[pearpc]/src/system/gif.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /src/system/gif.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 6056 byte(s)
import upstream CVS
1 dpavlin 1 /*
2     * PearPC
3     * font.cc
4     *
5     * Copyright (C) 1999-2003 Sebastian Biallas (sb@biallas.net)
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License version 2 as
9     * published by the Free Software Foundation.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     */
20    
21     #include <cstring>
22    
23     #include "system/types.h"
24     #include "system/gif.h"
25     #include "tools/except.h"
26     #include "tools/snprintf.h"
27    
28     struct GIF_IDB {
29     byte ISH; // = 0x2c
30     uint16 x;
31     uint16 y;
32     uint16 width;
33     uint16 height;
34     byte flags;
35     byte initial_code_size;
36     } PACKED;
37    
38     Gif::Gif()
39     {
40     pic = NULL;
41     }
42    
43     Gif::~Gif()
44     {
45     delete[] pic;
46     }
47    
48     Gif::Gif(Stream &str)
49     {
50     pic = NULL;
51     if (!loadFromByteStream(str)) {
52     String res; str.getDesc(res);
53     throw MsgfException("error loading '%y' (not a gif?)", &res);
54     }
55     }
56    
57     static inline bool getlogbyte(Stream &stream, int width, int &bitleft, int &byteleft, uint16 &lbyte, uint16 &curcode, int &bidx, byte *buf)
58     {
59     curcode = lbyte >> (8-bitleft);
60     curcode &= (1<<width)-1;
61     int want = width - bitleft;
62     int have = bitleft;
63     bitleft -= width;
64     if (bitleft<0) bitleft = 0;
65     while (want > 0) {
66     if (!byteleft) {
67     stream.readx(buf, 1);
68     byteleft = buf[0];
69     if (!byteleft) return false;
70     stream.readx(buf, byteleft);
71     bidx = 0;
72     }
73     byteleft--;
74     lbyte = buf[bidx++];
75     bitleft+=8;
76     int take = want;
77     if (take > 8) take = 8;
78     int a = lbyte & ((1<<take)-1);
79     a <<= have;
80     curcode |= a;
81     bitleft -= take;
82     have += take;
83     want -= take;
84     }
85     return true;
86     }
87    
88     bool Gif::loadFromByteStream(Stream &stream)
89     {
90     byte buf[768];
91     int idx;
92     uint16 alphStack[4096];
93     uint16 alphPrefix[4096];
94     uint16 alphTail[4096];
95     memset(alphStack, 0xff, sizeof alphStack);
96     memset(alphPrefix, 0xff, sizeof alphPrefix);
97     memset(alphTail, 0xff, sizeof alphTail);
98    
99     int free, width, max, stackp, bitleft, byteleft, bidx;
100     uint16 curcode, oldcode, readb, lbyte, special;
101     oldcode = 0;
102     special = 0;
103    
104     stream.readx(buf, 6); // magic
105     if (buf[0] != 'G' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != '8' || buf[5] != 'a') return false;
106     int version;
107     switch (buf[4]) {
108     case '7': version = 7; break;
109     case '9': version = 9; break;
110     default: return false;
111     }
112    
113     stream.readx(buf, 7); // header
114    
115     mWidth = buf[0] + (buf[1]<<8);
116     mHeight = buf[2] + (buf[3]<<8);
117     if (buf[4] & 0x80) {
118     // global color table
119     int palsize = 3*(1<<((buf[4] & 7)+1));
120     stream.readx(mPal, palsize);
121     }
122    
123     stream.readx(buf, 1);
124     while (buf[0] == 0x21) {
125     // skip extension blocks
126     stream.readx(buf, 2);
127     stream.readx(buf, buf[1]+1);
128     stream.readx(buf, 1);
129     }
130     stream.readx(buf+1, 10);
131     GIF_IDB *i = (GIF_IDB*)&buf;
132     /* printf("IDB: ISH=%02x, x=%04x, y=%04x, width=%04x, height=%04x, flags=%02x\n",
133     i->ISH, i->x, i->y, i->width, i->height, i->flags
134     );*/
135    
136     // image descriptor?
137     if (i->ISH != 0x2c) return false;
138    
139     if (i->flags & 128) {
140     // local color table
141     int palsize = 3*(1<<((buf[8] & 7)+1));
142     stream.readx(mPal, palsize);
143     }
144    
145     int initial_code_size = i->initial_code_size;
146     int _CLR = 1<<initial_code_size;
147     int _EOF = _CLR+1;
148     lbyte = 0;
149     free = _EOF+1;
150     width = initial_code_size+1;
151     max = (1<<width)-1;
152     // ht_printf("i: %d c: %d e: %d max: %d, free: %d\n", initial_code_size, _CLR, _EOF, max, free);
153     stackp = 0;
154     bitleft = 0;
155     byteleft = 0;
156     idx = 0;
157    
158     pic = new byte[mWidth*mHeight];
159    
160     while (true) {
161     if (!getlogbyte(stream, width, bitleft, byteleft, lbyte, curcode, bidx, buf)) return false;
162     g:
163     if (curcode == _EOF) break;
164     if (curcode == _CLR) {
165     width = initial_code_size+1;
166     max = (1<<width)-1;
167     free = _EOF;
168     memset(alphStack, 0xff, sizeof alphStack);
169     memset(alphPrefix, 0xff, sizeof alphPrefix);
170     memset(alphTail, 0xff, sizeof alphTail);
171     if (!getlogbyte(stream, width, bitleft, byteleft, lbyte, curcode, bidx, buf)) return false;
172    
173     special = curcode;
174     oldcode = curcode;
175     goto g;
176     }
177     readb = curcode;
178     if (curcode >= free) {
179     // new code
180     curcode = oldcode;
181     alphStack[stackp++] = special;
182     }
183     // code in alphabet
184     while (curcode > _CLR) {
185     // decode
186     alphStack[stackp++] = alphTail[curcode];
187     curcode = alphPrefix[curcode];
188     if (curcode == 0xffff) return false;
189     }
190     alphStack[stackp] = curcode;
191     special = curcode;
192     do {
193     pic[idx++] = alphStack[stackp--];
194     } while (stackp >= 0);
195     stackp = 0;
196     alphPrefix[free] = oldcode;
197     alphTail[free] = curcode;
198     oldcode = readb;
199     free++;
200     if (free > max) {
201     if (width < 12) {
202     width++;
203     max = (1<<width)-1;
204     }
205     }
206     }
207     stream.readx(buf, 2);
208     if (buf[0] != 0x00 || buf[1] != 0x3b) return false;
209     // ht_printf("mWidth: %d mHeight: %d\n", mWidth, mHeight);
210     return true;
211     }
212    
213     void Gif::draw(SystemDisplay *display, int x, int y)
214     {
215     int p=0;
216     switch (display->mClientChar.bytesPerPixel) {
217     case 1:
218     return;
219     case 2: {
220     byte *f = gFrameBuffer+y*display->mClientChar.width*2+x*2;
221     for (int i=0; i<mHeight; i++) {
222     for (int j=0; j<mWidth; j++) {
223     int c = pic[p]*3;
224     f[0]=((mPal[c]>>1)&0x7c)|(mPal[c+1]>>6);
225     f[1]=((mPal[c+1]<<2)&0xe0)|(mPal[c+2]>>3);
226     f+=2;
227     p++;
228     }
229     f += display->mClientChar.scanLineLength - mWidth*2;
230     }
231     break;
232     }
233     case 4: {
234     byte *f = gFrameBuffer+y*display->mClientChar.width*4+x*4;
235     for (int i=0; i<mHeight; i++) {
236     for (int j=0; j<mWidth; j++) {
237     int c = pic[p]*3;
238     f[0]=0;
239     f[1]=mPal[c];
240     f[2]=mPal[c+1];
241     f[3]=mPal[c+2];
242     f+=4;
243     p++;
244     }
245     f += display->mClientChar.scanLineLength - mWidth*4;
246     }
247     break;
248     }
249     default:
250     ht_printf("unknown bytes per pixel in gif.cc\n");
251     exit(1);
252     }
253     damageFrameBuffer(y * display->mClientChar.width*2 + x*2);
254     damageFrameBuffer((y+mHeight) * display->mClientChar.width*2 + (x+mWidth) * 2);
255     }

  ViewVC Help
Powered by ViewVC 1.1.26