📄 ximagif.cpp
字号:
{ case '!': // extension { DecodeExtension(fp); break; } case ',': // image { assert(sizeof(image) == 9); //log << "Image header" << endl; fp->Read(&image,sizeof(image),1); //avoid byte order problems with Solaris <candan> BYTE *byteData = (BYTE *) & image; image.l = byteData[0]+byteData[1]*256; image.t = byteData[2]+byteData[3]*256; image.w = byteData[4]+byteData[5]*256; image.h = byteData[6]+byteData[7]*256; if (((image.l + image.w) > dscgif->scrwidth)||((image.t + image.h) > dscgif->scrheight)) break; nframes++; // Local colour map? if (image.pf & 0x80) { TempTabCol.sogct = (short)(1 << ((image.pf & 0x07) +1)); assert(3 == sizeof(struct rgb_color)); fp->Read(TempTabCol.paleta,sizeof(struct rgb_color)*TempTabCol.sogct,1); //log << "Local colour map" << endl; } int bpp; //<DP> select the correct bit per pixel value if (TempTabCol.sogct <= 2) bpp = 1; else if (TempTabCol.sogct <= 16) bpp = 4; else bpp = 8; Create(image.w, image.h, bpp, CXIMAGE_FORMAT_GIF); CImageIterator* iter = new CImageIterator(this); iter->Upset(); int badcode=0; ibf = GIFBUFTAM+1; interlaced = image.pf & 0x40; iheight = image.h; istep = 8; iypos = 0; ipass = 0; long pos_start = fp->Tell(); //if (interlaced) log << "Interlaced" << endl; decoder(fp, iter, image.w, badcode); delete iter; if (badcode){ seek_next_image(fp,pos_start); } else { fp->Seek(-(ibfmax - ibf - 1), SEEK_CUR); } break; } case ';': //terminator bContinue=false; break; default: bPreviousWasNull = (ch==0); break; } } } fp->Seek(pos,SEEK_SET); return nframes;}////////////////////////////////////////////////////////////////////////////////long CxImageGIF::seek_next_image(CxFile* fp, long position){ fp->Seek(position, SEEK_SET); char ch1,ch2; ch1=ch2=0; while(fp->Read(&ch2,sizeof(char),1)>0){ if (ch1 == 0 && ch2 == ','){ fp->Seek(-1,SEEK_CUR); return fp->Tell(); } else { ch1 = ch2; } } return -1;}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::SetLoops(int loops){ m_loops=loops; }////////////////////////////////////////////////////////////////////////////////long CxImageGIF::GetLoops(){ return m_loops; }////////////////////////////////////////////////////////////////////////////////void CxImageGIF::SetComment(const char* sz_comment_in){ if (sz_comment_in) strncpy(m_comment,sz_comment_in,255); }////////////////////////////////////////////////////////////////////////////////void CxImageGIF::GetComment(char* sz_comment_out){ if (sz_comment_out) strncpy(sz_comment_out,m_comment,255); }////////////////////////////////////////////////////////////////////////////////void CxImageGIF::GifMix(CxImage & imgsrc2, struct_image & imgdesc){ long ymin = max(0,(long)(GetHeight()-imgdesc.t - imgdesc.h)); long ymax = GetHeight()-imgdesc.t; long xmin = imgdesc.l; long xmax = min(GetWidth(), (DWORD)(imgdesc.l + imgdesc.w)); long ibg2= imgsrc2.GetTransIndex(); BYTE i2; for(long y = ymin; y < ymax; y++){ for(long x = xmin; x < xmax; x++){ i2 = imgsrc2.GetPixelIndex(x-xmin,y-ymin); if(i2!=ibg2) SetPixelIndex(x,y,i2); } }}/////////////////////////////////////////////////////////////////////////////////*----------------------------------------------------------------------- * * miGIF Compression - mouse and ivo's GIF-compatible compression * * -run length encoding compression routines- * * Copyright (C) 1998 Hutchison Avenue Software Corporation * http://www.hasc.com * info@hasc.com * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. This software is provided "AS IS." The Hutchison Avenue * Software Corporation disclaims all warranties, either express or implied, * including but not limited to implied warranties of merchantability and * fitness for a particular purpose, with respect to this code and accompanying * documentation. * * The miGIF compression routines do not, strictly speaking, generate files * conforming to the GIF spec, since the image data is not LZW-compressed * (this is the point: in order to avoid transgression of the Unisys patent * on the LZW algorithm.) However, miGIF generates data streams that any * reasonably sane LZW decompresser will decompress to what we want. * * miGIF compression uses run length encoding. It compresses horizontal runs * of pixels of the same color. This type of compression gives good results * on images with many runs, for example images with lines, text and solid * shapes on a solid-colored background. It gives little or no compression * on images with few runs, for example digital or scanned photos. * * der Mouse * mouse@rodents.montreal.qc.ca * 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B * * ivo@hasc.com * * The Graphics Interchange Format(c) is the Copyright property of * CompuServe Incorporated. GIF(sm) is a Service Mark property of * CompuServe Incorporated. * */////////////////////////////////////////////////////////////////////////////////void CxImageGIF::rle_clear(struct_RLE* rle){ rle->out_bits = rle->out_bits_init; rle->out_bump = rle->out_bump_init; rle->out_clear = rle->out_clear_init; rle->out_count = 0; rle->rl_table_max = 0; rle->just_cleared = 1;}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::rle_flush(struct_RLE* rle){ if (rle->rl_count == 1){ rle_output_plain(rle->rl_pixel,rle); rle->rl_count = 0; return; } if (rle->just_cleared){ rle_flush_fromclear(rle->rl_count,rle); } else if ((rle->rl_table_max < 2) || (rle->rl_table_pixel != rle->rl_pixel)) { rle_flush_clearorrep(rle->rl_count,rle); } else { rle_flush_withtable(rle->rl_count,rle); } rle->rl_count = 0;}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::rle_output_plain(int c,struct_RLE* rle){ rle->just_cleared = 0; rle_output(c,rle); rle->out_count++; if (rle->out_count >= rle->out_bump){ rle->out_bits ++; rle->out_bump += 1 << (rle->out_bits - 1); } if (rle->out_count >= rle->out_clear){ rle_output(rle->code_clear,rle); rle_clear(rle); }}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::rle_flush_fromclear(int count,struct_RLE* rle){ int n; rle->out_clear = rle->max_ocodes; rle->rl_table_pixel = rle->rl_pixel; n = 1; while (count > 0){ if (n == 1){ rle->rl_table_max = 1; rle_output_plain(rle->rl_pixel,rle); count --; } else if (count >= n){ rle->rl_table_max = n; rle_output_plain(rle->rl_basecode+n-2,rle); count -= n; } else if (count == 1){ rle->rl_table_max ++; rle_output_plain(rle->rl_pixel,rle); count = 0; } else { rle->rl_table_max ++; rle_output_plain(rle->rl_basecode+count-2,rle); count = 0; } if (rle->out_count == 0) n = 1; else n ++; } rle_reset_out_clear(rle);}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::rle_reset_out_clear(struct_RLE* rle){ rle->out_clear = rle->out_clear_init; if (rle->out_count >= rle->out_clear){ rle_output(rle->code_clear,rle); rle_clear(rle); }}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::rle_flush_withtable(int count, struct_RLE* rle){ int repmax; int repleft; int leftover; repmax = count / rle->rl_table_max; leftover = count % rle->rl_table_max; repleft = (leftover ? 1 : 0); if (rle->out_count+repmax+repleft > rle->max_ocodes){ repmax = rle->max_ocodes - rle->out_count; leftover = count - (repmax * rle->rl_table_max); repleft = 1 + rle_compute_triangle_count(leftover,rle->max_ocodes); } if (1+rle_compute_triangle_count(count,rle->max_ocodes) < (unsigned int)(repmax+repleft)){ rle_output(rle->code_clear,rle); rle_clear(rle); rle_flush_fromclear(count,rle); return; } rle->out_clear = rle->max_ocodes; for (;repmax>0;repmax--) rle_output_plain(rle->rl_basecode+rle->rl_table_max-2,rle); if (leftover){ if (rle->just_cleared){ rle_flush_fromclear(leftover,rle); } else if (leftover == 1){ rle_output_plain(rle->rl_pixel,rle); } else { rle_output_plain(rle->rl_basecode+leftover-2,rle); } } rle_reset_out_clear(rle);}////////////////////////////////////////////////////////////////////////////////unsigned int CxImageGIF::rle_compute_triangle_count(unsigned int count, unsigned int nrepcodes){ unsigned int perrep; unsigned int cost; cost = 0; perrep = (nrepcodes * (nrepcodes+1)) / 2; while (count >= perrep){ cost += nrepcodes; count -= perrep; } if (count > 0){ unsigned int n; n = rle_isqrt(count); while ((n*(n+1)) >= 2*count) n --; while ((n*(n+1)) < 2*count) n ++; cost += n; } return(cost);}////////////////////////////////////////////////////////////////////////////////unsigned int CxImageGIF::rle_isqrt(unsigned int x){ unsigned int r; unsigned int v; if (x < 2) return(x); for (v=x,r=1;v;v>>=2,r<<=1) ; while (1){ v = ((x / r) + r) / 2; if ((v == r) || (v == r+1)) return(r); r = v; }}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::rle_flush_clearorrep(int count, struct_RLE* rle){ int withclr; withclr = 1 + rle_compute_triangle_count(count,rle->max_ocodes); if (withclr < count) { rle_output(rle->code_clear,rle); rle_clear(rle); rle_flush_fromclear(count,rle); } else { for (;count>0;count--) rle_output_plain(rle->rl_pixel,rle); }}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::rle_write_block(struct_RLE* rle){ g_outfile->PutC((BYTE)rle->oblen); g_outfile->Write(rle->oblock,1,rle->oblen); rle->oblen = 0;}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::rle_block_out(unsigned char c, struct_RLE* rle){ rle->oblock[rle->oblen++] = c; if (rle->oblen >= 255) rle_write_block(rle);}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::rle_block_flush(struct_RLE* rle){ if (rle->oblen > 0) rle_write_block(rle);}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::rle_output(int val, struct_RLE* rle){ rle->obuf |= val << rle->obits; rle->obits += rle->out_bits; while (rle->obits >= 8){ rle_block_out(rle->obuf&0xff,rle); rle->obuf >>= 8; rle->obits -= 8; }}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::rle_output_flush(struct_RLE* rle){ if (rle->obits > 0) rle_block_out(rle->obuf,rle); rle_block_flush(rle);}////////////////////////////////////////////////////////////////////////////////void CxImageGIF::compressRLE( int init_bits, CxFile* outfile){ g_init_bits = init_bits; g_outfile = outfile; struct_RLE rle; rle.code_clear = 1 << (init_bits - 1); rle.code_eof = rle.code_clear + 1; rle.rl_basecode = rle.code_eof + 1; rle.out_bump_init = (1 << (init_bits - 1)) - 1; rle.out_clear_init = (init_bits <= 3) ? 9 : (rle.out_bump_init-1); rle.out_bits_init = init_bits; rle.max_ocodes = (1 << MAXBITSCODES) - ((1 << (rle.out_bits_init - 1)) + 3); rle.rl_count = 0; rle_clear(&rle); rle.obuf = 0; rle.obits = 0; rle.oblen = 0; rle_output(rle.code_clear,&rle); int c; while (1){ c = GifNextPixel(); if ((rle.rl_count > 0) && (c != rle.rl_pixel)) rle_flush(&rle); if (c == EOF) break; if (rle.rl_pixel == c){ rle.rl_count++; } else { rle.rl_pixel = c; rle.rl_count = 1; } } rle_output(rle.code_eof,&rle); rle_output_flush(&rle);}////////////////////////////////////////////////////////////////////////////////#endif // CXIMAGE_SUPPORT_GIF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -