// Save a TIFF image bool fxsaveTIF(FXStream& store,const FXColor* data,FXint width,FXint height,FXushort codec) { tiff_store_handle s_handle; long rows_per_strip,line; const TIFFCodec* coder; TIFF *image; // Must make sense if(!data || width<=0 || height<=0) return false; // Correct for unsupported codecs coder=TIFFFindCODEC(codec); if(coder==NULL) codec=COMPRESSION_PACKBITS; // Due to the infamous UNISYS patent, we can read LZW TIFF's but not // write them back as that would require the LZW compression algorithm! if(codec==COMPRESSION_LZW) codec=COMPRESSION_PACKBITS; //FXTRACE((100,"fxsaveTIF: codec=%d\n",codec)); // Set error/warning handlers TIFFSetErrorHandler(fxerrorhandler); TIFFSetWarningHandler(fxwarninghandler); // Initialize s_handle.store=&store; s_handle.begin=store.position(); s_handle.end=store.position(); s_handle.error=FALSE; // Open image image=TIFFClientOpen("tiff","w",(thandle_t)&s_handle,tif_dummy_read_store,tif_write_store,tif_seek_store,tif_close_store,tif_size_store,tif_map_store,tif_unmap_store); if(!image) return FALSE; // Size of a strip is 16kb rows_per_strip=16*1024/width; if(rows_per_strip<1) rows_per_strip=1; // Set fields TIFFSetField(image,TIFFTAG_IMAGEWIDTH,width); TIFFSetField(image,TIFFTAG_IMAGELENGTH,height); TIFFSetField(image,TIFFTAG_COMPRESSION,codec); TIFFSetField(image,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT); TIFFSetField(image,TIFFTAG_ROWSPERSTRIP,rows_per_strip); TIFFSetField(image,TIFFTAG_BITSPERSAMPLE,8); TIFFSetField(image,TIFFTAG_SAMPLESPERPIXEL,4); TIFFSetField(image,TIFFTAG_PLANARCONFIG,1); TIFFSetField(image,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_RGB); // Dump each line for(line=0; line<height; line++) { if(TIFFWriteScanline(image,(void*)data,line,1)!=1 || s_handle.error) { TIFFClose(image); return false; } data+=width; } TIFFClose(image); return true; }
// Load image from stream bool fxloadBMP(FXStream& store,FXColor*& data,FXint& width,FXint& height){ FXint biXPelsPerMeter,biYPelsPerMeter,biClrUsed,biClrImportant,biCompression,biSize; FXint biWidth,biHeight,biSizeImage,bfOffBits,bfSize,i,j,x,y,maxpixels,colormaplen,padw,pad; FXushort bfType,bfReserved,biBitCount,biPlanes,rgb16; FXColor colormap[256],*pp; FXuchar padding[3],c1,c2; FXlong base,header; bool swap; bool ok=false; // Null out data=NULL; width=0; height=0; // Start of bitmap file header base=store.position(); // Bitmaps are little-endian swap=store.swapBytes(); store.setBigEndian(FALSE); // Get size and offset store >> bfType; store >> bfSize; store >> bfReserved; store >> bfReserved; store >> bfOffBits; // Check signature if(bfType!=0x4d42) goto x; // Start of bitmap info header header=store.position(); // Read bitmap info header store >> biSize; if(biSize==OS2_OLD){ // Old format store >> bfReserved; biWidth=bfReserved; store >> bfReserved; biHeight=bfReserved; store >> biPlanes; store >> biBitCount; biCompression = BIH_RGB; biSizeImage = (((biPlanes*biBitCount*biWidth)+31)/32)*4*biHeight; biXPelsPerMeter = 0; biYPelsPerMeter = 0; biClrUsed = 0; biClrImportant = 0; }
// Load object from stream void FXGLVertices::load(FXStream& store){ FXGLShape::load(store); store >> vertexNumber; FXMALLOC(&vertices, FXVec3f, vertexNumber); store.load((FXfloat *) vertices, 3*vertexNumber); store >> pointSize >> color; }
// Load a TIFF image FXbool fxloadTIF(FXStream& store,FXColor*& data,FXint& width,FXint& height,FXushort& codec){ tiff_store_handle s_handle; FXuval size,s; // Null out data=NULL; width=0; height=0; // Set error/warning handlers TIFFSetErrorHandler(NULL); TIFFSetWarningHandler(NULL); // Initialize s_handle.store=&store; s_handle.begin=store.position(); s_handle.end=store.position(); FXTRACE((100,"fxloadTIF\n")); // Open image TIFF* image=TIFFClientOpen("tiff","rm",(thandle_t)&s_handle,tif_read_store,tif_write_store,tif_seek_store,tif_close_store,tif_size_store,NULL,NULL); if(image){ // Get sizes TIFFGetField(image,TIFFTAG_IMAGEWIDTH,&width); TIFFGetField(image,TIFFTAG_IMAGELENGTH,&height); TIFFGetField(image,TIFFTAG_COMPRESSION,&codec); FXTRACE((100,"fxloadTIF: width=%d height=%d codec=%d\n",width,height,codec)); // Make room for data size=width*height; if(allocElms(data,size)){ if(TIFFReadRGBAImageOriented(image,width,height,data,ORIENTATION_TOPLEFT,0)){ for(s=0; s<size; s++){ data[s]=((data[s]&0xff)<<16)|((data[s]&0xff0000)>>16)|(data[s]&0xff00)|(data[s]&0xff000000); } TIFFClose(image); return true; } freeElms(data); } TIFFClose(image); } return false; }
// save object to stream void FXBaseObject::save(FXStream& store) const { FXObject::save(store); store << app; store << target; store << message; store << flags; store << options; store << datalen; store.save((FXuchar*)data, (unsigned long)datalen); }
// load object from stream void FXBaseObject::load(FXStream& store) { FXObject::load(store); store >> app; store >> target; store >> message; store >> flags; store >> options; store >> datalen; store.load((FXuchar*)data, (unsigned long)datalen); }
// Load data void FXId::load(FXStream& store){ FXuint version; FXObject::load(store); store >> version; if(version!=MAGIC){ store.setError(FXStreamFormat); throw FXResourceException("expected to match MAGIC tag"); } store >> app; }
// Save a bmp file to a stream bool fxsaveRGB(FXStream& store,const FXColor *data,FXint width,FXint height){ const FXushort dimension=3; const FXushort nchannels=3; const FXushort magic=474; const FXuint maxpix=255; const FXuint minpix=0; const FXuint dummy=0; const FXuchar storage=0; const FXuchar bpc=1; FXuchar temp[4096],swap; FXushort w=width; FXushort h=height; FXint i,j,c; // Must make sense if(data && 0<width && 0<height){ // Remember swap state swap=store.swapBytes(); store.setBigEndian(TRUE); // Save header store << magic; // MAGIC (2) store << storage; // STORAGE (1) store << bpc; // BPC (1) store << dimension; // DIMENSION (2) store << w; // XSIZE (2) store << h; // YSIZE (2) store << nchannels; // ZSIZE (2) store << minpix; // PIXMIN (4) store << maxpix; // PIXMAX (4) store << dummy; // DUMMY (4) memset(temp,0,80); // Clean it memcpy(temp,"IRIS RGB",8); // Write name store.save(temp,80); // IMAGENAME (80) store << dummy; // COLORMAP (4) memset(temp,0,404); // Clean it store.save(temp,404); // DUMMY (404) // Write pixels for(c=0; c<3; c++){ for(j=height-1; j>=0; j--){ for(i=0; i<width; i++) temp[i]=((FXuchar*)(data+j*width+i))[c]; store.save(temp,width); } } // Reset swap status store.swapBytes(swap); return true; } return false; }
// Check if stream contains a PNG bool fxcheckPNG(FXStream& store){ FXuchar signature[8]; store.load(signature,8); store.position(-8,FXFromCurrent); return signature[0]==137 && signature[1]==80 && signature[2]==78 && signature[3]==71 && signature[4]==13 && signature[5]==10 && signature[6]==26 && signature[7]==10; }
// Load SUN raster image file format bool fxloadRAS(FXStream& store,FXColor*& data,FXint& width,FXint& height){ FXuchar red[256],green[256],blue[256],*line,count,c,*p,*q,bit; register FXint npixels,depth,linesize,x,y,i; HEADER header; // Null out data=NULL; line=NULL; width=0; height=0; // Read header header.magic=read32(store); header.width=read32(store); header.height=read32(store); header.depth=read32(store); header.length=read32(store); header.type=read32(store); header.maptype=read32(store); header.maplength=read32(store); //FXTRACE((1,"fxloadRAS: magic=%08x width=%d height=%d depth=%d length=%d type=%d maptype=%d maplength=%d\n",header.magic,header.width,header.height,header.depth,header.length,header.type,header.maptype,header.maplength)); // Check magic code if(header.magic!=RAS_MAGIC) return false; // Trivial reject if(header.width<1 || header.height<1) return false; // Bad colormap size if(header.maplength<0 || header.maplength>768) return false; // Verify depth options; must be 1,8,24, or 32 if(header.depth!=1 && header.depth!=8 && header.depth!=24 && header.depth!=32) return false; // Verify supported types if(header.type!=RT_OLD && header.type!=RT_STANDARD && header.type!=RT_BYTE_ENCODED && header.type!=RT_FORMAT_RGB) return false; // Verify map types if(header.maptype!=RMT_RAW && header.maptype!=RMT_NONE && header.maptype!=RMT_EQUAL_RGB) return false; // Get size width=header.width; height=header.height; depth=header.depth; npixels=width*height; linesize=((width*depth+15)/16)*2; //FXTRACE((1,"fxloadRAS: header.length=%d linesize=%d 4*npixels=%d\n",header.length,linesize,4*npixels)); // Read in the colormap if(header.maptype==RMT_EQUAL_RGB && header.maplength){ //FXTRACE((1,"fxloadRAS: RMT_EQUAL_RGB\n")); store.load(red,header.maplength/3); store.load(green,header.maplength/3); store.load(blue,header.maplength/3); } // Skip colormap else if(header.maptype==RMT_RAW && header.maplength){ //FXTRACE((1,"fxloadRAS: RMT_RAW\n")); store.position(header.maplength,FXFromCurrent); } // Black and white else if(header.depth==1){ //FXTRACE((1,"fxloadRAS: 1 bit\n")); red[0]=green[0]=blue[0]=0; red[1]=green[1]=blue[1]=255; } // Gray scale else if(header.depth==8){ //FXTRACE((1,"fxloadRAS: 8 bit\n")); for(i=0; i<256; i++){ red[i]=green[i]=blue[i]=i; } } // Allocate pixel data if(!FXMALLOC(&data,FXColor,npixels)) return false; // Allocate scanline if(!FXMALLOC(&line,FXuchar,linesize)){ FXFREE(&data); return false; } // Now read the image for(y=0,p=(FXuchar*)data,count=c=0; y<height; y++){ if(header.type!=RT_BYTE_ENCODED){ // Load uncompressed store.load(line,linesize); } else{ for(i=0; i<linesize; i++){ // Load RLE compressed if(count){ line[i]=c; count--; } else{ store >> c; if(c==0x80){ store >> count; if(count==0){ line[i]=0x80; } else{ store >> c; line[i]=c; } } else{ line[i]=c; } } } }
// Check if stream contains a JPG FXbool fxcheckJP2(FXStream& store){ FXuchar ss[12]; store.load(ss,12); store.position(-12,FXFromCurrent); return ss[0]==0 && ss[1]==0 && ss[2]==0 && ss[3]==12 && ss[4]=='j' && ss[5]=='P' && ss[6]==' ' && ss[7]==' ' && ss[8]==0x0D && ss[9]==0x0A && ss[10]==0x87 && ss[11]==0x0A; }
// Save image to a stream FXbool fxsaveXPM(FXStream& store,const FXColor *data,FXint width,FXint height,FXbool fast){ const FXchar printable[]=" .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; const FXchar quote='"'; const FXchar comma=','; const FXchar newline='\n'; FXColor colormap[256]; FXint numpixels=width*height; FXint ncolors,cpp,len,i,j,c1,c2; FXchar buffer[200]; FXColor color; FXuchar *pixels,*ptr,pix; // Must make sense if(!data || width<=0 || height<=0) return false; // Allocate temp buffer for pixels if(!allocElms(pixels,numpixels)) return false; // First, try EZ quantization, because it is exact; a previously // loaded XPM will be re-saved with exactly the same colors. if(!fxezquantize(pixels,data,colormap,ncolors,width,height,256)){ if(fast){ fxfsquantize(pixels,data,colormap,ncolors,width,height,256); } else{ fxwuquantize(pixels,data,colormap,ncolors,width,height,256); } } FXASSERT(ncolors<=256); // How many characters needed to represent one pixel, characters per line cpp=(ncolors>MAXPRINTABLE)?2:1; // Save header store.save("/* XPM */\nstatic char * image[] = {\n",36); // Save values len=__snprintf(buffer,sizeof(buffer),"\"%d %d %d %d\",\n",width,height,ncolors,cpp); store.save(buffer,len); // Save the colors for(i=0; i<ncolors; i++){ color=colormap[i]; c1=printable[i%MAXPRINTABLE]; c2=printable[i/MAXPRINTABLE]; if(FXALPHAVAL(color)){ len=__snprintf(buffer,sizeof(buffer),"\"%c%c c #%02x%02x%02x\",\n",c1,c2,FXREDVAL(color),FXGREENVAL(color),FXBLUEVAL(color)); store.save(buffer,len); } else{ len=__snprintf(buffer,sizeof(buffer),"\"%c%c c None\",\n",c1,c2); store.save(buffer,len); } } // Save the image ptr=pixels; for(i=0; i<height; i++){ store << quote; for(j=0; j<width; j++){ pix=*ptr++; if(cpp==1){ store << printable[pix]; } else{ store << printable[pix%MAXPRINTABLE]; store << printable[pix/MAXPRINTABLE]; } } store << quote; if(i<height-1){ store << comma; store << newline; } } store.save("};\n",3); freeElms(pixels); return true; }
// Load GEO TIFF FXbool fxloadTIF__(FXStream& store,FXColor*& data,FXint& width,FXint& height,FXushort& codec){ tiff_store_handle s_handle; FXbool result=false; TIFF* image; // Null out data=NULL; width=0; height=0; codec=0; // Set error/warning handlers TIFFSetErrorHandler(NULL); TIFFSetWarningHandler(NULL); // Initialize s_handle.store=&store; s_handle.begin=store.position(); s_handle.end=store.position(); FXTRACE((100,"fxloadGEOTIF\n")); // Open image if((image=TIFFClientOpen("tiff","rm",(thandle_t)&s_handle,tif_read_store,tif_write_store,tif_seek_store,tif_close_store,tif_size_store,NULL,NULL))!=NULL){ FXushort samples=0; FXushort samplebits=0; FXushort format=0; FXuint scanlinesize; FXuchar *scanline; // Get size TIFFGetField(image,TIFFTAG_IMAGEWIDTH,&width); TIFFGetField(image,TIFFTAG_IMAGELENGTH,&height); TIFFGetField(image,TIFFTAG_SAMPLESPERPIXEL,&samples); TIFFGetField(image,TIFFTAG_BITSPERSAMPLE,&samplebits); TIFFGetField(image,TIFFTAG_SAMPLEFORMAT,&format); // We try to remember the codec for later when we save the image back out... TIFFGetField(image,TIFFTAG_COMPRESSION,&codec); // Get line size (bytes) scanlinesize=TIFFScanlineSize(image); // Show image configuration FXTRACE((100,"width=%d height=%d codec=%u samples=%u samplebits=%u format=%u scanlinesize=%u\n",width,height,codec,samples,samplebits,format,scanlinesize)); // Supported formats if((format==SAMPLEFORMAT_UINT || format==SAMPLEFORMAT_INT || format==SAMPLEFORMAT_IEEEFP) && (samples==1 || samples==3)){ // Allocate scanline buffer if(callocElms(scanline,scanlinesize)){ // Make room for data if(callocElms(data,width*height)){ /* FXuint nPlanarConfig=0; FXuint nCompressFlag=0; FXuint nPhotometric=0; TIFFGetField(image,TIFFTAG_PLANARCONFIG,&nPlanarConfig); TIFFGetField(image,TIFFTAG_COMPRESSION,&nCompressFlag); TIFFGetField(image,TIFFTAG_PHOTOMETRIC,&nPhotometric); FXTRACE((100,"nPlanarConfig=%u\n",nPlanarConfig)); FXTRACE((100,"nCompressFlag=%u\n",nCompressFlag)); FXTRACE((100,"nPhotometric=%u\n",nPhotometric)); switch(nSampleFormat){ case SAMPLEFORMAT_UINT: break; case SAMPLEFORMAT_INT: break; case SAMPLEFORMAT_IEEEFP: break; case SAMPLEFORMAT_VOID: break; case SAMPLEFORMAT_COMPLEXINT: break; case SAMPLEFORMAT_COMPLEXIEEEFP: break; default: break; } */ // Read lines for(FXint y=0; y<height; ++y){ TIFFReadScanline(image,scanline,y,0); if(samples==3){ if(samplebits==8){ for(FXint x=0; x<width; ++x){ ((FXuchar*)&data[y*width+x])[0]=scanline[3*x+2]; // Blue ((FXuchar*)&data[y*width+x])[1]=scanline[3*x+1]; // Green ((FXuchar*)&data[y*width+x])[2]=scanline[3*x+0]; // Red ((FXuchar*)&data[y*width+x])[3]=255; // Alpha } } else if(samplebits==16){ for(FXint x=0; x<width; ++x){ ((FXuchar*)&data[y*width+x])[0]=((FXushort*)scanline)[3*x+2]/257; ((FXuchar*)&data[y*width+x])[1]=((FXushort*)scanline)[3*x+1]/257; ((FXuchar*)&data[y*width+x])[2]=((FXushort*)scanline)[3*x+0]/257; ((FXuchar*)&data[y*width+x])[3]=255; } } } else{ if(samplebits==8){ for(FXint x=0; x<width; ++x){ ((FXuchar*)&data[y*width+x])[0]=scanline[x]; // Blue ((FXuchar*)&data[y*width+x])[1]=scanline[x]; // Green ((FXuchar*)&data[y*width+x])[2]=scanline[x]; // Red ((FXuchar*)&data[y*width+x])[3]=255; // Alpha } } else if(samplebits==16){ for(FXint x=0; x<width; ++x){ ((FXuchar*)&data[y*width+x])[0]=((FXushort*)scanline)[x]/257; ((FXuchar*)&data[y*width+x])[1]=((FXushort*)scanline)[x]/257; ((FXuchar*)&data[y*width+x])[2]=((FXushort*)scanline)[x]/257; ((FXuchar*)&data[y*width+x])[3]=255; } } } } // Got as far as this if success result=true; } } freeElms(scanline); } TIFFClose(image); } return result; }
// Load image from stream bool fxloadRGB(FXStream& store,FXColor*& data,FXint& width,FXint& height){ FXint i,j,c,tablen,sub,t,total; FXuchar temp[4096],*array,storage,bpc,swap; FXuint *starttab,*lengthtab; FXushort magic,dimension,nchannels,w,h; FXlong base,start; // Null out data=NULL; width=0; height=0; // Remember swap state swap=store.swapBytes(); store.setBigEndian(TRUE); // Where the image format starts base=store.position(); // Load header store >> magic; // MAGIC (2) store >> storage; // STORAGE (1) store >> bpc; // BPC (1) store >> dimension; // DIMENSION (2) store >> w; // XSIZE (2) store >> h; // YSIZE (2) store >> nchannels; // ZSIZE (2) FXTRACE((50,"fxloadRGB: magic=%d width=%d height=%d nchannels=%d dimension=%d storage=%d bpc=%d\n",magic,w,h,nchannels,dimension,storage,bpc)); // Check magic number and other parameters if(magic==474 && nchannels==3 && bpc==1 && w>0 && h>0){ // Make room for image if(FXMALLOC(&data,FXColor,w*h)){ // Clear memset(data,0xff,sizeof(FXColor)*w*h); // Skip stuff store.position(500,FXFromCurrent); // RLE compressed if(storage){ tablen=h*3; // Allocate line tables if(FXMALLOC(&starttab,FXuint,tablen*2)){ lengthtab=&starttab[tablen]; // Read line tables store.load(starttab,tablen); store.load(lengthtab,tablen); // Where the RLE chunks start start=store.position(); // Substract this amount to get offset from chunk start sub=start-base; total=0; // Fix up the line table & figure space for RLE chunks // Intelligent RGB writers (not ours ;-)) may re-use RLE // chunks for more than 1 line... for(i=0; i<tablen; i++){ starttab[i]-=sub; t=starttab[i]+lengthtab[i]; if(t>total) total=t; } // Make room for the compressed lines if(FXMALLOC(&array,FXuchar,total)){ // Load all RLE chunks store.load(array,total); for(c=0; c<3; c++){ for(j=h-1; j>=0; j--){ expandrow(((FXuchar*)(data+j*w))+c,&array[starttab[h-1-j+c*h]]); } } // Free RLE chunks FXFREE(&array); } // Free line tables FXFREE(&starttab); } } // NON compressed else{ for(c=0; c<3; c++){ for(j=h-1; j>=0; j--){ store.load(temp,w); for(i=0; i<w; i++) ((FXuchar*)(data+j*w+i))[c]=temp[i]; } } } // Set width and height width=w; height=h; // Reset swap status store.swapBytes(swap); return TRUE; } } // Reset swap status store.swapBytes(swap); return false; }
// Check if stream contains a RGB bool fxcheckRGB(FXStream& store){ FXuchar signature[2]; store.load(signature,2); store.position(-2,FXFromCurrent); return signature[0]==0x01 && signature[1]==0xDA; }
// Save object to stream void FXGLVertices::save(FXStream& store) const { FXGLShape::save(store); store << vertexNumber; store.save((FXfloat *) vertices, 3*vertexNumber); store << pointSize << color; }
// Save a TIFF image FXbool fxsaveTIF(FXStream& store,const FXColor* data,FXint width,FXint height,FXushort codec){ register FXbool result=false; // Must make sense if(data && 0<width && 0<height){ // Correct for unsupported codecs const TIFFCodec* coder=TIFFFindCODEC(codec); if(coder==NULL) codec=COMPRESSION_PACKBITS; // Due to the infamous UNISYS patent, we can read LZW TIFF's but not // write them back as that would require the LZW compression algorithm! if(codec==COMPRESSION_LZW) codec=COMPRESSION_PACKBITS; FXTRACE((100,"fxsaveTIF: codec=%d\n",codec)); // Set error/warning handlers TIFFSetErrorHandler(NULL); TIFFSetWarningHandler(NULL); // Initialize tiff_store_handle s_handle; s_handle.store=&store; s_handle.begin=store.position(); s_handle.end=store.position(); // Open image TIFF* image=TIFFClientOpen("tiff","w",(thandle_t)&s_handle,tif_dummy_read_store,tif_write_store,tif_seek_store,tif_close_store,tif_size_store,NULL,NULL); if(image){ FXColor *buffer=NULL; // Size of a strip is 16kb FXint rows_per_strip=16*1024/width; if(rows_per_strip<1) rows_per_strip=1; // Set fields TIFFSetField(image,TIFFTAG_IMAGEWIDTH,width); TIFFSetField(image,TIFFTAG_IMAGELENGTH,height); TIFFSetField(image,TIFFTAG_COMPRESSION,codec); TIFFSetField(image,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT); TIFFSetField(image,TIFFTAG_ROWSPERSTRIP,rows_per_strip); TIFFSetField(image,TIFFTAG_BITSPERSAMPLE,8); TIFFSetField(image,TIFFTAG_SAMPLESPERPIXEL,4); TIFFSetField(image,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); TIFFSetField(image,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_RGB); // Allocate scanline buffer if(allocElms(buffer,width)){ // Dump each line for(FXint y=0; y<height; data+=width,y++){ // Convert byte order for(FXint x=0; x<width; x++){ buffer[x]=FXREDVAL(data[x]) | FXGREENVAL(data[x])<<8 | FXBLUEVAL(data[x])<<16 | FXALPHAVAL(data[x])<<24; } // Write scanline if(TIFFWriteScanline(image,buffer,y,1)!=1) goto x; } // All done result=true; // Delete scanline buffer x: freeElms(buffer); } // Close image TIFFClose(image); } } return result; }
// 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; }
// Check if stream contains a TIFF bool fxcheckTIF(FXStream& store) { FXuchar signature[2]; store.load(signature,2); store.position(-2,FXFromCurrent); return (signature[0]==0x4d && signature[1]==0x4d) || (signature[0]==0x49 && signature[1]==0x49); }
// Load a TIFF image bool fxloadTIF(FXStream& store,FXColor*& data,FXint& width,FXint& height,FXushort& codec) { tiff_store_handle s_handle; TIFFRGBAImage img; TIFF *image; char emsg[1024]; register FXColor *up,*dn,t; register FXint i; register long size; // Null out data=NULL; width=0; height=0; // Set error/warning handlers TIFFSetErrorHandler(fxerrorhandler); TIFFSetWarningHandler(fxwarninghandler); // Initialize s_handle.store=&store; s_handle.begin=store.position(); s_handle.end=store.position(); s_handle.error=FALSE; // Open image image=TIFFClientOpen("tiff","rm",(thandle_t)&s_handle,tif_read_store,tif_write_store,tif_seek_store,tif_close_store,tif_size_store,tif_map_store,tif_unmap_store); if(!image) return false; // We try to remember the codec for later when we save the image back out... TIFFGetField(image,TIFFTAG_COMPRESSION,&codec); //FXTRACE((100,"fxloadTIF: codec=%d\n",codec)); // FIXME TIFFRGBAImage{Begin,Get,End} is too broken! if(TIFFRGBAImageBegin(&img,image,0,emsg)!=1) { TIFFClose(image); return false; } //FXTRACE((1,"fxloadTIF: width=%u height=%u alpha=%d bitspersample=%u samplesperpixel=%u orientation=%u photometric=%u\n",img.width,img.height,img.alpha,img.bitspersample,img.samplesperpixel,img.orientation,img.photometric)); // Make room for data size=img.width*img.height; if(!FXMALLOC(&data,FXColor,size)) { TIFFClose(image); return false; } // Get the pixels if(TIFFRGBAImageGet(&img,(uint32*)data,img.width,img.height)!=1) { FXFREE(&data); TIFFClose(image); return false; } // If we got this far, we have the data; // nothing can go wrong from here on. width=(FXint)img.width; height=(FXint)img.height; // Maybe flip image upside down? if(img.orientation==ORIENTATION_TOPLEFT) { for(up=data,dn=data+(height-1)*width; up<dn; up+=width,dn-=width) { for(i=0; i<width; i++) { t=up[i]; up[i]=dn[i]; dn[i]=t; } } } TIFFRGBAImageEnd(&img); TIFFClose(image); return true; }
// Load a JPEG image FXbool fxloadJP2(FXStream& store,FXColor*& data,FXint& width,FXint& height,FXint&){ register FXint x,y,cw,rsh,gsh,bsh,ash,rof,gof,bof,aof; register FXuchar r,g,b,a; FXbool swap=store.swapBytes(); FXlong pos=store.position(); FXbool result=false; FXuint box[4]; FXlong boxsize; FXuint size; FXuchar *ptr; // Null out data=NULL; width=0; height=0; // Switch big-endian to grab header store.setBigEndian(true); // Grab signature store.load(box,3); // Check signature, bail quickly if no match if(box[0]==12 && box[1]==BOX_JP && box[2]==SIGNATURE){ // Figure size store.position(0,FXFromEnd); size=store.position()-pos; store.position(pos); FXTRACE((90,"fxloadJP2: file size=%d\n",size)); // Allocate chunk for file data if(allocElms(ptr,size)){ // Load entire file store.load(ptr,size); // Create decompressor opj_dinfo_t *decompressor=opj_create_decompress(CODEC_JP2); if(decompressor){ opj_dparameters_t parameters; opj_event_mgr_t event_mgr; opj_cio_t *cio=NULL; opj_image_t *image=NULL; // Set up callbacks event_mgr.error_handler=j2k_error_callback; event_mgr.warning_handler=j2k_warning_callback; event_mgr.info_handler=j2k_info_callback; // Set event manager opj_set_event_mgr((opj_common_ptr)decompressor,&event_mgr,NULL); // Initialize decompression parameters opj_set_default_decoder_parameters(¶meters); // Setup the decoder decoding parameters using user parameters opj_setup_decoder(decompressor,¶meters); // Open a byte stream */ cio=opj_cio_open((opj_common_ptr)decompressor,ptr,size); if(cio){ // Decode the stream and fill the image structure image=opj_decode(decompressor,cio); if(image){ // Image size width=image->x1-image->x0; height=image->y1-image->y0; FXTRACE((90,"fxloadJP2: width=%d height=%d numcomps=%d color_space=%d\n",width,height,image->numcomps,image->color_space)); // Only support GREY, RGB, and RGBA if(((image->numcomps==1) && (image->color_space==CLRSPC_GRAY)) || ((image->numcomps==3 || image->numcomps==4) && (image->color_space==CLRSPC_SRGB))){ // Allocate image data if(allocElms(data,width*height)){ rof=gof=bof=aof=rsh=gsh=bsh=ash=0; switch(image->numcomps){ case 1: if(image->comps[0].sgnd) gof=1<<(image->comps[0].prec-1); gsh=image->comps[0].prec-8; cw=image->comps[0].w; for(y=0; y<height; ++y){ for(x=0; x<width; ++x){ g=(image->comps[0].data[y*cw+x]+gof)>>gsh; data[y*width+x]=FXRGB(g,g,g); } } break; case 3: if(image->comps[0].sgnd) rof=1<<(image->comps[0].prec-1); if(image->comps[1].sgnd) gof=1<<(image->comps[1].prec-1); if(image->comps[2].sgnd) bof=1<<(image->comps[2].prec-1); rsh=image->comps[0].prec-8; gsh=image->comps[1].prec-8; bsh=image->comps[2].prec-8; cw=image->comps[0].w; for(y=0; y<height; ++y){ for(x=0; x<width; ++x){ r=(image->comps[0].data[y*cw+x]+rof)>>rsh; g=(image->comps[1].data[y*cw+x]+gof)>>gsh; b=(image->comps[2].data[y*cw+x]+bof)>>bsh; data[y*width+x]=FXRGB(r,g,b); } } break; default: if(image->comps[0].sgnd) rof=1<<(image->comps[0].prec-1); if(image->comps[1].sgnd) gof=1<<(image->comps[1].prec-1); if(image->comps[2].sgnd) bof=1<<(image->comps[2].prec-1); if(image->comps[3].sgnd) aof=1<<(image->comps[3].prec-1); rsh=image->comps[0].prec-8; gsh=image->comps[1].prec-8; bsh=image->comps[2].prec-8; ash=image->comps[3].prec-8; cw=image->comps[0].w; for(y=0; y<height; ++y){ for(x=0; x<width; ++x){ r=(image->comps[0].data[y*cw+x]+rof)>>rsh; g=(image->comps[1].data[y*cw+x]+gof)>>gsh; b=(image->comps[2].data[y*cw+x]+bof)>>bsh; a=(image->comps[3].data[y*cw+x]+aof)>>ash; data[y*width+x]=FXRGBA(r,g,b,a); } } break; } result=true; } } opj_image_destroy(image); } opj_cio_close(cio); } opj_destroy_decompress(decompressor); } freeElms(ptr); } }
// Check if stream contains a RAS bool fxcheckRAS(FXStream& store){ FXint signature; signature=read32(store); store.position(-4,FXFromCurrent); return signature==RAS_MAGIC; }