static Layer * pyramid_new( Write *write, Layer *above, int width, int height ) { Layer *layer; layer = VIPS_NEW( write->im, Layer ); layer->write = write; layer->width = width; layer->height = height; if( !above ) /* Top of pyramid. */ layer->sub = 1; else layer->sub = above->sub * 2; layer->lname = NULL; layer->tif = NULL; layer->image = NULL; layer->write_y = 0; layer->y = 0; layer->strip = NULL; layer->copy = NULL; layer->below = NULL; layer->above = above; if( write->pyramid ) if( layer->width > write->tilew || layer->height > write->tileh ) layer->below = pyramid_new( write, layer, width / 2, height / 2 ); /* The name for the top layer is the output filename. * * We need lname to be freed automatically: it has to stay * alive until after write_gather(). */ if( !above ) layer->lname = vips_strdup( VIPS_OBJECT( write->im ), write->filename ); else { char *lname; lname = vips__temp_name( "%s.tif" ); layer->lname = vips_strdup( VIPS_OBJECT( write->im ), lname ); g_free( lname ); } return( layer ); }
int main (void) { g_print ("This test may take a few moments...\n"); GString *meta_name = g_string_new (TEST_IMG_BASENAME); g_string_append (meta_name, ".meta"); GString *data_name = g_string_new (TEST_IMG_BASENAME); g_string_append (data_name, ".img"); meta_parameters *md = meta_read_wrapper (meta_name->str); g_string_free (meta_name, TRUE); ssize_t tisx = md->general->sample_count; ssize_t tisy = md->general->line_count; FloatImage *tiafi = float_image_new_from_file (tisx, tisy, data_name->str, 0, FLOAT_IMAGE_BYTE_ORDER_BIG_ENDIAN); g_string_free (data_name, TRUE); float_image_export_as_jpeg (tiafi, "test_pyramid_base_layer_direct.jpg", GSL_MAX (tisx, tisy), TEST_IMG_BOGUS_MASK_VALUE); meta_free (md); Pyramid *p = pyramid_new (TEST_IMG_BASENAME, SCRATCH_DIR); // "Testing" currently consists of creating jpeg images of each // layer and checking to see if they look decent. size_t ii; for ( ii = 0 ; ii < p->layers->len ; ii++ ) { pyramid_layer *cl = g_ptr_array_index (p->layers, ii); float *region; size_t rstart_x, rstart_y, rw, rh; gboolean unowned_memory; pyramid_get_region (p, 0, 0, tisx, tisy, pow (2, ii), ®ion, &rstart_x, &rstart_y, &rw, &rh, &unowned_memory); g_assert (rstart_x == 0 & rstart_y == 0); g_assert (rstart_x + rw * pow (2.0, ii) >= tisx); g_assert (rstart_y + rh * pow (2.0, ii) >= tisy); FloatImage *layer_image = float_image_new_from_memory (rw, rh, region); if ( unowned_memory ) { g_free (region); } GString *layer_file_name = g_string_new (""); g_string_append_printf (layer_file_name, "layer_%d.jpg", ii); ssize_t max_dimension = rw > rh ? rw : rh; int return_code = float_image_export_as_jpeg (layer_image, layer_file_name->str, max_dimension, TEST_IMG_BOGUS_MASK_VALUE); g_assert (return_code == 0); float_image_unref (layer_image); g_string_free (layer_file_name, TRUE); } g_print ("JPEG images of pyramid layers formed, now look at them and\n" "'touch test_pyramid_stamp' if they are ok.\n"); exit (EXIT_SUCCESS); }
/* 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 ); }