/[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

Contents of /src/system/gif.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 6 months ago) by dpavlin
File size: 6056 byte(s)
import upstream CVS
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