vips_copy() can turn bands into width
handy for slicing up very large 3D arrays
This commit is contained in:
parent
6bf1f8afa5
commit
045678d438
@ -3,6 +3,7 @@
|
||||
- change the alpha range rules for vips_flatten() to match vips_premultiply()
|
||||
- vipsthumbnail uses vips_resize() rather than its own code
|
||||
- vipsthumbnail uses vips_premultiply() for better alpha quality
|
||||
- vips_copy() can turn 1xN or Nx1 M-band images into MxN one-band images
|
||||
|
||||
4/5/15 started 8.0.2
|
||||
- fix a refcount error in C++ wrapper, thanks huskier
|
||||
|
26
TODO
26
TODO
@ -1,24 +1,12 @@
|
||||
- try making a 1000 x 500 x 500 float image on disc, then
|
||||
- how about something like vips_grid() which turns a tall thin one-band
|
||||
image into a much smaller many-band image?
|
||||
|
||||
https://gist.github.com/jcupitt/93e7248bf9eddc34c4cb
|
||||
|
||||
see:
|
||||
|
||||
$ time ./slice.py ~/pics/1000x500x500.v
|
||||
vips warning: VipsImage: /Users/john/pics/1000x500x500.v is longer than
|
||||
expected
|
||||
Traceback (most recent call last):
|
||||
File "./slice.py", line 26, in <module> row.falsecolour().write_to_file("row.v")
|
||||
File "/usr/local/lib/python2.7/site-packages/gi/overrides/Vips.py", line 570, in write_to_file _call_base(saver, [filename], kwargs, self, option_string)
|
||||
File "/usr/local/lib/python2.7/site-packages/gi/overrides/Vips.py", line 338, in _call_base
|
||||
raise Error('Error calling operator %s.' % name)
|
||||
gi.overrides.Vips.Error: Error calling operator
|
||||
VipsForeignSaveVips.
|
||||
VipsRegion: images do not match in pixel size
|
||||
VipsRegion: valid clipped to nothing
|
||||
|
||||
caching is breaking with copy() stuff, somehow?
|
||||
at the moment making a 500-band image uses huge amounts of memory :-( since
|
||||
we have at least 500 bytes per pixel, times 128x128 for each tile, times N
|
||||
for the number of threads, times 500, since we need a 500-stage pipeline
|
||||
|
||||
much faster to make a very tall, thin image and fold it up in a single
|
||||
operation
|
||||
|
||||
- are the mosaic functions calling vips_fastcor()? it must be very slow
|
||||
|
||||
|
@ -47,6 +47,8 @@
|
||||
* - rewrite as a class
|
||||
* 1/12/11
|
||||
* - use glib byteswap macros
|
||||
* 15/5/15
|
||||
* - support bands -> width conversion
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -87,6 +89,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
@ -185,6 +188,70 @@ static SwapFn vips_copy_swap_fn[] = {
|
||||
vips_copy_swap8 /* VIPS_FORMAT_DPCOMPLEX = 9, */
|
||||
};
|
||||
|
||||
/* Copy, turning bands into the x axis.
|
||||
*/
|
||||
static int
|
||||
vips_copy_unbandize_gen( VipsRegion *or,
|
||||
void *seq, void *a, void *b, gboolean *stop )
|
||||
{
|
||||
VipsRegion *ir = (VipsRegion *) seq;
|
||||
VipsImage *in = ir->im;
|
||||
VipsRect *r = &or->valid;
|
||||
VipsCopy *copy = (VipsCopy *) b;
|
||||
SwapFn swap = vips_copy_swap_fn[copy->in->BandFmt];
|
||||
|
||||
VipsRect need;
|
||||
int y;
|
||||
|
||||
/* Ask for input we need.
|
||||
*/
|
||||
if( in->Xsize == 1 ) {
|
||||
need.left = 0;
|
||||
need.top = r->top;
|
||||
need.width = 1;
|
||||
need.height = r->height;
|
||||
}
|
||||
else {
|
||||
need.left = r->top;
|
||||
need.top = 0;
|
||||
need.width = r->height;
|
||||
need.height = 1;
|
||||
}
|
||||
if( vips_region_prepare( ir, &need ) )
|
||||
return( -1 );
|
||||
|
||||
|
||||
for( y = 0; y < r->height; y++ ) {
|
||||
VipsPel *p;
|
||||
VipsPel *q;
|
||||
|
||||
if( in->Xsize == 1 ) {
|
||||
p = r->left * VIPS_IMAGE_SIZEOF_ELEMENT( in ) +
|
||||
VIPS_REGION_ADDR( ir, 0, r->top + y );
|
||||
}
|
||||
else {
|
||||
p = r->left * VIPS_IMAGE_SIZEOF_ELEMENT( in ) +
|
||||
VIPS_REGION_ADDR( ir, r->top + y, 0 );
|
||||
}
|
||||
q = VIPS_REGION_ADDR( or, r->left, r->top + y );
|
||||
|
||||
if( copy->swap &&
|
||||
swap ) {
|
||||
swap( p, q, r->width, copy->in );
|
||||
}
|
||||
else
|
||||
/* We can't use vips_region_region(), it doesn't do
|
||||
* coordinate transforms. If we want to avoid the
|
||||
* memcpy() we'd need to add another vips_region_
|
||||
* function.
|
||||
*/
|
||||
memcpy( q, p,
|
||||
r->width * VIPS_IMAGE_SIZEOF_ELEMENT( in ) );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Copy a small area.
|
||||
*/
|
||||
static int
|
||||
@ -246,6 +313,8 @@ vips_copy_build( VipsObject *object )
|
||||
|
||||
guint64 image_size_before;
|
||||
guint64 image_size_after;
|
||||
VipsImage copy_of_fields;
|
||||
VipsGenerateFn copy_generate_fn;
|
||||
int i;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_copy_parent_class )->build( object ) )
|
||||
@ -258,10 +327,10 @@ vips_copy_build( VipsObject *object )
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, copy->in, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
/* We try to stop the worst crashes by at least ensuring that we don't
|
||||
* increase the number of pixels which might be addressed.
|
||||
/* Take a copy of all the basic header fields. We use this for
|
||||
* sanity-checking the changes our caller has made.
|
||||
*/
|
||||
image_size_before = VIPS_IMAGE_SIZEOF_IMAGE( conversion->out );
|
||||
copy_of_fields = *conversion->out;
|
||||
|
||||
/* Use props to adjust header fields.
|
||||
*/
|
||||
@ -300,6 +369,10 @@ vips_copy_build( VipsObject *object )
|
||||
}
|
||||
}
|
||||
|
||||
/* We try to stop the worst crashes by at least ensuring that we don't
|
||||
* increase the number of pixels which might be addressed.
|
||||
*/
|
||||
image_size_before = VIPS_IMAGE_SIZEOF_IMAGE( ©_of_fields );
|
||||
image_size_after = VIPS_IMAGE_SIZEOF_IMAGE( conversion->out );
|
||||
if( image_size_after > image_size_before ) {
|
||||
vips_error( class->nickname,
|
||||
@ -307,8 +380,23 @@ vips_copy_build( VipsObject *object )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Pick a generate function.
|
||||
*/
|
||||
copy_generate_fn = vips_copy_gen;
|
||||
|
||||
/* We let our caller change a 1xN or Nx1 image with M bands into a MxN
|
||||
* image. In other words, bands becomes width.
|
||||
*/
|
||||
if( (copy_of_fields.Xsize == 1 || copy_of_fields.Ysize == 1) &&
|
||||
conversion->out->Bands == 1 &&
|
||||
conversion->out->Xsize == copy_of_fields.Bands &&
|
||||
conversion->out->Ysize == VIPS_MAX(
|
||||
copy_of_fields.Xsize, copy_of_fields.Ysize ) ) {
|
||||
copy_generate_fn = vips_copy_unbandize_gen;
|
||||
}
|
||||
|
||||
if( vips_image_generate( conversion->out,
|
||||
vips_start_one, vips_copy_gen, vips_stop_one,
|
||||
vips_start_one, copy_generate_fn, vips_stop_one,
|
||||
copy->in, copy ) )
|
||||
return( -1 );
|
||||
|
||||
@ -461,6 +549,9 @@ vips_copy_init( VipsCopy *copy )
|
||||
* Setting @swap to %TRUE will make vips_copy() swap the byte ordering of
|
||||
* pixels according to the image's format.
|
||||
*
|
||||
* You can use this operation to turn 1xN or Nx1 images with M bands into MxN
|
||||
* one band images.
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user