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()
|
- change the alpha range rules for vips_flatten() to match vips_premultiply()
|
||||||
- vipsthumbnail uses vips_resize() rather than its own code
|
- vipsthumbnail uses vips_resize() rather than its own code
|
||||||
- vipsthumbnail uses vips_premultiply() for better alpha quality
|
- 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
|
4/5/15 started 8.0.2
|
||||||
- fix a refcount error in C++ wrapper, thanks huskier
|
- 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
|
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
|
||||||
see:
|
for the number of threads, times 500, since we need a 500-stage pipeline
|
||||||
|
|
||||||
$ 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?
|
|
||||||
|
|
||||||
|
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
|
- are the mosaic functions calling vips_fastcor()? it must be very slow
|
||||||
|
|
||||||
|
@ -47,6 +47,8 @@
|
|||||||
* - rewrite as a class
|
* - rewrite as a class
|
||||||
* 1/12/11
|
* 1/12/11
|
||||||
* - use glib byteswap macros
|
* - use glib byteswap macros
|
||||||
|
* 15/5/15
|
||||||
|
* - support bands -> width conversion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -87,6 +89,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
@ -185,6 +188,70 @@ static SwapFn vips_copy_swap_fn[] = {
|
|||||||
vips_copy_swap8 /* VIPS_FORMAT_DPCOMPLEX = 9, */
|
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.
|
/* Copy a small area.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -246,6 +313,8 @@ vips_copy_build( VipsObject *object )
|
|||||||
|
|
||||||
guint64 image_size_before;
|
guint64 image_size_before;
|
||||||
guint64 image_size_after;
|
guint64 image_size_after;
|
||||||
|
VipsImage copy_of_fields;
|
||||||
|
VipsGenerateFn copy_generate_fn;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_copy_parent_class )->build( object ) )
|
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 ) )
|
VIPS_DEMAND_STYLE_THINSTRIP, copy->in, NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
/* We try to stop the worst crashes by at least ensuring that we don't
|
/* Take a copy of all the basic header fields. We use this for
|
||||||
* increase the number of pixels which might be addressed.
|
* 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.
|
/* 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 );
|
image_size_after = VIPS_IMAGE_SIZEOF_IMAGE( conversion->out );
|
||||||
if( image_size_after > image_size_before ) {
|
if( image_size_after > image_size_before ) {
|
||||||
vips_error( class->nickname,
|
vips_error( class->nickname,
|
||||||
@ -307,8 +380,23 @@ vips_copy_build( VipsObject *object )
|
|||||||
return( -1 );
|
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,
|
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 ) )
|
copy->in, copy ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
@ -461,6 +549,9 @@ vips_copy_init( VipsCopy *copy )
|
|||||||
* Setting @swap to %TRUE will make vips_copy() swap the byte ordering of
|
* Setting @swap to %TRUE will make vips_copy() swap the byte ordering of
|
||||||
* pixels according to the image's format.
|
* 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.
|
* Returns: 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
Loading…
Reference in New Issue
Block a user