// 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; }
// 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 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); } }
// 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; }