summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--noncore/apps/opie-reader/CDrawBuffer.cpp211
-rw-r--r--noncore/apps/opie-reader/plucker.cpp579
2 files changed, 790 insertions, 0 deletions
diff --git a/noncore/apps/opie-reader/CDrawBuffer.cpp b/noncore/apps/opie-reader/CDrawBuffer.cpp
new file mode 100644
index 0000000..2ceb2d5
--- a/dev/null
+++ b/noncore/apps/opie-reader/CDrawBuffer.cpp
@@ -0,0 +1,211 @@
1
2#include "CDrawBuffer.h"
3#include "FontControl.h"
4#include <qfontmetrics.h>
5#include <qpainter.h>
6
7void CDrawBuffer::setright(CDrawBuffer& rhs, int f)
8{
9 int i;
10// qDebug("Trying 1:%d:%s", f, (const char*)toQString(rhs.data()));
11 len = rhs.len;
12 m_maxstyle = rhs.m_maxstyle;
13 m_ascent = rhs.m_ascent;
14 m_descent = rhs.m_descent;
15 m_lineSpacing = rhs.m_lineSpacing;
16 while (!segs.isEmpty()) segs.erase(0);
17 for (CList<textsegment>::iterator iter = rhs.segs.begin(); iter != rhs.segs.end(); )
18 {
19 CList<textsegment>::iterator next = iter;
20 iter++;
21 if (iter == rhs.segs.end() || iter->start > f)
22 {
23 int st = next->start-f;
24 if (st < 0) st = 0;
25 segs.push_back(textsegment(st,next->style));
26 }
27 }
28 for (i = f; rhs[i] != '\0'; i++) (*this)[i-f] = rhs[i];
29 (*this)[i-f] = '\0';
30 len = i;
31// qDebug("Tried 1");
32}
33
34CDrawBuffer& CDrawBuffer::operator=(CDrawBuffer& rhs)
35{
36 int i;
37// qDebug("Trying 2");
38 len = rhs.len;
39 m_maxstyle = rhs.m_maxstyle;
40 m_ascent = rhs.m_ascent;
41 m_descent = rhs.m_descent;
42 m_lineSpacing = rhs.m_lineSpacing;
43 while (!segs.isEmpty()) segs.erase(0);
44 for (CList<textsegment>::iterator iter = rhs.segs.begin(); iter != rhs.segs.end(); iter++)
45 {
46 segs.push_back(*iter);
47 }
48 for (i = 0; rhs[i] != '\0'; i++) (*this)[i] = rhs[i];
49 (*this)[i] = '\0';
50 len = i;
51// qDebug("Tried 2");
52 return *this;
53}
54
55CDrawBuffer& CDrawBuffer::operator=(const tchar*sztmp)
56{
57 int i;
58 while (!segs.isEmpty()) segs.erase(0);
59 segs.push_back(textsegment(0, CStyle()));
60 for (i = 0; sztmp[i] != '\0'; i++) (*this)[i] = sztmp[i];
61 (*this)[i] = '\0';
62 len = i;
63 return *this;
64}
65
66void CDrawBuffer::empty()
67{
68 len = 0;
69 (*this)[0] = 0;
70 while (!segs.isEmpty()) segs.erase(0);
71 segs.push_back(textsegment(0,CStyle()));
72 m_maxstyle = m_ascent = m_descent = m_lineSpacing = 0;
73}
74
75void CDrawBuffer::addch(tchar ch, CStyle _style/* = ucFontBase*/)
76{
77 if (len == 0)
78 {
79 int thissize = fc->getsize(_style);
80 m_maxstyle = thissize;
81 m_ascent = fc->ascent(_style);
82 m_descent = fc->descent(_style);
83 m_lineSpacing = fc->lineSpacing(_style);
84 segs.first().start = 0;
85 segs.first().style = _style;
86 }
87 else if (_style != segs.last().style)
88 {
89 int thissize = fc->getsize(_style);
90 if (thissize > m_maxstyle)
91 {
92 m_maxstyle = thissize;
93 m_ascent = fc->ascent(_style);
94 m_descent = fc->descent(_style);
95 m_lineSpacing = fc->lineSpacing(_style);
96 }
97 segs.push_back(textsegment(len, _style));
98 }
99 (*this)[len++] = ch;
100}
101
102void CDrawBuffer::truncate(int n)
103{
104 len = n;
105 (*this)[n] = 0;
106}
107
108int CDrawBuffer::width(int numchars = -1)
109{
110 int currentx = 0, end = 0;
111 QString text = toQString(data());
112 CList<textsegment>::iterator textstart = segs.begin();
113 CList<textsegment>::iterator textend = textstart;
114 do
115 {
116 textend++;
117 end = (textend != segs.end()) ? textend->start : length();
118 if (numchars >= 0 && end > numchars)
119 {
120 end = numchars;
121 }
122 CStyle currentstyle = textstart->style;
123 QFont f(fc->name(), fc->getsize(currentstyle), (currentstyle.isBold()) ? QFont::Bold : QFont::Normal, (currentstyle.isItalic()) );
124 QString str = text.mid(textstart->start, end-textstart->start);
125 QFontMetrics fm(f);
126 currentx += fm.width(str);
127 textstart = textend;
128 }
129 while (textend != segs.end() && end != numchars);
130 return currentx;
131}
132
133void CDrawBuffer::render(QPainter* _p, int _y, bool _bMono, int _charWidth, int scwidth)
134{
135 int currentx = 0;
136 QString text = toQString(data());
137 CList<textsegment>::iterator textstart = segs.begin();
138 StyleType align = textstart->style.getJustify();
139 switch (align)
140 {
141 case CStyle::m_AlignRight:
142 {
143 // int linelength = width();
144 currentx = scwidth - width();
145 }
146 break;
147 case CStyle::m_AlignCentre:
148 {
149 // int linelength = width();
150 currentx = (scwidth - width())/2;
151 }
152 break;
153 case CStyle::m_AlignJustify:
154 case CStyle::m_AlignLeft:
155 break;
156 }
157 CList<textsegment>::iterator textend = textstart;
158 do
159 {
160 textend++;
161 int end = (textend != segs.end()) ? textend->start : length();
162 CStyle currentstyle = textstart->style;
163 QFont f(fc->name(), fc->getsize(currentstyle), (currentstyle.isBold()) ? QFont::Bold : QFont::Normal, (currentstyle.isItalic()) );
164 _p->setFont(f);
165 QString str = text.mid(textstart->start, end-textstart->start);
166 _p->setPen(QColor(currentstyle.Red(), currentstyle.Green(), currentstyle.Blue()));
167 if (_bMono)
168 {
169 for (int i = 0; i < str.length(); i++)
170 {
171 _p->drawText( currentx + i*_charWidth, _y, QString(str[i]));
172 }
173 currentx += str.length()*_charWidth;
174 }
175 else
176 {
177 _p->drawText( currentx, _y, str);
178 QFontMetrics fm(f);
179 currentx += fm.width(str);
180 }
181 textstart = textend;
182 }
183 while (textend != segs.end());
184}
185
186CStyle CDrawBuffer::laststyle()
187{
188 return segs.last().style;
189}
190
191bool CDrawBuffer::isLink(int numchars, size_t& tgt)
192{
193 int end = 0;
194 CStyle currentstyle;
195 CList<textsegment>::iterator textstart = segs.begin();
196 CList<textsegment>::iterator textend = textstart;
197 do
198 {
199 textend++;
200 end = (textend != segs.end()) ? textend->start : length();
201 if (numchars >= 0 && end > numchars)
202 {
203 end = numchars;
204 }
205 currentstyle = textstart->style;
206 textstart = textend;
207 }
208 while (textend != segs.end() && end != numchars);
209 tgt = currentstyle.getData();
210 return currentstyle.getLink();
211}
diff --git a/noncore/apps/opie-reader/plucker.cpp b/noncore/apps/opie-reader/plucker.cpp
new file mode 100644
index 0000000..ddda4bc
--- a/dev/null
+++ b/noncore/apps/opie-reader/plucker.cpp
@@ -0,0 +1,579 @@
1#include <stdio.h>
2#include <string.h>
3#include <qmessagebox.h>
4#include "plucker.h"
5
6#include "Aportis.h"
7
8CPlucker::CPlucker() : expandedtextbuffer(NULL), compressedtextbuffer(NULL) { /*printf("constructing:%x\n",fin);*/ }
9
10
11int CPlucker::openfile(const char *src)
12{
13 if (!Cpdb::openfile(src))
14 {
15 return -1;
16 }
17
18//printf("Okay %u\n", 4);
19
20 if (memcmp(&head.type, "DataPlkr", 8) != 0) return -1;
21
22// qDebug("Cool - this IS plucker");
23
24 textlength = 0;
25 for (int recptr = 1; recptr < ntohs(head.recordList.numRecords); recptr++)
26 {
27 CPlucker_dataRecord thisHdr;
28 gotorecordnumber(recptr);
29 fread(&thisHdr, 1, sizeof(thisHdr), fin);
30 if (thisHdr.type < 2) textlength += htons(thisHdr.size);
31 }
32
33 gotorecordnumber(0);
34 fread(&hdr0, 1, sizeof(hdr0), fin);
35//printf("Okay %u\n", 5);
36 buffersize = 32*1024;
37 compressedtextbuffer = new UInt8[buffersize];
38 expandedtextbuffer = new UInt8[buffersize];
39
40// qDebug("Total number of records:%u", ntohs(head.recordList.numRecords));
41
42 unsigned int nrecs = ntohs(hdr0.nRecords);
43// qDebug("Version %u, no. res %u", ntohs(hdr0.version), nrecs);
44 for (unsigned int i = 0; i < 4*nrecs; i++)
45 {
46 UInt8 id;
47 fread(&id, 1, sizeof(id), fin);
48// qDebug("%x", id);
49 }
50 home();
51 return 0;
52}
53
54int CPlucker::bgetch()
55{
56 int ch = EOF;
57 if (bufferpos >= buffercontent)
58 {
59 if (bufferrec >= ntohs(head.recordList.numRecords) - 1) return EOF;
60// qDebug("Passing through %u", currentpos);
61 if (!expand(bufferrec+1)) return EOF;
62 mystyle.unset();
63 }
64
65 if (bufferpos == m_nextPara)
66 {
67 UInt16 attr = m_ParaAttrs[m_nextParaIndex];
68 m_nextParaIndex++;
69 if (m_nextParaIndex == m_nParas)
70 {
71 m_nextPara = -1;
72 }
73 else
74 {
75 m_nextPara += m_ParaOffsets[m_nextParaIndex];
76 }
77// qDebug("New paragraph");
78 ch = 10;
79 }
80 else
81 {
82 currentpos++;
83 ch = expandedtextbuffer[bufferpos++];
84 }
85 return ch;
86}
87
88int CPlucker::getch()
89{
90 int ch = bgetch();
91 while (ch == 0)
92 {
93 ch = bgetch();
94// qDebug("Function:%x", ch);
95 switch (ch)
96 {
97 case 0x38:
98 ch = 10;
99 break;
100 case 0x0a:
101 case 0x0c:
102 {
103 unsigned long ln = 0;
104 int skip = ch & 7;
105 for (int i = 0; i < 2; i++)
106 {
107 int ch = bgetch();
108 ln = (ln << 8) + ch;
109// qDebug("ch:%d, ln:%u", ch, ln);
110 }
111 if (skip == 2)
112 {
113 ln <<= 16;
114 }
115 else
116 {
117 for (int i = 0; i < 2; i++)
118 {
119 int ch = bgetch();
120 ln = (ln << 8) + ch;
121// qDebug("ch:%d, ln:%u", ch, ln);
122 }
123 }
124// qDebug("ln:%u", ln);
125 mystyle.setLink(true);
126 mystyle.setData(ln);
127 mystyle.setColour(255, 0, 0);
128 ch = bgetch();
129 }
130 break;
131 case 0x08:
132 ch = bgetch();
133 mystyle.setColour(0, 0, 0);
134 mystyle.setLink(false);
135 mystyle.setData(0);
136 break;
137 case 0x40:
138 mystyle.setItalic();
139 ch = bgetch();
140 break;
141 case 0x48:
142 mystyle.unsetItalic();
143 ch = bgetch();
144 break;
145 case 0x11:
146 {
147 ch = bgetch();
148 qDebug("Font:%d",ch);
149 switch (ch)
150 {
151 case 0:
152 mystyle.unsetBold();
153 mystyle.setFontSize(0);
154 break;
155 case 1:
156 mystyle.setBold();
157 mystyle.setFontSize(1);
158 break;
159 case 2:
160 mystyle.setBold();
161 mystyle.setFontSize(1);
162 break;
163 case 3:
164// mystyle.setBold();
165 mystyle.setFontSize(1);
166 break;
167 case 4:
168// mystyle.setBold();
169 mystyle.setFontSize(1);
170 break;
171 case 5:
172 mystyle.setBold();
173 mystyle.setFontSize(0);
174 break;
175 case 6:
176 mystyle.setBold();
177 mystyle.setFontSize(0);
178 break;
179 case 7:
180 mystyle.setBold();
181 mystyle.setFontSize(0);
182 break;
183 case 8: // should be fixed width
184 mystyle.unsetBold();
185 mystyle.setFontSize(0);
186 break;
187 default:
188 mystyle.unsetBold();
189 mystyle.setFontSize(0);
190 break;
191 }
192 ch = bgetch();
193 }
194 break;
195 case 0x29:
196 ch = bgetch();
197 switch (ch)
198 {
199 case 0:
200 mystyle.setLeftJustify();
201// qDebug("left");
202 break;
203 case 1:
204 mystyle.setRightJustify();
205// qDebug("right");
206 break;
207 case 2:
208 mystyle.setCentreJustify();
209// qDebug("centre");
210 break;
211 case 3:
212 mystyle.setFullJustify();
213// qDebug("full");
214 break;
215
216 }
217 ch = bgetch();
218 break;
219 case 0x53:
220 {
221 int r = bgetch();
222 int g = bgetch();
223 int b = bgetch();
224 mystyle.setColour(r,g,b);
225 ch = bgetch();
226 }
227 break;
228 case 0x1a:
229/*
230 {
231 UInt16 ir = bgetch();
232 ir = (ir << 8) + bgetch();
233 expandimg(ir);
234 }
235 ch = bgetch();
236 break;
237*/
238 case 0x33:
239 case 0x22:
240 case 0x5c:
241 case 0x60:
242 case 0x68:
243 case 0x70:
244 case 0x78:
245 case 0x83:
246 case 0x85:
247 default:
248 qDebug("Function:%x NOT IMPLEMENTED", ch);
249 {
250 int skip = ch & 7;
251 for (int i = 0; i < skip; i++)
252 {
253 ch = bgetch();
254 qDebug("Arg %d, %d", i, ch);
255 }
256 ch = bgetch();
257 }
258 }
259 }
260 return ch;
261}
262
263void CPlucker::getch(int& ch, CStyle& sty)
264{
265 ch = getch();
266 sty = mystyle;
267}
268
269unsigned int CPlucker::locate()
270{
271 return currentpos;
272/*
273 UInt16 thisrec = 1;
274 unsigned long locpos = 0;
275 gotorecordnumber(thisrec);
276 CPlucker_dataRecord thisHdr;
277 while (thisrec < bufferrec)
278 {
279 fread(&thisHdr, 1, sizeof(thisHdr), fin);
280 if (thisHdr.type < 2) locpos += htons(thisHdr.size);
281 thisrec++;
282 gotorecordnumber(thisrec);
283 }
284 return locpos+bufferpos;
285*/
286}
287
288void CPlucker::locate(unsigned int n)
289{
290 UInt16 thisrec = 0;
291 unsigned long locpos = 0;
292 unsigned long bs = 0;
293 CPlucker_dataRecord thisHdr;
294 do
295 {
296 thisrec++;
297 locpos += bs;
298 gotorecordnumber(thisrec);
299 fread(&thisHdr, 1, sizeof(thisHdr), fin);
300 if (thisHdr.type < 2)
301 {
302 bs = htons(thisHdr.size);
303 }
304 else
305 {
306 bs = 0;
307 }
308 } while (locpos + bs < n);
309 currentpos = locpos;
310 expand(thisrec);
311 while (currentpos < n && bufferpos < buffercontent) bgetch();
312}
313
314bool CPlucker::hyperlink(unsigned int n)
315{
316 UInt16 tuid = (n >> 16);
317 n &= 0xffff;
318 UInt16 thisrec = 1;
319 currentpos = 0;
320 gotorecordnumber(thisrec);
321 CPlucker_dataRecord thisHdr;
322 while (1)
323 {
324 fread(&thisHdr, 1, sizeof(thisHdr), fin);
325 if (tuid <= htons(thisHdr.uid)) break;
326 if (thisHdr.type < 2) currentpos += htons(thisHdr.size);
327// qDebug("hyper-cp:%u", currentpos);
328 thisrec++;
329 gotorecordnumber(thisrec);
330 }
331 if (thisHdr.type > 1)
332 {
333 QMessageBox::information(NULL,
334 QString("OpieReader"),
335 QString("External links\nnot yet supported")
336 );
337 return false;
338 }
339 else
340 {
341 expand(thisrec);
342 while (bufferpos < n && bufferpos < buffercontent) getch();
343 }
344 return true;
345}
346
347bool CPlucker::expand(int thisrec)
348{
349 mystyle.unset();
350 size_t reclen = recordlength(thisrec);
351 gotorecordnumber(thisrec);
352 CPlucker_dataRecord thisHdr;
353 while (1)
354 {
355 fread(&thisHdr, 1, sizeof(thisHdr), fin);
356// qDebug("This (%d) type is %d, uid is %u", thisrec, thisHdr.type, ntohs(thisHdr.uid));
357 if (thisHdr.type < 2) break;
358 qDebug("Skipping paragraph of type %d", thisHdr.type);
359 if (++thisrec >= ntohs(head.recordList.numRecords) - 1) return false;
360 reclen = recordlength(thisrec);
361 gotorecordnumber(thisrec);
362 }
363 m_nParas = ntohs(thisHdr.nParagraphs);
364// qDebug("It has %u paragraphs and is %u bytes", htons(thisHdr.nParagraphs), htons(thisHdr.size));
365 uid = ntohs(thisHdr.uid);
366 for (int i = 0; i < m_nParas; i++)
367 {
368 UInt16 ubytes, attrs;
369 fread(&ubytes, 1, sizeof(ubytes), fin);
370 fread(&attrs, 1, sizeof(attrs), fin);
371 m_ParaOffsets[i] = ntohs(ubytes);
372 m_ParaAttrs[i] = ntohs(attrs);
373// qDebug("Bytes %u, Attr %x", ntohs(ubytes), attrs);
374 }
375 if (m_nParas > 0)
376 {
377 m_nextPara = m_ParaOffsets[0];
378// qDebug("First offset = %u", m_nextPara);
379 m_nextParaIndex = 0;
380 }
381 else
382 {
383 m_nextPara = -1;
384 }
385
386 reclen -= sizeof(thisHdr)+4*m_nParas;
387
388 buffercontent = htons(thisHdr.size);
389
390 if (thisHdr.type == 0)
391 {
392 fread(expandedtextbuffer, reclen, sizeof(char), fin);
393 }
394 else
395 {
396 fread(compressedtextbuffer, reclen, sizeof(char), fin);
397 switch (ntohs(hdr0.version))
398 {
399 case 2:
400 UnZip(reclen, expandedtextbuffer, buffercontent);
401 break;
402 case 1:
403 UnDoc(reclen, expandedtextbuffer, buffercontent);
404 break;
405 }
406 }
407 bufferpos = 0;
408 bufferrec = thisrec;
409// qDebug("BC:%u, HS:%u", buffercontent, ntohs(thisHdr.size));
410 return true;
411}
412
413void CPlucker::UnZip(size_t reclen, UInt8* tgtbuffer, UInt16 bsize)
414{
415 z_stream zstream;
416 memset(&zstream,sizeof(zstream),0);
417 zstream.next_in = compressedtextbuffer;
418 zstream.next_out = tgtbuffer;
419 zstream.avail_out = bsize;
420 zstream.avail_in = reclen;
421
422 int keylen = 0;
423
424 zstream.zalloc = Z_NULL;
425 zstream.zfree = Z_NULL;
426 zstream.opaque = Z_NULL;
427
428// printf("Initialising\n");
429
430 inflateInit(&zstream);
431 int err = 0;
432 do {
433 if ( zstream.avail_in == 0 && 0 < keylen ) {
434 zstream.next_in = compressedtextbuffer + keylen;
435 zstream.avail_in = reclen - keylen;
436 keylen = 0;
437 }
438 zstream.next_out = tgtbuffer;
439 zstream.avail_out = bsize;
440
441 err = inflate( &zstream, Z_SYNC_FLUSH );
442
443 } while ( err == Z_OK );
444
445 inflateEnd(&zstream);
446}
447
448void CPlucker::UnDoc(size_t reclen, UInt8* tgtbuffer, UInt16 bsize)
449{
450// UInt16 headerSize;
451 UInt16 docSize;
452 UInt16 i;
453 UInt16 j;
454 UInt16 k;
455
456 UInt8 *inBuf = compressedtextbuffer;
457 UInt8 *outBuf = tgtbuffer;
458
459// headerSize = sizeof( Header ) + record->paragraphs * sizeof( Paragraph );
460 docSize = reclen;
461
462 j = 0;
463 k = 0;
464 while ( j < docSize ) {
465 i = 0;
466 while ( i < bsize && j < docSize ) {
467 UInt16 c;
468
469 c = (UInt16) inBuf[ j++ ];
470 if ( 0 < c && c < 9 ) {
471 while ( 0 < c-- )
472 outBuf[ i++ ] = inBuf[ j++ ];
473 }
474 else if ( c < 0x80 )
475 outBuf[ i++ ] = c;
476 else if ( 0xc0 <= c ) {
477 outBuf[ i++ ] = ' ';
478 outBuf[ i++ ] = c ^ 0x80;
479 }
480 else {
481 Int16 m;
482 Int16 n;
483
484 c <<= 8;
485 c += inBuf[ j++ ];
486
487 m = ( c & 0x3fff ) >> COUNT_BITS;
488 n = c & ( ( 1 << COUNT_BITS ) - 1 );
489 n += 2;
490
491 do {
492 outBuf[ i ] = outBuf[ i - m ];
493 i++;
494 } while ( 0 < n-- );
495 }
496 }
497 k += bsize;
498 }
499}
500
501void CPlucker::home()
502{
503 currentpos = 0;
504 expand(1);
505}
506
507CList<Bkmk>* CPlucker::getbkmklist()
508{
509/*
510 CPlucker_dataRecord thisHdr;
511
512 for (int i = 1; i < ntohs(head.recordList.numRecords); i++)
513 {
514 gotorecordnumber(i);
515 fread(&thisHdr, 1, sizeof(thisHdr), fin);
516 if (thisHdr.type == 8)
517 {
518 UInt16 n;
519 fread(&n, 1, sizeof(n), fin);
520 n = ntohs(n);
521 qDebug("Found %u bookmarks", n);
522 }
523 qDebug("Found:%d, %u", i , thisHdr.type);
524 }
525*/
526 return NULL;
527}
528
529void CPlucker::expandimg(UInt16 tgt)
530{
531 qDebug("Image:%u", tgt);
532 CPlucker_dataRecord thisHdr;
533 size_t reclen;
534 UInt16 thisrec = 0;
535 do
536 {
537 thisrec++;
538 reclen = recordlength(thisrec);
539 gotorecordnumber(thisrec);
540 qDebug("thisrec:%u.%u", ftell(fin),thisrec);
541 fread(&thisHdr, 1, sizeof(thisHdr), fin);
542 }
543 while (ntohs(thisHdr.uid) != tgt);
544
545 reclen -= sizeof(thisHdr);
546
547 UInt16 imgsize = htons(thisHdr.size);
548 UInt8* imgbuffer = new UInt8[imgsize];
549
550 qDebug("type:%u", thisHdr.type);
551
552 if (thisHdr.type == 2)
553 {
554 qDebug("Not compressed:%u.%u", ftell(fin),reclen);
555 fread(imgbuffer, reclen, sizeof(char), fin);
556 qDebug("Not compressed:%u.%u", ftell(fin),reclen);
557 }
558 else
559 {
560 qDebug("Compressed");
561 fread(compressedtextbuffer, reclen, sizeof(char), fin);
562 switch (ntohs(hdr0.version))
563 {
564 case 2:
565 UnZip(reclen, imgbuffer, imgsize);
566 break;
567 case 1:
568 UnDoc(reclen, imgbuffer, imgsize);
569 break;
570 }
571 }
572 FILE* imgfile = fopen("/home/tim/newreader/imagefile.tbmp", "w");
573 if (imgfile != NULL)
574 {
575 fwrite(imgbuffer, 1, imgsize, imgfile);
576 fclose(imgfile);
577 }
578 delete [] imgbuffer;
579}