Merge pull request #915 from harukizaemon/region-shrink-method
WIP: Adds a region shrink method
This commit is contained in:
commit
8a8a093523
@ -447,6 +447,7 @@ struct _VipsForeignSaveDz {
|
|||||||
VipsAngle angle;
|
VipsAngle angle;
|
||||||
VipsForeignDzContainer container;
|
VipsForeignDzContainer container;
|
||||||
int compression;
|
int compression;
|
||||||
|
VipsRegionShrink region_shrink;
|
||||||
|
|
||||||
/* Tile and overlap geometry. The members above are the parameters we
|
/* Tile and overlap geometry. The members above are the parameters we
|
||||||
* accept, this next set are the derived values which are actually
|
* accept, this next set are the derived values which are actually
|
||||||
@ -1355,6 +1356,8 @@ strip_shrink( Layer *layer )
|
|||||||
Layer *below = layer->below;
|
Layer *below = layer->below;
|
||||||
VipsRegion *from = layer->strip;
|
VipsRegion *from = layer->strip;
|
||||||
VipsRegion *to = below->strip;
|
VipsRegion *to = below->strip;
|
||||||
|
VipsForeignSaveDz *dz = layer->dz;
|
||||||
|
VipsRegionShrink region_shrink = dz->region_shrink;
|
||||||
|
|
||||||
VipsRect target;
|
VipsRect target;
|
||||||
VipsRect source;
|
VipsRect source;
|
||||||
@ -1401,10 +1404,11 @@ strip_shrink( Layer *layer )
|
|||||||
|
|
||||||
/* None? All done.
|
/* None? All done.
|
||||||
*/
|
*/
|
||||||
if( vips_rect_isempty( &target ) )
|
if( vips_rect_isempty( &target ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
(void) vips_region_shrink( from, to, &target );
|
(void) vips_region_shrink( from, to, &target,
|
||||||
|
region_shrink );
|
||||||
|
|
||||||
below->write_y += target.height;
|
below->write_y += target.height;
|
||||||
|
|
||||||
@ -2098,6 +2102,14 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class )
|
|||||||
G_STRUCT_OFFSET( VipsForeignSaveDz, compression ),
|
G_STRUCT_OFFSET( VipsForeignSaveDz, compression ),
|
||||||
-1, 9, 0 );
|
-1, 9, 0 );
|
||||||
|
|
||||||
|
VIPS_ARG_ENUM( class, "region_shrink", 18,
|
||||||
|
_( "Region shrink" ),
|
||||||
|
_( "Method for blah" ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignSaveDz, region_shrink ),
|
||||||
|
VIPS_TYPE_REGION_SHRINK,
|
||||||
|
VIPS_REGION_SHRINK_MEAN );
|
||||||
|
|
||||||
/* How annoying. We stupidly had these in earlier versions.
|
/* How annoying. We stupidly had these in earlier versions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -2136,6 +2148,7 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz )
|
|||||||
dz->angle = VIPS_ANGLE_D0;
|
dz->angle = VIPS_ANGLE_D0;
|
||||||
dz->container = VIPS_FOREIGN_DZ_CONTAINER_FS;
|
dz->container = VIPS_FOREIGN_DZ_CONTAINER_FS;
|
||||||
dz->compression = 0;
|
dz->compression = 0;
|
||||||
|
dz->region_shrink = VIPS_REGION_SHRINK_MEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _VipsForeignSaveDzFile {
|
typedef struct _VipsForeignSaveDzFile {
|
||||||
@ -2332,6 +2345,7 @@ vips_foreign_save_dz_buffer_init( VipsForeignSaveDzBuffer *buffer )
|
|||||||
* * @container: #VipsForeignDzContainer set container type
|
* * @container: #VipsForeignDzContainer set container type
|
||||||
* * @properties: %gboolean write a properties file
|
* * @properties: %gboolean write a properties file
|
||||||
* * @compression: %gint zip deflate compression level
|
* * @compression: %gint zip deflate compression level
|
||||||
|
* * @shrink_region: #VipsRegionShrink How to shrink each 2x2 region.
|
||||||
*
|
*
|
||||||
* Save an image as a set of tiles at various resolutions. By default dzsave
|
* Save an image as a set of tiles at various resolutions. By default dzsave
|
||||||
* uses DeepZoom layout -- use @layout to pick other conventions.
|
* uses DeepZoom layout -- use @layout to pick other conventions.
|
||||||
@ -2375,6 +2389,10 @@ vips_foreign_save_dz_buffer_init( VipsForeignSaveDzBuffer *buffer )
|
|||||||
* (use zlib default), 0 (store, compression disabled) to 9 (max compression).
|
* (use zlib default), 0 (store, compression disabled) to 9 (max compression).
|
||||||
* If no value is given, the default is to store files without compression.
|
* If no value is given, the default is to store files without compression.
|
||||||
*
|
*
|
||||||
|
* You can use @region_shrink to control the method for shrinking each 2x2
|
||||||
|
* region. This defaults to using the average of the 4 input pixels but you can
|
||||||
|
* also use the median in cases where you want to preseve the range of values.
|
||||||
|
*
|
||||||
* See also: vips_tiffsave().
|
* See also: vips_tiffsave().
|
||||||
*
|
*
|
||||||
* Returns: 0 on success, -1 on error.
|
* Returns: 0 on success, -1 on error.
|
||||||
|
@ -1389,10 +1389,11 @@ layer_strip_shrink( Layer *layer )
|
|||||||
|
|
||||||
/* None? All done.
|
/* None? All done.
|
||||||
*/
|
*/
|
||||||
if( vips_rect_isempty( &target ) )
|
if( vips_rect_isempty( &target ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
(void) vips_region_shrink( from, to, &target );
|
(void) vips_region_shrink( from, to, &target,
|
||||||
|
VIPS_REGION_SHRINK_MEAN );
|
||||||
|
|
||||||
below->write_y += target.height;
|
below->write_y += target.height;
|
||||||
|
|
||||||
|
@ -72,7 +72,8 @@ vips_scan_headers = \
|
|||||||
${top_srcdir}/libvips/include/vips/morphology.h \
|
${top_srcdir}/libvips/include/vips/morphology.h \
|
||||||
${top_srcdir}/libvips/include/vips/draw.h \
|
${top_srcdir}/libvips/include/vips/draw.h \
|
||||||
${top_srcdir}/libvips/include/vips/basic.h \
|
${top_srcdir}/libvips/include/vips/basic.h \
|
||||||
${top_srcdir}/libvips/include/vips/object.h
|
${top_srcdir}/libvips/include/vips/object.h \
|
||||||
|
${top_srcdir}/libvips/include/vips/region.h
|
||||||
|
|
||||||
enumtypes.h: $(vips_scan_headers) Makefile.am
|
enumtypes.h: $(vips_scan_headers) Makefile.am
|
||||||
glib-mkenums --template enumtemplate $(vips_scan_headers) > enumtypes.h
|
glib-mkenums --template enumtemplate $(vips_scan_headers) > enumtypes.h
|
||||||
|
@ -55,6 +55,21 @@ extern "C" {
|
|||||||
(G_TYPE_INSTANCE_GET_CLASS( (obj), \
|
(G_TYPE_INSTANCE_GET_CLASS( (obj), \
|
||||||
VIPS_TYPE_REGION, VipsRegionClass ))
|
VIPS_TYPE_REGION, VipsRegionClass ))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VipsRegionShrink:
|
||||||
|
* @VIPS_REGION_SHRINK_MEAN: use the average
|
||||||
|
* @VIPS_REGION_SHRINK_MEDIAN: use the median
|
||||||
|
* @VIPS_REGION_SHRINK_MODE: use the mode
|
||||||
|
*
|
||||||
|
* How to calculate the output pixels when shrinking a 2x2 region.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
VIPS_REGION_SHRINK_MEAN,
|
||||||
|
VIPS_REGION_SHRINK_MEDIAN,
|
||||||
|
VIPS_REGION_SHRINK_MODE,
|
||||||
|
VIPS_REGION_SHRINK_LAST
|
||||||
|
} VipsRegionShrink;
|
||||||
|
|
||||||
/* Sub-area of image.
|
/* Sub-area of image.
|
||||||
*/
|
*/
|
||||||
typedef struct _VipsRegion {
|
typedef struct _VipsRegion {
|
||||||
@ -115,13 +130,14 @@ void vips_region_paint( VipsRegion *reg, const VipsRect *r, int value );
|
|||||||
void vips_region_paint_pel( VipsRegion *reg,
|
void vips_region_paint_pel( VipsRegion *reg,
|
||||||
const VipsRect *r, const VipsPel *ink );
|
const VipsRect *r, const VipsPel *ink );
|
||||||
void vips_region_black( VipsRegion *reg );
|
void vips_region_black( VipsRegion *reg );
|
||||||
void vips_region_copy( VipsRegion *reg, VipsRegion *dest,
|
void vips_region_copy( VipsRegion *reg, VipsRegion *dest,
|
||||||
const VipsRect *r, int x, int y );
|
const VipsRect *r, int x, int y );
|
||||||
int vips_region_shrink( VipsRegion *from,
|
int vips_region_shrink( VipsRegion *from,
|
||||||
VipsRegion *to, const VipsRect *target );
|
VipsRegion *to, const VipsRect *target,
|
||||||
|
VipsRegionShrink method );
|
||||||
|
|
||||||
int vips_region_prepare( VipsRegion *reg, const VipsRect *r );
|
int vips_region_prepare( VipsRegion *reg, const VipsRect *r );
|
||||||
int vips_region_prepare_to( VipsRegion *reg,
|
int vips_region_prepare_to( VipsRegion *reg,
|
||||||
VipsRegion *dest, const VipsRect *r, int x, int y );
|
VipsRegion *dest, const VipsRect *r, int x, int y );
|
||||||
|
|
||||||
void vips_region_invalidate( VipsRegion *reg );
|
void vips_region_invalidate( VipsRegion *reg );
|
||||||
|
@ -70,7 +70,8 @@ vips_scan_headers = \
|
|||||||
${top_srcdir}/libvips/include/vips/morphology.h \
|
${top_srcdir}/libvips/include/vips/morphology.h \
|
||||||
${top_srcdir}/libvips/include/vips/draw.h \
|
${top_srcdir}/libvips/include/vips/draw.h \
|
||||||
${top_srcdir}/libvips/include/vips/basic.h \
|
${top_srcdir}/libvips/include/vips/basic.h \
|
||||||
${top_srcdir}/libvips/include/vips/object.h
|
${top_srcdir}/libvips/include/vips/object.h \
|
||||||
|
${top_srcdir}/libvips/include/vips/region.h
|
||||||
|
|
||||||
enumtypes.c: $(vips_scan_headers) Makefile.am
|
enumtypes.c: $(vips_scan_headers) Makefile.am
|
||||||
glib-mkenums --template enumtemplate $(vips_scan_headers) > enumtypes.c
|
glib-mkenums --template enumtemplate $(vips_scan_headers) > enumtypes.c
|
||||||
|
@ -866,6 +866,26 @@ vips_operation_flags_get_type( void )
|
|||||||
|
|
||||||
return( etype );
|
return( etype );
|
||||||
}
|
}
|
||||||
|
/* enumerations from "../../libvips/include/vips/region.h" */
|
||||||
|
GType
|
||||||
|
vips_region_shrink_get_type( void )
|
||||||
|
{
|
||||||
|
static GType etype = 0;
|
||||||
|
|
||||||
|
if( etype == 0 ) {
|
||||||
|
static const GEnumValue values[] = {
|
||||||
|
{VIPS_REGION_SHRINK_MEAN, "VIPS_REGION_SHRINK_MEAN", "mean"},
|
||||||
|
{VIPS_REGION_SHRINK_MEDIAN, "VIPS_REGION_SHRINK_MEDIAN", "median"},
|
||||||
|
{VIPS_REGION_SHRINK_MODE, "VIPS_REGION_SHRINK_MODE", "mode"},
|
||||||
|
{VIPS_REGION_SHRINK_LAST, "VIPS_REGION_SHRINK_LAST", "last"},
|
||||||
|
{0, NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
etype = g_enum_register_static( "VipsRegionShrink", values );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( etype );
|
||||||
|
}
|
||||||
/* enumerations from "../../libvips/include/vips/resample.h" */
|
/* enumerations from "../../libvips/include/vips/resample.h" */
|
||||||
GType
|
GType
|
||||||
vips_kernel_get_type( void )
|
vips_kernel_get_type( void )
|
||||||
|
@ -1166,7 +1166,7 @@ vips_region_shrink_labpack( VipsRegion *from,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SHRINK_TYPE_INT( TYPE ) \
|
#define SHRINK_TYPE_MEAN_INT( TYPE ) \
|
||||||
for( x = 0; x < target->width; x++ ) { \
|
for( x = 0; x < target->width; x++ ) { \
|
||||||
TYPE *tp = (TYPE *) p; \
|
TYPE *tp = (TYPE *) p; \
|
||||||
TYPE *tp1 = (TYPE *) (p + ls); \
|
TYPE *tp1 = (TYPE *) (p + ls); \
|
||||||
@ -1185,7 +1185,7 @@ vips_region_shrink_labpack( VipsRegion *from,
|
|||||||
q += ps; \
|
q += ps; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SHRINK_TYPE_FLOAT( TYPE ) \
|
#define SHRINK_TYPE_MEAN_FLOAT( TYPE ) \
|
||||||
for( x = 0; x < target->width; x++ ) { \
|
for( x = 0; x < target->width; x++ ) { \
|
||||||
TYPE *tp = (TYPE *) p; \
|
TYPE *tp = (TYPE *) p; \
|
||||||
TYPE *tp1 = (TYPE *) (p + ls); \
|
TYPE *tp1 = (TYPE *) (p + ls); \
|
||||||
@ -1204,10 +1204,69 @@ vips_region_shrink_labpack( VipsRegion *from,
|
|||||||
q += ps; \
|
q += ps; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This method is implemented so as to perform well and to always select an
|
||||||
|
* output pixel from one of the input pixels. As such we make only the
|
||||||
|
* following guarantees:
|
||||||
|
*
|
||||||
|
* ONLY works for non-complex uncoded images pixel types
|
||||||
|
* ALWAYS draws from the input values
|
||||||
|
* NEVER interpolates
|
||||||
|
* NOT stable with respect to the ordered set of input values
|
||||||
|
* IS stable with respect to the initial arrangement of input values
|
||||||
|
*/
|
||||||
|
#define SHRINK_TYPE_MEDIAN( TYPE ) \
|
||||||
|
for( x = 0; x < target->width; x++ ) { \
|
||||||
|
TYPE *tp = (TYPE *) p; \
|
||||||
|
TYPE *tp1 = (TYPE *) (p + ls); \
|
||||||
|
TYPE *tq = (TYPE *) q; \
|
||||||
|
\
|
||||||
|
for( z = 0; z < nb; z++ ) { \
|
||||||
|
tq[z] = VIPS_MIN( \
|
||||||
|
VIPS_MAX( tp[z], tp[z + nb] ), \
|
||||||
|
VIPS_MAX( tp1[z], tp1[z + nb] ) \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Move on two pels in input. \
|
||||||
|
*/ \
|
||||||
|
p += ps << 1; \
|
||||||
|
q += ps; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This method is implemented so as to perform well and to always select an
|
||||||
|
* output pixel from one of the input pixels. As such we make only the
|
||||||
|
* following guarantees:
|
||||||
|
*
|
||||||
|
* ONLY works for non-complex uncoded images pixel types
|
||||||
|
* ALWAYS draws from the input values
|
||||||
|
* NEVER interpolates
|
||||||
|
* NOT stable with respect to the ordered set of input values
|
||||||
|
* IS stable with respect to the initial arrangement of input values
|
||||||
|
*/
|
||||||
|
#define SHRINK_TYPE_MODE( TYPE ) \
|
||||||
|
for( x = 0; x < target->width; x++ ) { \
|
||||||
|
TYPE *tp = (TYPE *) p; \
|
||||||
|
TYPE *tp1 = (TYPE *) (p + ls); \
|
||||||
|
TYPE *tq = (TYPE *) q; \
|
||||||
|
\
|
||||||
|
for( z = 0; z < nb; z++ ) { \
|
||||||
|
TYPE v[] = {tp[z], tp[z + nb], tp1[z], tp1[z + nb]}; \
|
||||||
|
int b0 = (v[0] == v[1]) | (v[0] == v[2]) | (v[0] == v[3]); \
|
||||||
|
int b1 = (v[1] == v[0]) | (v[1] == v[2]) | (v[1] == v[3]); \
|
||||||
|
int index = ((~b0) & 0x1) + (~(b0 ^ b1) & 0x1); \
|
||||||
|
tq[z] = v[index]; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Move on two pels in input. \
|
||||||
|
*/ \
|
||||||
|
p += ps << 1; \
|
||||||
|
q += ps; \
|
||||||
|
}
|
||||||
|
|
||||||
/* Generate area @target in @to using pixels in @from. Non-complex.
|
/* Generate area @target in @to using pixels in @from. Non-complex.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
vips_region_shrink_uncoded( VipsRegion *from,
|
vips_region_shrink_uncoded_mean( VipsRegion *from,
|
||||||
VipsRegion *to, const VipsRect *target )
|
VipsRegion *to, const VipsRect *target )
|
||||||
{
|
{
|
||||||
int ls = VIPS_REGION_LSKIP( from );
|
int ls = VIPS_REGION_LSKIP( from );
|
||||||
@ -1225,22 +1284,22 @@ vips_region_shrink_uncoded( VipsRegion *from,
|
|||||||
/* Process this line of pels.
|
/* Process this line of pels.
|
||||||
*/
|
*/
|
||||||
switch( from->im->BandFmt ) {
|
switch( from->im->BandFmt ) {
|
||||||
case VIPS_FORMAT_UCHAR:
|
case VIPS_FORMAT_UCHAR:
|
||||||
SHRINK_TYPE_INT( unsigned char ); break;
|
SHRINK_TYPE_MEAN_INT( unsigned char ); break;
|
||||||
case VIPS_FORMAT_CHAR:
|
case VIPS_FORMAT_CHAR:
|
||||||
SHRINK_TYPE_INT( signed char ); break;
|
SHRINK_TYPE_MEAN_INT( signed char ); break;
|
||||||
case VIPS_FORMAT_USHORT:
|
case VIPS_FORMAT_USHORT:
|
||||||
SHRINK_TYPE_INT( unsigned short ); break;
|
SHRINK_TYPE_MEAN_INT( unsigned short ); break;
|
||||||
case VIPS_FORMAT_SHORT:
|
case VIPS_FORMAT_SHORT:
|
||||||
SHRINK_TYPE_INT( signed short ); break;
|
SHRINK_TYPE_MEAN_INT( signed short ); break;
|
||||||
case VIPS_FORMAT_UINT:
|
case VIPS_FORMAT_UINT:
|
||||||
SHRINK_TYPE_INT( unsigned int ); break;
|
SHRINK_TYPE_MEAN_INT( unsigned int ); break;
|
||||||
case VIPS_FORMAT_INT:
|
case VIPS_FORMAT_INT:
|
||||||
SHRINK_TYPE_INT( signed int ); break;
|
SHRINK_TYPE_MEAN_INT( signed int ); break;
|
||||||
case VIPS_FORMAT_FLOAT:
|
case VIPS_FORMAT_FLOAT:
|
||||||
SHRINK_TYPE_FLOAT( float ); break;
|
SHRINK_TYPE_MEAN_FLOAT( float ); break;
|
||||||
case VIPS_FORMAT_DOUBLE:
|
case VIPS_FORMAT_DOUBLE:
|
||||||
SHRINK_TYPE_FLOAT( double ); break;
|
SHRINK_TYPE_MEAN_FLOAT( double ); break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
@ -1248,6 +1307,116 @@ vips_region_shrink_uncoded( VipsRegion *from,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Generate area @target in @to using pixels in @from. Non-complex.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
vips_region_shrink_uncoded_median( VipsRegion *from,
|
||||||
|
VipsRegion *to, const VipsRect *target )
|
||||||
|
{
|
||||||
|
int ls = VIPS_REGION_LSKIP( from );
|
||||||
|
int ps = VIPS_IMAGE_SIZEOF_PEL( from->im );
|
||||||
|
int nb = from->im->Bands;
|
||||||
|
|
||||||
|
int x, y, z;
|
||||||
|
|
||||||
|
for( y = 0; y < target->height; y++ ) {
|
||||||
|
VipsPel *p = VIPS_REGION_ADDR( from,
|
||||||
|
target->left * 2, (target->top + y) * 2 );
|
||||||
|
VipsPel *q = VIPS_REGION_ADDR( to,
|
||||||
|
target->left, target->top + y );
|
||||||
|
|
||||||
|
/* Process this line of pels.
|
||||||
|
*/
|
||||||
|
switch( from->im->BandFmt ) {
|
||||||
|
case VIPS_FORMAT_UCHAR:
|
||||||
|
SHRINK_TYPE_MEDIAN( unsigned char ); break;
|
||||||
|
case VIPS_FORMAT_CHAR:
|
||||||
|
SHRINK_TYPE_MEDIAN( signed char ); break;
|
||||||
|
case VIPS_FORMAT_USHORT:
|
||||||
|
SHRINK_TYPE_MEDIAN( unsigned short ); break;
|
||||||
|
case VIPS_FORMAT_SHORT:
|
||||||
|
SHRINK_TYPE_MEDIAN( signed short ); break;
|
||||||
|
case VIPS_FORMAT_UINT:
|
||||||
|
SHRINK_TYPE_MEDIAN( unsigned int ); break;
|
||||||
|
case VIPS_FORMAT_INT:
|
||||||
|
SHRINK_TYPE_MEDIAN( signed int ); break;
|
||||||
|
case VIPS_FORMAT_FLOAT:
|
||||||
|
SHRINK_TYPE_MEDIAN( float ); break;
|
||||||
|
case VIPS_FORMAT_DOUBLE:
|
||||||
|
SHRINK_TYPE_MEDIAN( double ); break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate area @target in @to using pixels in @from. Non-complex.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
vips_region_shrink_uncoded_mode( VipsRegion *from,
|
||||||
|
VipsRegion *to, const VipsRect *target )
|
||||||
|
{
|
||||||
|
int ls = VIPS_REGION_LSKIP( from );
|
||||||
|
int ps = VIPS_IMAGE_SIZEOF_PEL( from->im );
|
||||||
|
int nb = from->im->Bands;
|
||||||
|
|
||||||
|
int x, y, z;
|
||||||
|
|
||||||
|
for( y = 0; y < target->height; y++ ) {
|
||||||
|
VipsPel *p = VIPS_REGION_ADDR( from,
|
||||||
|
target->left * 2, (target->top + y) * 2 );
|
||||||
|
VipsPel *q = VIPS_REGION_ADDR( to,
|
||||||
|
target->left, target->top + y );
|
||||||
|
|
||||||
|
/* Process this line of pels.
|
||||||
|
*/
|
||||||
|
switch( from->im->BandFmt ) {
|
||||||
|
case VIPS_FORMAT_UCHAR:
|
||||||
|
SHRINK_TYPE_MODE( unsigned char ); break;
|
||||||
|
case VIPS_FORMAT_CHAR:
|
||||||
|
SHRINK_TYPE_MODE( signed char ); break;
|
||||||
|
case VIPS_FORMAT_USHORT:
|
||||||
|
SHRINK_TYPE_MODE( unsigned short ); break;
|
||||||
|
case VIPS_FORMAT_SHORT:
|
||||||
|
SHRINK_TYPE_MODE( signed short ); break;
|
||||||
|
case VIPS_FORMAT_UINT:
|
||||||
|
SHRINK_TYPE_MODE( unsigned int ); break;
|
||||||
|
case VIPS_FORMAT_INT:
|
||||||
|
SHRINK_TYPE_MODE( signed int ); break;
|
||||||
|
case VIPS_FORMAT_FLOAT:
|
||||||
|
SHRINK_TYPE_MODE( float ); break;
|
||||||
|
case VIPS_FORMAT_DOUBLE:
|
||||||
|
SHRINK_TYPE_MODE( double ); break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate area @target in @to using pixels in @from. Non-complex.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
vips_region_shrink_uncoded( VipsRegion *from,
|
||||||
|
VipsRegion *to, const VipsRect *target, VipsRegionShrink method )
|
||||||
|
{
|
||||||
|
switch( method ) {
|
||||||
|
case VIPS_REGION_SHRINK_MEAN:
|
||||||
|
vips_region_shrink_uncoded_mean( from, to, target );
|
||||||
|
break;
|
||||||
|
case VIPS_REGION_SHRINK_MEDIAN:
|
||||||
|
vips_region_shrink_uncoded_median( from, to, target );
|
||||||
|
break;
|
||||||
|
case VIPS_REGION_SHRINK_MODE:
|
||||||
|
vips_region_shrink_uncoded_mode( from, to, target );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* No point having an int path, this will always be horribly slow.
|
/* No point having an int path, this will always be horribly slow.
|
||||||
*/
|
*/
|
||||||
#define SHRINK_ALPHA_TYPE( TYPE ) { \
|
#define SHRINK_ALPHA_TYPE( TYPE ) { \
|
||||||
@ -1333,9 +1502,10 @@ vips_region_shrink_alpha( VipsRegion *from,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_region_shrink:
|
* vips_region_shrink:
|
||||||
* @from: source region
|
* @from: source region
|
||||||
* @to: (inout): destination region
|
* @to: (inout): destination region
|
||||||
* @target: #VipsRect of pixels you need to copy
|
* @target: #VipsRect of pixels you need to copy
|
||||||
|
* @method: #VipsRegionShrink method to use when generating target pixels
|
||||||
*
|
*
|
||||||
* Write the pixels @target in @to from the x2 larger area in @from.
|
* Write the pixels @target in @to from the x2 larger area in @from.
|
||||||
* Non-complex uncoded images and LABQ only. Images with alpha (see
|
* Non-complex uncoded images and LABQ only. Images with alpha (see
|
||||||
@ -1344,7 +1514,8 @@ vips_region_shrink_alpha( VipsRegion *from,
|
|||||||
* See also: vips_region_copy().
|
* See also: vips_region_copy().
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
vips_region_shrink( VipsRegion *from, VipsRegion *to, const VipsRect *target )
|
vips_region_shrink( VipsRegion *from, VipsRegion *to, const VipsRect *target,
|
||||||
|
VipsRegionShrink method )
|
||||||
{
|
{
|
||||||
VipsImage *image = from->im;
|
VipsImage *image = from->im;
|
||||||
|
|
||||||
@ -1355,10 +1526,10 @@ vips_region_shrink( VipsRegion *from, VipsRegion *to, const VipsRect *target )
|
|||||||
if( vips_check_noncomplex( "vips_region_shrink", image ) )
|
if( vips_check_noncomplex( "vips_region_shrink", image ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips_image_hasalpha( image ) )
|
if( vips_image_hasalpha( image ) )
|
||||||
vips_region_shrink_alpha( from, to, target );
|
vips_region_shrink_alpha( from, to, target );
|
||||||
else
|
else
|
||||||
vips_region_shrink_uncoded( from, to, target );
|
vips_region_shrink_uncoded( from, to, target, method );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vips_region_shrink_labpack( from, to, target );
|
vips_region_shrink_labpack( from, to, target );
|
||||||
|
Loading…
Reference in New Issue
Block a user