// Load image from stream FXbool fxloadXPM(FXStream& store,FXColor*& data,FXint& width,FXint& height){ FXchar lookuptable[1024][8],line[100],name[100],word[100],flag,best,ch; FXColor colortable[16384],*pix,color; const FXchar *src; FXint i,j,ncolors,cpp,c; // Null out data=NULL; width=0; height=0; color=0; // Read header line readline(store,name,sizeof(name)); if(!strstr(name,"XPM")) return false; // Read description readtext(store,line,sizeof(line)); // Parse size description if(__sscanf(line,"%d %d %u %u",&width,&height,&ncolors,&cpp)!=4) return false; // Check size if(width<1 || height<1 || width>16384 || height>16384) return false; // Sensible inputs if(cpp<1 || cpp>8 || ncolors<1) return false; // Limited number of colors for long lookup strings if(cpp>2 && ncolors>1024) return false; // Allow more colors for short lookup strings if(ncolors>16384) return false; //FXTRACE((100,"fxloadXPM: width=%d height=%d ncolors=%d cpp=%d\n",width,height,ncolors,cpp)); // Read the color table for(c=0; c<ncolors; c++){ readtext(store,line,sizeof(line)); src=line+cpp; nextword(src,word); best='z'; while(iskey(word)){ flag=word[0]; name[0]=0; while(nextword(src,word) && !iskey(word)){ strncat(name,word,sizeof(name)); } if(flag<best){ // c < g < m < s color=fxcolorfromname(name); best=flag; } } if(cpp==1){ colortable[(FXuchar)line[0]]=color; } else if(cpp==2){ colortable[(((FXuchar)line[1])<<7)+(FXuchar)line[0]]=color; } else{ colortable[c]=color; strncpy(lookuptable[c],line,cpp); } } // Try allocate pixels if(!allocElms(data,width*height)){ return false; } // Read the pixels for(i=0,pix=data; i<height; i++){ while(!store.eof() && (store>>ch,ch!='"')){} for(j=0; j<width; j++){ store.load(line,cpp); if(cpp==1){ color=colortable[(FXuchar)line[0]]; } else if(cpp==2){ color=colortable[(((FXuchar)line[1])<<7)+(FXuchar)line[0]]; } else{ for(c=0; c<ncolors; c++){ if(strncmp(lookuptable[c],line,cpp)==0){ color=colortable[c]; break; } } } *pix++=color; } while(!store.eof() && (store>>ch,ch!='"')){} } // We got the image, but we're not done yet; need to read few more bytes // the number of bytes read here must match the number of bytes written // by fxsaveXPM() so that the stream won't get out of sync while(!store.eof()){ store >> ch; if(ch=='\n') break; } return true; }
// Load image from stream bool fxloadGIF(FXStream& store,FXColor*& data,FXint& width,FXint& height){ const FXint Yinit[4]={0,4,2,1}; const FXint Yinc[4]={8,8,4,2}; FXint imwidth,imheight,interlace,ncolors,npixels,maxpixels,i; FXuchar c1,c2,c3,sbsize,flags,alpha,*ptr,*buf,*pix; FXColor colormap[256]; FXint BitOffset; // Bit Offset of next code FXint ByteOffset; // Byte offset of next code FXint XC,YC; // Output X and Y coords of current pixel FXint Pass; // Used by output routine if interlaced pic FXint OutCount; // Decompressor output 'stack count' FXint CodeSize; // Code size, read from GIF header FXint InitCodeSize; // Starting code size, used during Clear FXint Code; // Value returned by ReadCode FXint MaxCode; // limiting value for current code size FXint ClearCode; // GIF clear code FXint EOFCode; // GIF end-of-information code FXint CurCode,OldCode,InCode; // Decompressor variables FXint FirstFree; // First free code, generated per GIF spec FXint FreeCode; // Decompressor,next free slot in hash table FXint FinChar; // Decompressor variable FXint BitMask; // AND mask for data size FXint ReadMask; // Code AND mask for current code size FXint Prefix[4096]; // The hash table used by the decompressor FXint Suffix[4096]; // The hash table used by the decompressor FXint OutCode[4097]; // An output array used by the decompressor // Null out data=NULL; width=0; height=0; // Load signature store >> c1; store >> c2; store >> c3; // Check signature if(c1!=TAG_SIG1 || c2!=TAG_SIG2 || c3!=TAG_SIG3) return false; // Load version store >> c1; store >> c2; store >> c3; // Check version if(c1!=TAG_VER || (c2!=TAG_OLD && c2!=TAG_NEW) || c3!=TAG_SUF) return false; // Get screen descriptor store >> c1 >> c2; // Skip screen width store >> c1 >> c2; // Skip screen height store >> flags; // Get flags store >> alpha; // Background store >> c2; // Skip aspect ratio // Determine number of colors ncolors=2<<(flags&7); BitMask=ncolors-1; // If no colormap, spec says first 2 colors are black and white colormap[0]=FXRGB(0,0,0); colormap[1]=FXRGB(255,255,255); // Read global map if there is one if(flags&0x80){ for(i=0; i<ncolors; i++){ store >> ((FXuchar*)(colormap+i))[0]; // Blue store >> ((FXuchar*)(colormap+i))[1]; // Green store >> ((FXuchar*)(colormap+i))[2]; // Red ((FXuchar*)(colormap+i))[3]=255; // Alpha } } // Process it while(1){ store >> c1; if(c1==TAG_EXTENSION){ // Read extension code store >> c2; // Graphic Control Extension if(c2==TAG_GRAPHIC){ store >> sbsize; if(sbsize!=TAG_GRAPHICSIZE) return false; store >> flags; // Flags store >> c3 >> c3; // Delay time store >> alpha; // Alpha color index; we suspect alpha<ncolors not always true... store >> c3; if(flags&1){ // Clear alpha channel of alpha color colormap[alpha]&=FXRGBA(255,255,255,0); // Clear the alpha channel but keep the RGB } continue; } // Other extension do{ store >> sbsize; store.position(store.position()+sbsize); } while(sbsize>0 && !store.eof()); // FIXME this logic still flawed continue; }