From 69136b1d8c2154fb4dc8d8aefbc4d98c915130f8 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 28 May 2013 10:32:37 +0100 Subject: [PATCH] auto rshift to 8 bits for 8-bit save --- ChangeLog | 1 + TODO | 2 -- libvips/foreign/foreign.c | 23 +++++++++++++++++++++++ libvips/include/vips/image.h | 1 + libvips/iofuncs/image.c | 30 ++++++++++++++++++++++++++++++ 5 files changed, 55 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 06e7ab71..358b2f3b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ - vipsthumbnail lets you specify the sharpening mask - turn off caching for im_copy()/vips_copy(), we use copy to stop sharing, and it's cheap so caching doesn't help anyway +- auto rshift down to 8 bits on save, if necessary 14/5/13 started 7.32.4 - icc import and export could segv on very wide images diff --git a/TODO b/TODO index 13767d2e..9ece20c6 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,4 @@ -- save 16bit RGB as jpg, does not drop bottom 8 bits, should it? - - look at There is an order 1 algorithm for doing medians over boxes (truly O(1) diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 9b60bbb4..22dd828d 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -4,6 +4,8 @@ * - add support for sequential reads * 18/6/12 * - flatten alpha with vips_flatten() + * 28/5/13 + * - auto rshift down to 8 bits during save */ /* @@ -1258,6 +1260,27 @@ vips_foreign_convert_saveable( VipsForeignSave *save ) in = out; } + /* Shift down to 8 bits. Handy for 8-bit-only formats like jpeg. + * + * If the operation wants to write 8 bits for this format and this + * image is 16 bits or more and Type is RGB16 or GREY16 ... + * automatically shift down. + */ + if( vips_band_format_is8bit( class->format_table[in->BandFmt] ) && + !vips_band_format_is8bit( in->BandFmt ) && + (in->Type == VIPS_INTERPRETATION_RGB16 || + in->Type == VIPS_INTERPRETATION_GREY16) ) { + VipsImage *out; + + if( vips_rshift_const1( in, &out, 8, NULL ) ) { + g_object_unref( in ); + return( -1 ); + } + g_object_unref( in ); + + in = out; + } + /* Cast to the output format. */ { diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index d3ba4509..8fa95637 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -526,6 +526,7 @@ int vips_image_write_line( VipsImage *image, int ypos, VipsPel *linebuffer ); gboolean vips_band_format_isint( VipsBandFormat format ); gboolean vips_band_format_isuint( VipsBandFormat format ); +gboolean vips_band_format_is8bit( VipsBandFormat format ); gboolean vips_band_format_isfloat( VipsBandFormat format ); gboolean vips_band_format_iscomplex( VipsBandFormat format ); diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index f0b9d8ac..4f9d4f79 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -2447,6 +2447,36 @@ vips_band_format_isuint( VipsBandFormat format ) } } +/** + * vips_band_format_is8bit: + * @format: format to test + * + * Return %TRUE if @format is uchar or schar. + */ +gboolean +vips_band_format_is8bit( VipsBandFormat format ) +{ + switch( format ) { + case VIPS_FORMAT_UCHAR: + case VIPS_FORMAT_CHAR: + return( TRUE ); + + case VIPS_FORMAT_USHORT: + case VIPS_FORMAT_SHORT: + case VIPS_FORMAT_UINT: + case VIPS_FORMAT_INT: + case VIPS_FORMAT_FLOAT: + case VIPS_FORMAT_DOUBLE: + case VIPS_FORMAT_COMPLEX: + case VIPS_FORMAT_DPCOMPLEX: + return( FALSE ); + + default: + g_assert( 0 ); + return( -1 ); + } +} + /** * vips_band_format_isfloat: * @format: format to test