int combineblk(RECPOS ads, int size) { ENTRY e; RECPOS address; int esize, off, ret, saveoff, ibuff; ret = 0; saveoff = CO(--(pci->level)); retrieve_block(pci->level, CB(pci->level)); if ((off = next_entry( saveoff )) < block_ptr->bend) /* combine with page on right */ { if ((ENT_SIZE(ENT_ADR(block_ptr, off)) + size) < (uint32_t)split_size) { copy_entry(&e, ENT_ADR(block_ptr, off)); address = ENT_ADR(block_ptr, CO(pci->level))->idxptr; retrieve_block(++pci->level, address); ibuff = cache_ptr; spare_block = block_ptr; retrieve_block(pci->level, ads); esize = ENT_SIZE(&e); if(((block_ptr->bend + spare_block->bend + esize) >= split_size)&& (spare_block->bend <= block_ptr->bend + esize)) { return ret; } e.idxptr = spare_block->p0; ins_block(block_ptr, &e, block_ptr->bend); update_block(); if ((block_ptr->bend + spare_block->bend) < split_size) /* combine the blocks */ { memcpy(ENT_ADR(block_ptr, block_ptr->bend),ENT_ADR(spare_block, 0),spare_block->bend); block_ptr->bend += spare_block->bend; write_free(spare_block->brec, spare_block); BUFDIRTY(ibuff) = 0; BUFHANDLE(ibuff) = 0; --pci->level; ret = 1; } else /* move an entry up to replace the one moved */ { copy_entry(&e, ENT_ADR(spare_block, 0)); esize = ENT_SIZE(&e); movedown(spare_block, 0, esize); spare_block->bend -= esize; spare_block->p0 = e.idxptr; BUFDIRTY(ibuff) = 1; --(pci->level); replace_entry(&e); } } } else /* move from page on left */ { if ( (ENT_SIZE(ENT_ADR(block_ptr, CO(pci->level))) + size) < (uint32_t)split_size) { copy_entry(&e, ENT_ADR(block_ptr, saveoff)); off = prev_entry(saveoff); if (CO(pci->level) == -1) address = block_ptr->p0; else address = ENT_ADR(block_ptr, CO(pci->level))->idxptr; retrieve_block(++pci->level, address); off = last_entry(); ibuff = cache_ptr; spare_block = block_ptr; retrieve_block(pci->level, ads); esize = ENT_SIZE(&e); if(((block_ptr->bend + spare_block->bend + esize) >= split_size)&& (spare_block->bend <= block_ptr->bend + esize)) { return ret; } BUFDIRTY(ibuff) = 1; CO(pci->level) = 0; e.idxptr = block_ptr->p0; ins_block(block_ptr, &e, 0); if ((block_ptr->bend + spare_block->bend) < split_size) /* combine the blocks */ { memcpy(ENT_ADR(spare_block, spare_block->bend),ENT_ADR(block_ptr, 0),block_ptr->bend); spare_block->bend += block_ptr->bend; write_free(block_ptr->brec, block_ptr); BUFDIRTY(cache_ptr) = 0; BUFHANDLE(cache_ptr) = 0; CO(--(pci->level)) = saveoff; ret = 1; } else /* move an entry up to replace the one moved */ { block_ptr->p0 = ENT_ADR(spare_block,off)->idxptr; copy_entry(&e, ENT_ADR(spare_block, off)); spare_block->bend = off; update_block(); CO(--(pci->level)) = saveoff; replace_entry(&e); } } } root_dirty = 1; return ret; }
/* Make and init a Write. */ static Write * write_new( VipsImage *im, const char *filename, VipsForeignTiffCompression compression, int Q, VipsForeignTiffPredictor predictor, char *profile, gboolean tile, int tile_width, int tile_height, gboolean pyramid, gboolean squash, gboolean miniswhite, VipsForeignTiffResunit resunit, double xres, double yres, gboolean bigtiff, gboolean rgbjpeg, gboolean properties, gboolean strip ) { Write *write; if( !(write = VIPS_NEW( im, Write )) ) return( NULL ); write->im = im; write->filename = vips_strdup( VIPS_OBJECT( im ), filename ); write->layer = NULL; write->tbuf = NULL; write->compression = get_compression( compression ); write->jpqual = Q; write->predictor = predictor; write->tile = tile; write->tilew = tile_width; write->tileh = tile_height; write->pyramid = pyramid; write->onebit = squash; write->miniswhite = miniswhite; write->icc_profile = vips_strdup( NULL, profile ); write->bigtiff = bigtiff; write->rgbjpeg = rgbjpeg; write->properties = properties; write->strip = strip; write->resunit = get_resunit( resunit ); write->xres = xres; write->yres = yres; /* In strip mode we use tileh to set rowsperstrip, and that does not * have the multiple-of-16 restriction. */ if( tile ) { if( (write->tilew & 0xf) != 0 || (write->tileh & 0xf) != 0 ) { vips_error( "vips2tiff", "%s", _( "tile size not a multiple of 16" ) ); return( NULL ); } } /* We can only pyramid LABQ and non-complex images. */ if( write->pyramid ) { if( im->Coding == VIPS_CODING_NONE && vips_band_format_iscomplex( im->BandFmt ) ) { vips_error( "vips2tiff", "%s", _( "can only pyramid LABQ and " "non-complex images" ) ); return( NULL ); } } /* Only 1-bit-ize 8 bit mono images. */ if( write->onebit && (im->Coding != VIPS_CODING_NONE || im->BandFmt != VIPS_FORMAT_UCHAR || im->Bands != 1) ) { vips_warn( "vips2tiff", "%s", _( "can only squash 1 band uchar images -- " "disabling squash" ) ); write->onebit = 0; } if( write->onebit && write->compression == COMPRESSION_JPEG ) { vips_warn( "vips2tiff", "%s", _( "can't have 1-bit JPEG -- disabling JPEG" ) ); write->compression = COMPRESSION_NONE; } /* We can only MINISWHITE non-complex images of 1 or 2 bands. */ if( write->miniswhite && (im->Coding != VIPS_CODING_NONE || vips_band_format_iscomplex( im->BandFmt ) || im->Bands > 2) ) { vips_warn( "vips2tiff", "%s", _( "can only save non-complex greyscale images " "as miniswhite -- disabling miniswhite" ) ); write->miniswhite = FALSE; } /* Sizeof a line of bytes in the TIFF tile. */ if( im->Coding == VIPS_CODING_LABQ ) write->tls = write->tilew * 3; else if( write->onebit ) write->tls = VIPS_ROUND_UP( write->tilew, 8 ) / 8; else write->tls = VIPS_IMAGE_SIZEOF_PEL( im ) * write->tilew; /* Build the pyramid framework. */ write->layer = pyramid_new( write, NULL, im->Xsize, im->Ysize ); /* Fill all the layers. */ if( pyramid_fill( write ) ) { write_free( write ); return( NULL ); } if( tile ) write->tbuf = vips_malloc( NULL, TIFFTileSize( write->layer->tif ) ); else write->tbuf = vips_malloc( NULL, TIFFScanlineSize( write->layer->tif ) ); if( !write->tbuf ) { write_free( write ); return( NULL ); } return( write ); }
/* BPLUS delete key functions */ int delete_key(ENTRY *pe, IX_DESC *pix) { ENTRY e; RECPOS ads; int h, leveli, levelf; if (!find_exact(pe, pix)) { return (IX_NOTEXISTED); } h = 1; if ((ads = pe->idxptr) != NULLREC) { leveli = pci->level; do { retrieve_block(++(pci->level), ads); CO(pci->level) = -1; } while ((ads = block_ptr->p0) != NULLREC); CO(pci->level) = 0; copy_entry(&e, ENT_ADR(block_ptr, CO(pci->level))); levelf = pci->level; pci->level = leveli; replace_entry(&e); pci->level = levelf; /*update_root(&pci->root);*/ } while ( h ) { retrieve_block(pci->level, CB(pci->level)); del_block(block_ptr, CO(pci->level)); update_block(); if ( (pci->level == 0) && (block_ptr->bend == 0)) /* tree was reduced in height */ { if (pci->root.p0 != NULLREC) { retrieve_block(++pci->level, pci->root.p0); memcpy(&(pci->root), block_ptr, sizeof(BLOCK)); (pci->dx.nl)--; write_free(block_ptr->brec, block_ptr); BUFDIRTY(cache_ptr) = 0; BUFHANDLE(cache_ptr) = 0; update_root(&pci->root); } break; } h = (block_ptr->bend < comb_size) && (pci->level > 0); if ( h ) { h = combineblk(CB(pci->level), block_ptr->bend); } } /*return flush_index(pix);*/ if(root_dirty == 1) { flush_index(pix); root_dirty = 0; } return(IX_OK); }
int vips__tiff_write( VipsImage *in, const char *filename, VipsForeignTiffCompression compression, int Q, VipsForeignTiffPredictor predictor, char *profile, gboolean tile, int tile_width, int tile_height, gboolean pyramid, gboolean squash, gboolean miniswhite, VipsForeignTiffResunit resunit, double xres, double yres, gboolean bigtiff, gboolean rgbjpeg, gboolean properties, gboolean strip ) { Write *write; #ifdef DEBUG printf( "tiff2vips: libtiff version is \"%s\"\n", TIFFGetVersion() ); #endif /*DEBUG*/ vips__tiff_init(); if( vips_check_coding_known( "vips2tiff", in ) ) return( -1 ); /* Make output image. */ if( !(write = write_new( in, filename, compression, Q, predictor, profile, tile, tile_width, tile_height, pyramid, squash, miniswhite, resunit, xres, yres, bigtiff, rgbjpeg, properties, strip )) ) return( -1 ); if( vips_sink_disc( write->im, write_strip, write ) ) { write_free( write ); return( -1 ); } if( !TIFFWriteDirectory( write->layer->tif ) ) return( -1 ); if( write->pyramid ) { /* Free lower pyramid resources ... this will TIFFClose() (but * not delete) the smaller layers ready for us to read from * them again. */ if( write->layer->below ) pyramid_free( write->layer->below ); /* Append smaller layers to the main file. */ if( write_gather( write ) ) { write_free( write ); return( -1 ); } } write_free( write ); return( 0 ); }