add mono image -> many band column
or row ... handy for loading LUT images from CSV files
This commit is contained in:
parent
5cb2239d7d
commit
e84b97038f
11
TODO
11
TODO
@ -1,14 +1,11 @@
|
||||
- try:
|
||||
|
||||
$ vips copy y.v x.v --width 1 --bands 3
|
||||
VipsRegion: images do not match in pixel size
|
||||
$ vips csvload ~/Desktop/NDVI_VGYRM-lut.txt x.v --skip 1
|
||||
$ vips copy x.v x2.v --width 256 --height 1 --bands 4
|
||||
Segmentation fault (core dumped)
|
||||
|
||||
copy will make 1xN or Nx1 M-band images into MxN one-band images, but it
|
||||
won't go the other way
|
||||
see commented-out test in test_conversion.py
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- does ruby need to unpack RefString as well? what about C++?
|
||||
|
||||
|
@ -49,6 +49,8 @@
|
||||
* - use glib byteswap macros
|
||||
* 15/5/15
|
||||
* - support bands -> width conversion
|
||||
* 4/6/15
|
||||
* - support width -> bands conversion
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -196,12 +198,14 @@ vips_copy_unbandize_gen( VipsRegion *or,
|
||||
{
|
||||
VipsRegion *ir = (VipsRegion *) seq;
|
||||
VipsImage *in = ir->im;
|
||||
VipsImage *out = or->im;
|
||||
VipsRect *r = &or->valid;
|
||||
VipsCopy *copy = (VipsCopy *) b;
|
||||
SwapFn swap = vips_copy_swap_fn[copy->in->BandFmt];
|
||||
int sze = VIPS_IMAGE_SIZEOF_ELEMENT( in );
|
||||
|
||||
VipsRect need;
|
||||
int y;
|
||||
int x, y;
|
||||
|
||||
/* Ask for input we need.
|
||||
*/
|
||||
@ -220,33 +224,97 @@ vips_copy_unbandize_gen( VipsRegion *or,
|
||||
if( vips_region_prepare( ir, &need ) )
|
||||
return( -1 );
|
||||
|
||||
/* We copy 1 pixel at a time. A vertical input image won't be
|
||||
* guaranteed to have continuous data.
|
||||
*/
|
||||
|
||||
for( y = 0; y < r->height; y++ ) {
|
||||
VipsPel *p;
|
||||
VipsPel *q;
|
||||
for( x = 0; x < r->width; x++ ) {
|
||||
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( in->Xsize == 1 )
|
||||
p = VIPS_REGION_ADDR( ir, 0, r->top + y ) +
|
||||
(r->left + x) * sze;
|
||||
else
|
||||
p = VIPS_REGION_ADDR( ir, r->top + y, 0 ) +
|
||||
(r->left + x) * sze;
|
||||
q = VIPS_REGION_ADDR( or, r->left + x, r->top + y );
|
||||
|
||||
if( copy->swap &&
|
||||
swap ) {
|
||||
swap( p, q, r->width, copy->in );
|
||||
if( copy->swap &&
|
||||
swap )
|
||||
swap( p, q, 1, out );
|
||||
else
|
||||
memcpy( q, p, sze );
|
||||
}
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Copy, turning the x axis into bands, the inverse of the above. Useful for
|
||||
* turning CSV files into RGB LUTs, for example.
|
||||
*
|
||||
* output has bands == input width, one of width or height 1.
|
||||
*/
|
||||
static int
|
||||
vips_copy_bandize_gen( VipsRegion *or,
|
||||
void *seq, void *a, void *b, gboolean *stop )
|
||||
{
|
||||
VipsRegion *ir = (VipsRegion *) seq;
|
||||
VipsImage *in = ir->im;
|
||||
VipsImage *out = or->im;
|
||||
VipsRect *r = &or->valid;
|
||||
VipsCopy *copy = (VipsCopy *) b;
|
||||
SwapFn swap = vips_copy_swap_fn[copy->in->BandFmt];
|
||||
int sze = VIPS_IMAGE_SIZEOF_ELEMENT( in );
|
||||
|
||||
VipsRect need;
|
||||
int x, y;
|
||||
|
||||
/* Ask for input we need.
|
||||
*/
|
||||
if( out->Xsize == 1 ) {
|
||||
need.left = 0;
|
||||
need.top = r->top;
|
||||
need.width = in->Xsize;
|
||||
need.height = r->height;
|
||||
}
|
||||
else {
|
||||
need.left = 0;
|
||||
need.top = r->left;
|
||||
need.width = in->Xsize;
|
||||
need.height = r->width;
|
||||
}
|
||||
if( vips_region_prepare( ir, &need ) )
|
||||
return( -1 );
|
||||
|
||||
/* We have to copy 1 pixel at a time. Each scanline in our input
|
||||
* becomes a pixel in the output. Scanlines are not guaranteed to be
|
||||
* continuous after vips_region_prepare(), they may be a window on a
|
||||
* larger image.
|
||||
*/
|
||||
|
||||
for( y = 0; y < r->height; y++ ) {
|
||||
for( x = 0; x < r->width; x++ ) {
|
||||
VipsPel *p;
|
||||
VipsPel *q;
|
||||
|
||||
if( out->Xsize == 1 ) {
|
||||
p = VIPS_REGION_ADDR( ir, 0, r->top + y );
|
||||
q = VIPS_REGION_ADDR( or, 0, r->top + y );
|
||||
}
|
||||
else {
|
||||
p = VIPS_REGION_ADDR( ir, 0, r->left + x );
|
||||
q = VIPS_REGION_ADDR( or, 0, r->left + x );
|
||||
}
|
||||
|
||||
if( copy->swap &&
|
||||
swap )
|
||||
swap( p, q, 1, out );
|
||||
else
|
||||
memcpy( q, p, out->Bands * sze );
|
||||
}
|
||||
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 );
|
||||
@ -391,9 +459,18 @@ vips_copy_build( VipsObject *object )
|
||||
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_of_fields.Xsize, copy_of_fields.Ysize ) )
|
||||
copy_generate_fn = vips_copy_unbandize_gen;
|
||||
}
|
||||
|
||||
/* And the inverse: change a MxN one-band image into a 1xN or Nx1
|
||||
* M-band image. That is, squash M into bands.
|
||||
*/
|
||||
if( (conversion->out->Xsize == 1 || conversion->out->Ysize == 1) &&
|
||||
conversion->out->Bands == copy_of_fields.Xsize &&
|
||||
copy_of_fields.Bands == 1 &&
|
||||
copy_of_fields.Ysize == VIPS_MAX(
|
||||
conversion->out->Xsize, conversion->out->Ysize ) )
|
||||
copy_generate_fn = vips_copy_bandize_gen;
|
||||
|
||||
if( vips_image_generate( conversion->out,
|
||||
vips_start_one, copy_generate_fn, vips_stop_one,
|
||||
|
@ -224,16 +224,32 @@ class TestConversion(unittest.TestCase):
|
||||
self.assertEqual(x.xoffset, 42)
|
||||
x = self.colour.copy(yoffset = 42)
|
||||
self.assertEqual(x.yoffset, 42)
|
||||
x = self.colour.copy(bands = 1)
|
||||
self.assertEqual(x.bands, 1)
|
||||
x = self.colour.copy(format = Vips.BandFormat.USHORT, bands = 1)
|
||||
self.assertEqual(x.format, Vips.BandFormat.USHORT)
|
||||
x = self.colour.copy(coding = Vips.Coding.NONE)
|
||||
self.assertEqual(x.coding, Vips.Coding.NONE)
|
||||
x = self.colour.copy(width = 42)
|
||||
self.assertEqual(x.width, 42)
|
||||
x = self.colour.copy(height = 42)
|
||||
self.assertEqual(x.height, 42)
|
||||
|
||||
# test squashing width of mono image into bands
|
||||
x = self.mono.copy(width = 1, bands = self.mono.width)
|
||||
self.assertEqual(x.width, 1)
|
||||
self.assertEqual(x.bands, self.mono.width)
|
||||
|
||||
# back the other way
|
||||
y = x.copy(width = self.mono.width, bands = 1)
|
||||
self.assertEqual(y.width, self.mono.width)
|
||||
self.assertEqual(y.bands, 1)
|
||||
self.assertEqual(x.avg(), y.avg())
|
||||
|
||||
# test squashing width of mono image into bands
|
||||
x = self.mono.copy(width = self.mono.height, height = 1, bands = self.mono.width)
|
||||
self.assertEqual(x.width, self.mono.height)
|
||||
self.assertEqual(x.height, 1)
|
||||
self.assertEqual(x.bands, self.mono.width)
|
||||
|
||||
# back the other way
|
||||
y = x.copy(width = self.mono.width, height = self.mono.height, bands = 1)
|
||||
self.assertEqual(y.width, self.mono.width)
|
||||
self.assertEqual(y.height, self.mono.height)
|
||||
self.assertEqual(y.bands, 1)
|
||||
#self.assertEqual(x.avg(), y.avg())
|
||||
|
||||
def test_embed(self):
|
||||
for fmt in all_formats:
|
||||
|
Loading…
Reference in New Issue
Block a user