3
* Purpose: Platform Independent GIF Image Class Loader and Writer
4
* 07/Aug/2001 Davide Pizzolato - www.xdp.it
5
* CxImage version 5.99c 17/Oct/2004
10
#if CXIMAGE_SUPPORT_GIF
14
#if CXIMAGE_SUPPORT_WINCE
21
////////////////////////////////////////////////////////////////////////////////
22
bool CxImageGIF::Decode(CxFile *fp)
24
/* AD - for transparency */
29
if (fp == NULL) return false;
31
fp->Read(&dscgif,/*sizeof(dscgif)*/13,1);
32
//if (strncmp(dscgif.header,"GIF8",3)!=0) {
33
if (strncmp(dscgif.header,"GIF8",4)!=0) return FALSE;
35
// Avoid Byte order problem with Mac
36
dscgif.scrheight = ltohs(dscgif.scrheight);
37
dscgif.scrwidth = ltohs(dscgif.scrwidth);
39
if (info.nEscape == -1) {
40
// Return output dimensions only
41
head.biWidth = dscgif.scrwidth;
42
head.biHeight = dscgif.scrheight;
46
/* AD - for interlace */
47
TabCol.sogct = (short)(1 << ((dscgif.pflds & 0x07)+1));
48
TabCol.colres = (short)(((dscgif.pflds & 0x70) >> 3) + 1);
50
// assume that the image is a truecolor-gif if
51
// 1) no global color map found
52
// 2) (image.w, image.h) of the 1st image != (dscgif.scrwidth, dscgif.scrheight)
57
if (dscgif.pflds & 0x80)
58
fp->Read(TabCol.paleta,sizeof(struct rgb_color)*TabCol.sogct,1);
60
bTrueColor++; //first chance for a truecolor gif
62
long first_transparent_index;
65
info.nNumFrames=get_num_frames(fp,&TabCol,&dscgif);
67
if ((info.nFrame<0)||(info.nFrame>=info.nNumFrames)) return false;
69
//it cannot be a true color GIF with only one frame
70
if (info.nNumFrames == 1)
74
bool bPreviousWasNull = true;
77
for (BOOL bContinue = TRUE; bContinue; )
79
if (fp->Read(&ch, sizeof(ch), 1) != 1) {break;}
81
if (info.nEscape > 0) return false; // <vho> - cancel decoding
82
if (bPreviousWasNull || ch==0)
86
case '!': // extension
88
bContinue = DecodeExtension(fp);
93
assert(sizeof(image) == 9);
94
fp->Read(&image,sizeof(image),1);
95
//avoid byte order problems with Solaris <candan>
96
/*BYTE *byteData = (BYTE *) & image;
97
image.l = byteData[0]+byteData[1]*256;
98
image.t = byteData[2]+byteData[3]*256;
99
image.w = byteData[4]+byteData[5]*256;
100
image.h = byteData[6]+byteData[7]*256;*/
101
image.l = ltohs(image.l);
102
image.t = ltohs(image.t);
103
image.w = ltohs(image.w);
104
image.h = ltohs(image.h);
106
if (((image.l + image.w) > dscgif.scrwidth)||((image.t + image.h) > dscgif.scrheight))
109
// check if it could be a truecolor gif
110
if ((iImage==0) && (image.w != dscgif.scrwidth) && (image.h != dscgif.scrheight))
114
if (image.pf & 0x80) {
115
TabCol.sogct = (short)(1 << ((image.pf & 0x07) +1));
116
assert(3 == sizeof(struct rgb_color));
117
fp->Read(TabCol.paleta,sizeof(struct rgb_color)*TabCol.sogct,1);
118
//log << "Local colour map" << endl;
121
int bpp; //<DP> select the correct bit per pixel value
122
if (TabCol.sogct <= 2) bpp = 1;
123
else if (TabCol.sogct <= 16) bpp = 4;
126
CxImageGIF backimage;
127
backimage.CopyInfo(*this);
129
//first frame: build image background
130
backimage.Create(dscgif.scrwidth, dscgif.scrheight, bpp, CXIMAGE_FORMAT_GIF);
131
first_transparent_index = info.nBkgndIndex;
132
backimage.Clear((BYTE)gifgce.transpcolindex);
134
//generic frame: handle disposal method from previous one
135
/*Values : 0 - No disposal specified. The decoder is
136
not required to take any action.
137
1 - Do not dispose. The graphic is to be left
139
2 - Restore to background color. The area used by the
140
graphic must be restored to the background color.
141
3 - Restore to previous. The decoder is required to
142
restore the area overwritten by the graphic with
143
what was there prior to rendering the graphic.
145
backimage.Copy(*this);
146
if (prevdispmeth==2){
147
backimage.Clear((BYTE)first_transparent_index);
152
Create(image.w, image.h, bpp, CXIMAGE_FORMAT_GIF);
154
if ((image.pf & 0x80) || (dscgif.pflds & 0x80)) {
155
unsigned char r[256], g[256], b[256];
156
int i, has_white = 0;
158
for (i=0; i < TabCol.sogct; i++) {
159
r[i] = TabCol.paleta[i].r;
160
g[i] = TabCol.paleta[i].g;
161
b[i] = TabCol.paleta[i].b;
163
if (RGB(r[i],g[i],b[i]) == 0xFFFFFF) has_white = 1;
166
// Force transparency colour white...
167
//if (0) if (info.nBkgndIndex != -1)
168
// r[info.nBkgndIndex] = g[info.nBkgndIndex] = b[info.nBkgndIndex] = 255;
169
// Fill in with white // AD
170
if (info.nBkgndIndex != -1) {
173
r[i] = g[i] = b[i] = 255;
178
// Force last colour to white... // AD
179
//if ((info.nBkgndIndex != -1) && !has_white) {
180
// r[255] = g[255] = b[255] = 255;
183
SetPalette((info.nBkgndIndex != -1 ? 256 : TabCol.sogct), r, g, b);
186
CImageIterator* iter = new CImageIterator(this);
191
interlaced = image.pf & 0x40;
197
long pos_start = fp->Tell();
198
//if (interlaced) log << "Interlaced" << endl;
199
decoder(fp, iter, image.w, badcode);
202
if (info.nEscape) return false; // <vho> - cancel decoding
204
if (bTrueColor<2 ){ //standard GIF: mix frame with background
205
backimage.GifMix(*this,image);
206
backimage.SetTransIndex(first_transparent_index);
207
backimage.SetPalette(GetPalette());
209
} else { //it's a truecolor gif!
210
//force full image decoding
211
info.nFrame=info.nNumFrames-1;
212
//build the RGB image
213
if (imaRGB==NULL) imaRGB = new CxImage(dscgif.scrwidth,dscgif.scrheight,24,CXIMAGE_FORMAT_GIF);
214
//copy the partial image into the full RGB image
215
for(long y=0;y<image.h;y++){
216
for (long x=0;x<image.w;x++){
217
imaRGB->SetPixelColor(x+image.l,dscgif.scrheight-1-image.t-y,GetPixelColor(x,image.h-y-1));
222
prevdispmeth = (gifgce.flags >> 2) & 0x7;
224
//restore the correct position in the file for the next image
226
seek_next_image(fp,pos_start);
228
fp->Seek(-(ibfmax - ibf - 1), SEEK_CUR);
231
if (info.bGetAllFrames) {
233
delete info.GifFrames;
234
info.GifFrames = new CxImage*[info.nNumFrames];
235
for(int frameIdx = 0; frameIdx < info.nNumFrames; frameIdx++){
236
info.GifFrames[frameIdx] = NULL;
240
info.GifFrames[iImage] = new CxImage(*imaRGB);
242
info.GifFrames[iImage] = new CxImage(*this);
243
info.GifFrames[iImage]->RetreiveSingleFrame();
245
if (info.nFrame==iImage) bContinue=false; else iImage++;
250
case ';': //terminator
254
bPreviousWasNull = (ch==0);
260
if (bTrueColor>=2 && imaRGB){
261
if (gifgce.flags & 0x1){
262
imaRGB->SetTransColor(GetPaletteColor((BYTE)info.nBkgndIndex));
263
imaRGB->SetTransIndex(0);
273
////////////////////////////////////////////////////////////////////////////////
274
bool CxImageGIF::DecodeExtension(CxFile *fp)
280
bContinue = (1 == fp->Read(&fc, sizeof(fc), 1));
282
/* AD - for transparency */
284
bContinue = (1 == fp->Read(&count, sizeof(count), 1));
286
assert(sizeof(gifgce) == 4);
287
bContinue = (count == fp->Read(&gifgce, 1, sizeof(gifgce)));
288
// Avoid Byte order problem with Mac
289
gifgce.delaytime = ltohs(gifgce.delaytime);
290
//fprintf(stderr, "Transparency block get, valid ? %u, Has transparency ? %u\n",bContinue, gifgce.flags & 0x1);
291
//fprintf(stderr, "transpcolflag %u : userinputflag %u : dispmeth %u : res %u\n", gifgce.flags & 0x1, (gifgce.flags >> 1) & 0x1, (gifgce.flags >> 2) & 0x7, (gifgce.flags >> 5) & 0x7 );
293
if (gifgce.flags & 0x1) info.nBkgndIndex = gifgce.transpcolindex;
294
info.dwFrameDelay = gifgce.delaytime;
295
SetDisposalMethod((gifgce.flags >> 2) & 0x7);
300
if (fc == 0xFE) { //<DP> Comment block
301
bContinue = (1 == fp->Read(&count, sizeof(count), 1));
303
bContinue = (1 == fp->Read(m_comment, count, 1));
304
m_comment[count]='\0';
307
if (fc == 0xFF) { //<DP> Application Extension block
308
bContinue = (1 == fp->Read(&count, sizeof(count), 1));
310
bContinue = (count==11);
313
bContinue = (1 == fp->Read(AppID, count, 1));
315
bContinue = (1 == fp->Read(&count, sizeof(count), 1));
317
BYTE* dati = (BYTE*)malloc(count);
318
bContinue = (dati!=NULL);
320
bContinue = (1 == fp->Read(dati, count, 1));
322
m_loops = dati[1]+256*dati[2];
328
while (bContinue && fp->Read(&count, sizeof(count), 1) && count) {
329
//log << "Skipping " << count << " bytes" << endl;
330
fp->Seek(count, SEEK_CUR);
338
// - This external (machine specific) function is expected to return
339
// either the next BYTE from the GIF file, or a negative error number.
340
int CxImageGIF::get_byte(CxFile* file)
344
ibfmax = file->Read( buf , 1 , GIFBUFTAM) ;
345
if( ibfmax < GIFBUFTAM ) buf[ ibfmax ] = 255 ;
349
if (ibf>=ibfmax) return -1; //<DP> avoid overflows
352
////////////////////////////////////////////////////////////////////////////////
353
/* - This function takes a full line of pixels (one BYTE per pixel) and
354
* displays them (or does whatever your program wants with them...). It
355
* should return zero, or negative if an error or some other event occurs
356
* which would require aborting the decode process... Note that the length
357
* passed will almost always be equal to the line length passed to the
358
* decoder function, with the sole exception occurring when an ending code
359
* occurs in an odd place in the GIF file... In any case, linelen will be
360
* equal to the number of pixels passed...
362
int CxImageGIF::out_line(CImageIterator* iter, unsigned char *pixels, int linelen)
364
//<DP> for 1 & 4 bpp images, the pixels are compressed
365
if (head.biBitCount < 8){
366
for(long x=0;x<head.biWidth;x++){
368
BYTE* iDst= pixels + (x*head.biBitCount >> 3);
369
if (head.biBitCount==4){
370
pos = (BYTE)(4*(1-x%2));
371
*iDst &= ~(0x0F<<pos);
372
*iDst |= ((pixels[x] & 0x0F)<<pos);
373
} else if (head.biBitCount==1){
375
*iDst &= ~(0x01<<pos);
376
*iDst |= ((pixels[x] & 0x01)<<pos);
381
/* AD - for interlace */
383
iter->SetY(iheight-iypos-1);
384
iter->SetRow(pixels, linelen);
386
if ((iypos += istep) >= iheight) {
388
if (ipass++ > 0) istep /= 2;
391
while (iypos > iheight);
396
iter->SetRow(pixels, linelen);
397
(void)iter->PrevRow();
405
////////////////////////////////////////////////////////////////////////////////
406
#if CXIMAGE_SUPPORT_ENCODE
407
////////////////////////////////////////////////////////////////////////////////
408
// SaveFile - writes GIF87a gif file
409
// Randy Spann 6/15/97
410
// R.Spann@ConnRiver.net
411
bool CxImageGIF::Encode(CxFile * fp)
413
if ( GetNumFrames()>1 && info.GifFrames ) {
414
return Encode(fp, info.GifFrames, GetNumFrames() );
417
if (EncodeSafeCheck(fp)) return false;
419
if(head.biBitCount > 8) {
420
//strcpy(info.szLastError,"GIF Images must be 8 bit or less");
422
return EncodeRGB(fp);
433
fp->PutC(';'); // Write the GIF file terminator
435
return true; // done!
438
////////////////////////////////////////////////////////////////////////////////
439
bool CxImageGIF::Encode(CxFile * fp, CxImage ** pImages, int pagecount, bool bLocalColorMap)
442
if (fp==NULL) throw "invalid file pointer";
443
if (pImages==NULL || pagecount==0 || pImages[0]==NULL) throw "multipage GIF, no images!";
447
//write the first image
448
ghost.Ghost(pImages[0]);
449
ghost.EncodeHeader(fp);
452
ghost.SetLoops(max(0,m_loops-1));
453
ghost.EncodeLoopExtension(fp);
456
//ghost.SetDisposalMethod(pImages[0]->GetDisposalMethod());
457
ghost.EncodeExtension(fp);
461
ghost.EncodeBody(fp);
463
for (int i=2; i<=pagecount; i++){
464
if (pImages[i-1]==NULL) throw "Bad image pointer";
465
ghost.Ghost(pImages[i-1]);
467
//ghost.SetDisposalMethod(pImages[i-1]->GetDisposalMethod());
468
ghost.EncodeExtension(fp);
470
ghost.EncodeBody(fp,bLocalColorMap);
473
fp->PutC(';'); // Write the GIF file terminator
475
} catch (const char *message) {
476
strncpy(info.szLastError,message,255);
481
////////////////////////////////////////////////////////////////////////////////
482
void CxImageGIF::EncodeHeader(CxFile *fp)
484
fp->Write("GIF89a",1,6); //GIF Header
486
Putword(head.biWidth,fp); //Logical screen descriptor
487
Putword(head.biHeight,fp);
490
if (head.biClrUsed==0){
494
Flags |=(head.biBitCount - 1) << 5;
495
Flags |=(head.biBitCount - 1);
498
fp->PutC(Flags); //GIF "packed fields"
499
fp->PutC(0); //GIF "BackGround"
500
fp->PutC(0); //GIF "pixel aspect ratio"
502
if (head.biClrUsed!=0){
503
RGBQUAD* pPal = GetPalette();
504
for(DWORD i=0; i<head.biClrUsed; ++i)
506
fp->PutC(pPal[i].rgbRed);
507
fp->PutC(pPal[i].rgbGreen);
508
fp->PutC(pPal[i].rgbBlue);
512
////////////////////////////////////////////////////////////////////////////////
513
void CxImageGIF::EncodeExtension(CxFile *fp)
515
// TRK BEGIN : transparency
517
fp->PutC(TRANSPARENCY_CODE);
520
gifgce.flags |= ((info.nBkgndIndex != -1) ? 1 : 0);
521
//gifgce.flags = ( (0 & 0x1) << 1 );
522
gifgce.flags |= ( (GetDisposalMethod() & 0x7) << 2);
523
//gifgce.flags |= ( (0 & 0x7) << 5 );
524
gifgce.delaytime = (WORD)info.dwFrameDelay;
525
gifgce.transpcolindex = (BYTE)info.nBkgndIndex;
526
fp->PutC(sizeof(gifgce));
527
//Invert byte order in case we use a byte order arch, then set it back
528
gifgce.delaytime = htols(gifgce.delaytime);
529
fp->Write(&gifgce, sizeof(gifgce), 1);
530
gifgce.delaytime = ltohs(gifgce.delaytime);
534
////////////////////////////////////////////////////////////////////////////////
535
void CxImageGIF::EncodeLoopExtension(CxFile *fp)
537
fp->PutC('!'); //byte 1 : 33 (hex 0x21) GIF Extension code
538
fp->PutC(255); //byte 2 : 255 (hex 0xFF) Application Extension Label
539
fp->PutC(11); //byte 3 : 11 (hex (0x0B) Length of Application Block (eleven bytes of data to follow)
540
fp->Write("NETSCAPE2.0",11,1);
541
fp->PutC(3); //byte 15 : 3 (hex 0x03) Length of Data Sub-Block (three bytes of data to follow)
542
fp->PutC(1); //byte 16 : 1 (hex 0x01)
543
Putword(m_loops,fp); //bytes 17 to 18 : 0 to 65535, an unsigned integer in lo-hi byte format.
544
//This indicate the number of iterations the loop should be executed.
545
fp->PutC(0); //bytes 19 : 0 (hex 0x00) a Data Sub-block Terminator.
547
////////////////////////////////////////////////////////////////////////////////
548
void CxImageGIF::EncodeBody(CxFile *fp, bool bLocalColorMap)
551
cury = head.biHeight - 1; //because we read the image bottom to top
552
CountDown = (long)head.biWidth * (long)head.biHeight;
556
Putword(info.xOffset,fp);
557
Putword(info.yOffset,fp);
558
Putword(head.biWidth,fp);
559
Putword(head.biHeight,fp);
561
BYTE Flags=0x00; //non-interlaced (0x40 = interlaced) (0x80 = LocalColorMap)
562
if (bLocalColorMap) { Flags|=0x80; Flags|=head.biBitCount-1; }
567
RGBQUAD* pPal = GetPalette();
568
for(DWORD i=0; i<head.biClrUsed; ++i)
570
fp->PutC(pPal[i].rgbRed);
571
fp->PutC(pPal[i].rgbGreen);
572
fp->PutC(pPal[i].rgbBlue);
576
int InitCodeSize = head.biBitCount <=1 ? 2 : head.biBitCount;
577
// Write out the initial code size
578
fp->PutC((BYTE)InitCodeSize);
580
// Go and actually compress the data
581
switch (GetCodecOption(CXIMAGE_FORMAT_GIF))
583
case 1: //uncompressed
584
compressNONE(InitCodeSize+1, fp);
587
compressRLE(InitCodeSize+1, fp);
590
compressLZW(InitCodeSize+1, fp);
593
// Write out a Zero-length packet (to end the series)
596
////////////////////////////////////////////////////////////////////////////////
597
void CxImageGIF::EncodeComment(CxFile *fp)
599
unsigned long n = (unsigned long) strlen(m_comment);
602
fp->PutC('!'); //extension code:
603
fp->PutC(254); //comment extension
604
fp->PutC((BYTE)n); //size of comment
605
fp->Write(m_comment,n,1);
606
fp->PutC(0); //block terminator
609
////////////////////////////////////////////////////////////////////////////////
610
bool CxImageGIF::EncodeRGB(CxFile *fp)
614
// EncodeLoopExtension(fp);
620
const long cellw = 17;
621
const long cellh = 15;
623
for (long y=0;y<head.biHeight;y+=cellh){
624
for (long x=0;x<head.biWidth;x+=cellw){
625
if ((head.biWidth -x)<cellw) w=head.biWidth -x; else w=cellw;
626
if ((head.biHeight-y)<cellh) h=head.biHeight-y; else h=cellh;
628
if (w!=tmp.GetWidth() || h!=tmp.GetHeight()) tmp.Create(w,h,8);
630
if (IsTransparent()){
631
tmp.SetTransIndex(0);
632
tmp.SetPaletteColor(0,GetTransColor());
636
for (unsigned long j=0;j<h;j++){
637
for (unsigned long k=0;k<w;k++){
638
i=(BYTE)(1+k+cellw*j);
639
tmp.SetPaletteColor(i,GetPixelColor(x+k,head.biHeight-y-h+j));
640
tmp.SetPixelIndex(k,j,tmp.GetNearestIndex(tmp.GetPaletteColor(i)));
645
tmp.EncodeExtension(fp);
646
tmp.EncodeBody(fp,true);
650
fp->PutC(';'); // Write the GIF file terminator
652
return true; // done!
654
////////////////////////////////////////////////////////////////////////////////
655
#endif // CXIMAGE_SUPPORT_ENCODE
656
////////////////////////////////////////////////////////////////////////////////
657
// Return the next pixel from the image
658
// <DP> fix for 1 & 4 bpp images
659
int CxImageGIF::GifNextPixel( )
661
if( CountDown == 0 ) return EOF;
663
int r = GetPixelIndex(curx,cury);
664
// Bump the current X position
666
if( curx == head.biWidth ){
668
cury--; //bottom to top
672
////////////////////////////////////////////////////////////////////////////////
673
void CxImageGIF::Putword(int w, CxFile *fp )
675
fp->PutC((BYTE)(w & 0xff));
676
fp->PutC((BYTE)((w / 256) & 0xff));
678
////////////////////////////////////////////////////////////////////////////////
679
void CxImageGIF::compressNONE( int init_bits, CxFile* outfile)
684
// g_init_bits - initial number of bits
685
// g_outfile - pointer to output file
686
g_init_bits = init_bits;
689
// Set up the necessary values
690
cur_accum = cur_bits = clear_flg = 0;
691
maxcode = (short)MAXCODE(n_bits = g_init_bits);
692
code_int maxmaxcode = (code_int)1 << MAXBITSCODES;
694
ClearCode = (1 << (init_bits - 1));
695
EOFCode = ClearCode + 1;
696
free_ent = (short)(ClearCode + 2);
699
ent = GifNextPixel( );
701
output( (code_int)ClearCode );
703
while ( ent != EOF ) {
706
output ( (code_int) ent );
708
if ( free_ent < maxmaxcode ) {
711
free_ent=(short)(ClearCode+2);
713
output((code_int)ClearCode);
716
// Put out the final code.
717
output( (code_int) EOFCode );
719
////////////////////////////////////////////////////////////////////////////////
721
/***************************************************************************
723
* GIFCOMPR.C - LZW GIF Image compression routines
725
***************************************************************************/
727
void CxImageGIF::compressLZW( int init_bits, CxFile* outfile)
732
register long hshift;
736
// g_init_bits - initial number of bits
737
// g_outfile - pointer to output file
738
g_init_bits = init_bits;
741
// Set up the necessary values
742
cur_accum = cur_bits = clear_flg = 0;
743
maxcode = (short)MAXCODE(n_bits = g_init_bits);
744
code_int maxmaxcode = (code_int)1 << MAXBITSCODES;
746
ClearCode = (1 << (init_bits - 1));
747
EOFCode = ClearCode + 1;
748
free_ent = (short)(ClearCode + 2);
751
ent = GifNextPixel( );
754
for ( fcode = (long) HSIZE; fcode < 65536L; fcode *= 2L ) ++hshift;
755
hshift = 8 - hshift; /* set hash code range bound */
756
cl_hash((long)HSIZE); /* clear hash table */
757
output( (code_int)ClearCode );
759
while ( (c = GifNextPixel( )) != EOF ) {
761
fcode = (long) (((long) c << MAXBITSCODES) + ent);
762
i = (((code_int)c << hshift) ^ ent); /* xor hashing */
764
if ( HashTabOf (i) == fcode ) {
767
} else if ( (long)HashTabOf (i) < 0 ) /* empty slot */
769
disp = HSIZE - i; /* secondary hash (after G. Knott) */
770
if ( i == 0 ) disp = 1;
772
if ( (i -= disp) < 0 ) i += HSIZE;
773
if ( HashTabOf (i) == fcode ) { ent = CodeTabOf (i); continue; }
774
if ( (long)HashTabOf (i) > 0 ) goto probe;
776
output ( (code_int) ent );
778
if ( free_ent < maxmaxcode ) {
779
CodeTabOf (i) = free_ent++; /* code -> hashtable */
780
HashTabOf (i) = fcode;
782
cl_hash((long)HSIZE);
783
free_ent=(short)(ClearCode+2);
785
output((code_int)ClearCode);
788
// Put out the final code.
789
output( (code_int)ent );
790
output( (code_int) EOFCode );
792
////////////////////////////////////////////////////////////////////////////////
794
static const unsigned long code_mask[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
795
0x001F, 0x003F, 0x007F, 0x00FF,
796
0x01FF, 0x03FF, 0x07FF, 0x0FFF,
797
0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
799
////////////////////////////////////////////////////////////////////////////////
800
void CxImageGIF::output( code_int code)
802
cur_accum &= code_mask[ cur_bits ];
805
cur_accum |= ((long)code << cur_bits);
811
while( cur_bits >= 8 ) {
812
char_out( (unsigned int)(cur_accum & 0xff) );
818
* If the next entry is going to be too big for the code size,
819
* then increase it, if possible.
822
if ( free_ent > maxcode || clear_flg ) {
824
maxcode = (short)MAXCODE(n_bits = g_init_bits);
828
if ( n_bits == MAXBITSCODES )
829
maxcode = (code_int)1 << MAXBITSCODES; /* should NEVER generate this code */
831
maxcode = (short)MAXCODE(n_bits);
835
if( code == EOFCode ) {
836
// At EOF, write the rest of the buffer.
837
while( cur_bits > 0 ) {
838
char_out( (unsigned int)(cur_accum & 0xff) );
846
if(g_outfile->Error()) strcpy(info.szLastError,"Write Error in GIF file");
849
////////////////////////////////////////////////////////////////////////////////
851
void CxImageGIF::cl_hash(register long hsize)
854
register long *htab_p = htab+hsize;
857
register long m1 = -1L;
880
} while ((i-=16) >=0);
886
/*******************************************************************************
888
*******************************************************************************/
890
void CxImageGIF::char_out(int c)
892
accum[a_count++]=(char)c;
897
void CxImageGIF::flush_char()
900
g_outfile->PutC((BYTE)a_count);
901
g_outfile->Write(accum,1,a_count);
906
/*******************************************************************************
908
*******************************************************************************/
909
/* DECODE.C - An LZW decoder for GIF
910
* Copyright (C) 1987, by Steven A. Bennett
911
* Copyright (C) 1994, C++ version by Alejandro Aguilar Sierra
913
* Permission is given by the author to freely redistribute and include
914
* this code in any program as long as this credit is given where due.
916
* In accordance with the above, I want to credit Steve Wilhite who wrote
917
* the code which this is heavily inspired by...
919
* GIF and 'Graphics Interchange Format' are trademarks (tm) of
920
* Compuserve, Incorporated, an H&R Block Company.
922
* Release Notes: This file contains a decoder routine for GIF images
923
* which is similar, structurally, to the original routine by Steve Wilhite.
924
* It is, however, somewhat noticably faster in most cases.
928
////////////////////////////////////////////////////////////////////////////////
930
short CxImageGIF::init_exp(short size)
932
curr_size = (short)(size + 1);
933
top_slot = (short)(1 << curr_size);
934
clear = (short)(1 << size);
935
ending = (short)(clear + 1);
936
slot = newcodes = (short)(ending + 1);
937
navail_bytes = nbits_left = 0;
939
memset(stack,0,MAX_CODES + 1);
940
memset(prefix,0,MAX_CODES + 1);
941
memset(suffix,0,MAX_CODES + 1);
944
////////////////////////////////////////////////////////////////////////////////
947
* - gets the next code from the GIF file. Returns the code, or else
948
* a negative number in case of file errors...
950
short CxImageGIF::get_next_code(CxFile* file)
955
if (nbits_left == 0) {
956
if (navail_bytes <= 0) {
957
/* Out of bytes in current block, so read next block */
959
if ((navail_bytes = (short)get_byte(file)) < 0)
960
return(navail_bytes);
961
else if (navail_bytes) {
962
for (i = 0; i < navail_bytes; ++i) {
963
if ((x = (short)get_byte(file)) < 0) return(x);
964
byte_buff[i] = (BYTE)x;
973
if (navail_bytes<0) return ending; // prevent deadlocks (thanks to Mike Melnikov)
975
ret = b1 >> (8 - nbits_left);
976
while (curr_size > nbits_left){
977
if (navail_bytes <= 0){
978
/* Out of bytes in current block, so read next block*/
980
if ((navail_bytes = (short)get_byte(file)) < 0)
981
return(navail_bytes);
982
else if (navail_bytes){
983
for (i = 0; i < navail_bytes; ++i){
984
if ((x = (short)get_byte(file)) < 0) return(x);
985
byte_buff[i] = (BYTE)x;
990
ret |= b1 << nbits_left;
994
nbits_left = (short)(nbits_left-curr_size);
995
ret &= code_mask[curr_size];
996
return((short)(ret));
998
////////////////////////////////////////////////////////////////////////////////
1000
/* short decoder(linewidth)
1001
* short linewidth; * Pixels per line of image *
1003
* - This function decodes an LZW image, according to the method used
1004
* in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded
1005
* will generate a call to out_line(), which is a user specific function
1006
* to display a line of pixels. The function gets it's codes from
1007
* get_next_code() which is responsible for reading blocks of data and
1008
* seperating them into the proper size codes. Finally, get_byte() is
1009
* the global routine to read the next BYTE from the GIF file.
1011
* It is generally a good idea to have linewidth correspond to the actual
1012
* width of a line (as specified in the Image header) to make your own
1013
* code a bit simpler, but it isn't absolutely necessary.
1015
* Returns: 0 if successful, else negative. (See ERRS.H)
1018
/* bad_code_count is incremented each time an out of range code is read.
1019
* When this value is non-zero after a decode, your GIF file is probably
1020
* corrupt in some way...
1022
short CxImageGIF::decoder(CxFile* file, CImageIterator* iter, short linewidth, int &bad_code_count)
1024
register BYTE *sp, *bufptr;
1026
register short code, fc, oc, bufcnt;
1029
/* Initialize for decoding a new image... */
1031
if ((size = (short)get_byte(file)) < 0) return(size);
1032
if (size < 2 || 9 < size) return(BAD_CODE_SIZE);
1033
// out_line = outline;
1035
//printf("L %d %x\n",linewidth,size);
1037
/* Initialize in case they forgot to put in a clear code.
1038
* (This shouldn't happen, but we'll try and decode it anyway...)
1042
/* Allocate space for the decode buffer */
1043
if ((buf = new BYTE[linewidth + 1]) == NULL) return(OUT_OF_MEMORY);
1045
/* Set up the stack pointer and decode buffer pointer */
1050
/* This is the main loop. For each code we get we pass through the
1051
* linked list of prefix codes, pushing the corresponding "character" for
1052
* each code onto the stack. When the list reaches a single "character"
1053
* we push that on the stack too, and then start unstacking each
1054
* character for output in the correct order. Special handling is
1055
* included for the clear code, and the whole thing ends when we get
1058
while ((c = get_next_code(file)) != ending) {
1059
/* If we had a file error, return without completing the decode*/
1064
/* If the code is a clear code, reinitialize all necessary items.*/
1066
curr_size = (short)(size + 1);
1068
top_slot = (short)(1 << curr_size);
1070
/* Continue reading codes until we get a non-clear code
1071
* (Another unlikely, but possible case...)
1073
while ((c = get_next_code(file)) == clear);
1075
/* If we get an ending code immediately after a clear code
1076
* (Yet another unlikely case), then break out of the loop.
1078
if (c == ending) break;
1080
/* Finally, if the code is beyond the range of already set codes,
1081
* (This one had better NOT happen... I have no idea what will
1082
* result from this, but I doubt it will look good...) then set it
1085
if (c >= slot) c = 0;
1088
/* And let us not forget to put the char into the buffer... And
1089
* if, on the off chance, we were exactly one pixel from the end
1090
* of the line, we have to send the buffer to the out_line()
1093
*bufptr++ = (BYTE)c;
1094
if (--bufcnt == 0) {
1095
if ((ret = (short)out_line(iter, buf, linewidth)) < 0) {
1103
/* In this case, it's not a clear code or an ending code, so
1104
* it must be a code code... So we can now decode the code into
1105
* a stack of character codes. (Clear as mud, right?)
1109
/* Here we go again with one of those off chances... If, on the
1110
* off chance, the code we got is beyond the range of those already
1111
* set up (Another thing which had better NOT happen...) we trick
1112
* the decoder into thinking it actually got the last code read.
1113
* (Hmmn... I'm not sure why this works... But it does...)
1116
if (code > slot) ++bad_code_count;
1121
/* Here we scan back along the linked list of prefixes, pushing
1122
* helpless characters (ie. suffixes) onto the stack as we do so.
1124
while (code >= newcodes) {
1125
*sp++ = suffix[code];
1126
code = prefix[code];
1129
/* Push the last character on the stack, and set up the new
1130
* prefix and suffix, and if the required slot number is greater
1131
* than that allowed by the current bit size, increase the bit
1132
* size. (NOTE - If we are all full, we *don't* save the new
1133
* suffix and prefix... I'm not certain if this is correct...
1134
* it might be more proper to overwrite the last code...
1137
if (slot < top_slot){
1138
suffix[slot] = (BYTE)(fc = (BYTE)code);
1139
prefix[slot++] = oc;
1142
if (slot >= top_slot){
1143
if (curr_size < 12) {
1149
/* Now that we've pushed the decoded string (in reverse order)
1150
* onto the stack, lets pop it off and put it into our decode
1151
* buffer... And when the decode buffer is full, write another
1154
while (sp > stack) {
1155
*bufptr++ = *(--sp);
1156
if (--bufcnt == 0) {
1157
if ((ret = (short)out_line(iter, buf, linewidth)) < 0) {
1168
if (bufcnt != linewidth)
1169
ret = (short)out_line(iter, buf, (linewidth - bufcnt));
1173
////////////////////////////////////////////////////////////////////////////////
1174
int CxImageGIF::get_num_frames(CxFile *fp,struct_TabCol* TabColSrc,struct_dscgif* dscgif)
1178
long pos=fp->Tell();
1181
struct_TabCol TempTabCol;
1182
memcpy(&TempTabCol,TabColSrc,sizeof(struct_TabCol));
1185
bool bPreviousWasNull = true;
1187
for (BOOL bContinue = TRUE; bContinue; )
1189
if (fp->Read(&ch, sizeof(ch), 1) != 1) {break;}
1191
if (bPreviousWasNull || ch==0)
1195
case '!': // extension
1197
DecodeExtension(fp);
1203
assert(sizeof(image) == 9);
1204
//log << "Image header" << endl;
1205
fp->Read(&image,sizeof(image),1);
1207
//avoid byte order problems with Solaris <candan>
1208
BYTE *byteData = (BYTE *) & image;
1209
image.l = byteData[0]+byteData[1]*256;
1210
image.t = byteData[2]+byteData[3]*256;
1211
image.w = byteData[4]+byteData[5]*256;
1212
image.h = byteData[6]+byteData[7]*256;
1214
if (((image.l + image.w) > dscgif->scrwidth)||((image.t + image.h) > dscgif->scrheight))
1219
// Local colour map?
1220
if (image.pf & 0x80) {
1221
TempTabCol.sogct = (short)(1 << ((image.pf & 0x07) +1));
1222
assert(3 == sizeof(struct rgb_color));
1223
fp->Read(TempTabCol.paleta,sizeof(struct rgb_color)*TempTabCol.sogct,1);
1224
//log << "Local colour map" << endl;
1227
int bpp; //<DP> select the correct bit per pixel value
1228
if (TempTabCol.sogct <= 2) bpp = 1;
1229
else if (TempTabCol.sogct <= 16) bpp = 4;
1232
Create(image.w, image.h, bpp, CXIMAGE_FORMAT_GIF);
1234
CImageIterator* iter = new CImageIterator(this);
1239
interlaced = image.pf & 0x40;
1245
long pos_start = fp->Tell();
1247
//if (interlaced) log << "Interlaced" << endl;
1248
decoder(fp, iter, image.w, badcode);
1252
seek_next_image(fp,pos_start);
1254
fp->Seek(-(ibfmax - ibf - 1), SEEK_CUR);
1259
case ';': //terminator
1263
bPreviousWasNull = (ch==0);
1269
fp->Seek(pos,SEEK_SET);
1272
////////////////////////////////////////////////////////////////////////////////
1273
long CxImageGIF::seek_next_image(CxFile* fp, long position)
1275
fp->Seek(position, SEEK_SET);
1278
while(fp->Read(&ch2,sizeof(char),1)>0){
1279
if (ch1 == 0 && ch2 == ','){
1280
fp->Seek(-1,SEEK_CUR);
1288
////////////////////////////////////////////////////////////////////////////////
1289
void CxImageGIF::SetLoops(int loops)
1291
////////////////////////////////////////////////////////////////////////////////
1292
long CxImageGIF::GetLoops()
1294
////////////////////////////////////////////////////////////////////////////////
1295
void CxImageGIF::SetComment(const char* sz_comment_in)
1296
{ if (sz_comment_in) strncpy(m_comment,sz_comment_in,255); }
1297
////////////////////////////////////////////////////////////////////////////////
1298
void CxImageGIF::GetComment(char* sz_comment_out)
1299
{ if (sz_comment_out) strncpy(sz_comment_out,m_comment,255); }
1300
////////////////////////////////////////////////////////////////////////////////
1301
void CxImageGIF::GifMix(CxImage & imgsrc2, struct_image & imgdesc)
1303
long ymin = max(0,(long)(GetHeight()-imgdesc.t - imgdesc.h));
1304
long ymax = GetHeight()-imgdesc.t;
1305
long xmin = imgdesc.l;
1306
long xmax = min(GetWidth(), (DWORD)(imgdesc.l + imgdesc.w));
1308
long ibg2= imgsrc2.GetTransIndex();
1311
for(long y = ymin; y < ymax; y++){
1312
for(long x = xmin; x < xmax; x++){
1313
i2 = imgsrc2.GetPixelIndex(x-xmin,y-ymin);
1314
if(i2!=ibg2) SetPixelIndex(x,y,i2);
1318
////////////////////////////////////////////////////////////////////////////////
1319
/*-----------------------------------------------------------------------
1321
* miGIF Compression - mouse and ivo's GIF-compatible compression
1323
* -run length encoding compression routines-
1325
* Copyright (C) 1998 Hutchison Avenue Software Corporation
1326
* http://www.hasc.com
1329
* Permission to use, copy, modify, and distribute this software and its
1330
* documentation for any purpose and without fee is hereby granted, provided
1331
* that the above copyright notice appear in all copies and that both that
1332
* copyright notice and this permission notice appear in supporting
1333
* documentation. This software is provided "AS IS." The Hutchison Avenue
1334
* Software Corporation disclaims all warranties, either express or implied,
1335
* including but not limited to implied warranties of merchantability and
1336
* fitness for a particular purpose, with respect to this code and accompanying
1339
* The miGIF compression routines do not, strictly speaking, generate files
1340
* conforming to the GIF spec, since the image data is not LZW-compressed
1341
* (this is the point: in order to avoid transgression of the Unisys patent
1342
* on the LZW algorithm.) However, miGIF generates data streams that any
1343
* reasonably sane LZW decompresser will decompress to what we want.
1345
* miGIF compression uses run length encoding. It compresses horizontal runs
1346
* of pixels of the same color. This type of compression gives good results
1347
* on images with many runs, for example images with lines, text and solid
1348
* shapes on a solid-colored background. It gives little or no compression
1349
* on images with few runs, for example digital or scanned photos.
1352
* mouse@rodents.montreal.qc.ca
1353
* 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
1357
* The Graphics Interchange Format(c) is the Copyright property of
1358
* CompuServe Incorporated. GIF(sm) is a Service Mark property of
1359
* CompuServe Incorporated.
1362
////////////////////////////////////////////////////////////////////////////////
1363
void CxImageGIF::rle_clear(struct_RLE* rle)
1365
rle->out_bits = rle->out_bits_init;
1366
rle->out_bump = rle->out_bump_init;
1367
rle->out_clear = rle->out_clear_init;
1369
rle->rl_table_max = 0;
1370
rle->just_cleared = 1;
1372
////////////////////////////////////////////////////////////////////////////////
1373
void CxImageGIF::rle_flush(struct_RLE* rle)
1375
if (rle->rl_count == 1){
1376
rle_output_plain(rle->rl_pixel,rle);
1380
if (rle->just_cleared){
1381
rle_flush_fromclear(rle->rl_count,rle);
1382
} else if ((rle->rl_table_max < 2) || (rle->rl_table_pixel != rle->rl_pixel)) {
1383
rle_flush_clearorrep(rle->rl_count,rle);
1385
rle_flush_withtable(rle->rl_count,rle);
1389
////////////////////////////////////////////////////////////////////////////////
1390
void CxImageGIF::rle_output_plain(int c,struct_RLE* rle)
1392
rle->just_cleared = 0;
1395
if (rle->out_count >= rle->out_bump){
1397
rle->out_bump += 1 << (rle->out_bits - 1);
1399
if (rle->out_count >= rle->out_clear){
1400
rle_output(rle->code_clear,rle);
1404
////////////////////////////////////////////////////////////////////////////////
1405
void CxImageGIF::rle_flush_fromclear(int count,struct_RLE* rle)
1409
rle->out_clear = rle->max_ocodes;
1410
rle->rl_table_pixel = rle->rl_pixel;
1414
rle->rl_table_max = 1;
1415
rle_output_plain(rle->rl_pixel,rle);
1417
} else if (count >= n){
1418
rle->rl_table_max = n;
1419
rle_output_plain(rle->rl_basecode+n-2,rle);
1421
} else if (count == 1){
1422
rle->rl_table_max ++;
1423
rle_output_plain(rle->rl_pixel,rle);
1426
rle->rl_table_max ++;
1427
rle_output_plain(rle->rl_basecode+count-2,rle);
1430
if (rle->out_count == 0) n = 1; else n ++;
1432
rle_reset_out_clear(rle);
1434
////////////////////////////////////////////////////////////////////////////////
1435
void CxImageGIF::rle_reset_out_clear(struct_RLE* rle)
1437
rle->out_clear = rle->out_clear_init;
1438
if (rle->out_count >= rle->out_clear){
1439
rle_output(rle->code_clear,rle);
1443
////////////////////////////////////////////////////////////////////////////////
1444
void CxImageGIF::rle_flush_withtable(int count, struct_RLE* rle)
1450
repmax = count / rle->rl_table_max;
1451
leftover = count % rle->rl_table_max;
1452
repleft = (leftover ? 1 : 0);
1453
if (rle->out_count+repmax+repleft > rle->max_ocodes){
1454
repmax = rle->max_ocodes - rle->out_count;
1455
leftover = count - (repmax * rle->rl_table_max);
1456
repleft = 1 + rle_compute_triangle_count(leftover,rle->max_ocodes);
1458
if (1+rle_compute_triangle_count(count,rle->max_ocodes) < (unsigned int)(repmax+repleft)){
1459
rle_output(rle->code_clear,rle);
1461
rle_flush_fromclear(count,rle);
1464
rle->out_clear = rle->max_ocodes;
1465
for (;repmax>0;repmax--) rle_output_plain(rle->rl_basecode+rle->rl_table_max-2,rle);
1467
if (rle->just_cleared){
1468
rle_flush_fromclear(leftover,rle);
1469
} else if (leftover == 1){
1470
rle_output_plain(rle->rl_pixel,rle);
1472
rle_output_plain(rle->rl_basecode+leftover-2,rle);
1475
rle_reset_out_clear(rle);
1477
////////////////////////////////////////////////////////////////////////////////
1478
unsigned int CxImageGIF::rle_compute_triangle_count(unsigned int count, unsigned int nrepcodes)
1480
unsigned int perrep;
1484
perrep = (nrepcodes * (nrepcodes+1)) / 2;
1485
while (count >= perrep){
1491
n = rle_isqrt(count);
1492
while ((n*(n+1)) >= 2*count) n --;
1493
while ((n*(n+1)) < 2*count) n ++;
1498
////////////////////////////////////////////////////////////////////////////////
1499
unsigned int CxImageGIF::rle_isqrt(unsigned int x)
1504
if (x < 2) return(x);
1505
for (v=x,r=1;v;v>>=2,r<<=1) ;
1507
v = ((x / r) + r) / 2;
1508
if ((v == r) || (v == r+1)) return(r);
1512
////////////////////////////////////////////////////////////////////////////////
1513
void CxImageGIF::rle_flush_clearorrep(int count, struct_RLE* rle)
1516
withclr = 1 + rle_compute_triangle_count(count,rle->max_ocodes);
1517
if (withclr < count) {
1518
rle_output(rle->code_clear,rle);
1520
rle_flush_fromclear(count,rle);
1522
for (;count>0;count--) rle_output_plain(rle->rl_pixel,rle);
1525
////////////////////////////////////////////////////////////////////////////////
1526
void CxImageGIF::rle_write_block(struct_RLE* rle)
1528
g_outfile->PutC((BYTE)rle->oblen);
1529
g_outfile->Write(rle->oblock,1,rle->oblen);
1532
////////////////////////////////////////////////////////////////////////////////
1533
void CxImageGIF::rle_block_out(unsigned char c, struct_RLE* rle)
1535
rle->oblock[rle->oblen++] = c;
1536
if (rle->oblen >= 255) rle_write_block(rle);
1538
////////////////////////////////////////////////////////////////////////////////
1539
void CxImageGIF::rle_block_flush(struct_RLE* rle)
1541
if (rle->oblen > 0) rle_write_block(rle);
1543
////////////////////////////////////////////////////////////////////////////////
1544
void CxImageGIF::rle_output(int val, struct_RLE* rle)
1546
rle->obuf |= val << rle->obits;
1547
rle->obits += rle->out_bits;
1548
while (rle->obits >= 8){
1549
rle_block_out(rle->obuf&0xff,rle);
1554
////////////////////////////////////////////////////////////////////////////////
1555
void CxImageGIF::rle_output_flush(struct_RLE* rle)
1557
if (rle->obits > 0) rle_block_out(rle->obuf,rle);
1558
rle_block_flush(rle);
1560
////////////////////////////////////////////////////////////////////////////////
1561
void CxImageGIF::compressRLE( int init_bits, CxFile* outfile)
1563
g_init_bits = init_bits;
1564
g_outfile = outfile;
1567
rle.code_clear = 1 << (init_bits - 1);
1568
rle.code_eof = rle.code_clear + 1;
1569
rle.rl_basecode = rle.code_eof + 1;
1570
rle.out_bump_init = (1 << (init_bits - 1)) - 1;
1571
rle.out_clear_init = (init_bits <= 3) ? 9 : (rle.out_bump_init-1);
1572
rle.out_bits_init = init_bits;
1573
rle.max_ocodes = (1 << MAXBITSCODES) - ((1 << (rle.out_bits_init - 1)) + 3);
1580
rle_output(rle.code_clear,&rle);
1585
if ((rle.rl_count > 0) && (c != rle.rl_pixel)) rle_flush(&rle);
1586
if (c == EOF) break;
1587
if (rle.rl_pixel == c){
1594
rle_output(rle.code_eof,&rle);
1595
rle_output_flush(&rle);
1597
////////////////////////////////////////////////////////////////////////////////
1598
#endif // CXIMAGE_SUPPORT_GIF