diff --git a/ChangeLog b/ChangeLog index 06089de8..1557102b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,8 @@ - in jpegsave, don't set JFIF resolution if we set EXIF resolution - bump minimum libheif version to 1.3 [lovell] - dzsave in iiif mode could set info.json dimensions off by one [Linden6] +- pdfload allows dpi and scale to both be set [le0daniel] +- allow gaussblur sigma zero, meaning no blur 9/8/20 started 8.10.1 - fix markdown -> xml conversion in doc generation diff --git a/libvips/convolution/gaussblur.c b/libvips/convolution/gaussblur.c index 215eefd9..e5228542 100644 --- a/libvips/convolution/gaussblur.c +++ b/libvips/convolution/gaussblur.c @@ -4,6 +4,9 @@ * - from vips_sharpen() * 19/11/14 * - change parameters to be more imagemagick-like + * 21/9/20 + * - allow sigma zero, meaning no blur + * - sigma < 0.2 is just copy */ /* @@ -73,23 +76,33 @@ vips_gaussblur_build( VipsObject *object ) if( VIPS_OBJECT_CLASS( vips_gaussblur_parent_class )->build( object ) ) return( -1 ); - if( vips_gaussmat( &t[0], gaussblur->sigma, gaussblur->min_ampl, - "separable", TRUE, - "precision", gaussblur->precision, - NULL ) ) - return( -1 ); + /* vips_gaussmat() will make a 1x1 pixel mask for anything smaller than + * this. + */ + if( sigma < 0.2 ) { + if( vips_copy( gaussblur->in, &t[1], NULL ) ) + return( -1 ); + } + else { + if( vips_gaussmat( &t[0], + gaussblur->sigma, gaussblur->min_ampl, + "separable", TRUE, + "precision", gaussblur->precision, + NULL ) ) + return( -1 ); #ifdef DEBUG - printf( "gaussblur: blurring with:\n" ); - vips_matrixprint( t[0], NULL ); + printf( "gaussblur: blurring with:\n" ); + vips_matrixprint( t[0], NULL ); #endif /*DEBUG*/ - g_info( "gaussblur mask width %d", t[0]->Xsize ); + g_info( "gaussblur mask width %d", t[0]->Xsize ); - if( vips_convsep( gaussblur->in, &t[1], t[0], - "precision", gaussblur->precision, - NULL ) ) - return( -1 ); + if( vips_convsep( gaussblur->in, &t[1], t[0], + "precision", gaussblur->precision, + NULL ) ) + return( -1 ); + } g_object_set( object, "out", vips_image_new(), NULL ); @@ -132,7 +145,7 @@ vips_gaussblur_class_init( VipsGaussblurClass *class ) _( "Sigma of Gaussian" ), VIPS_ARGUMENT_REQUIRED_INPUT, G_STRUCT_OFFSET( VipsGaussblur, sigma ), - 0.01, 1000, 1.5 ); + 0.0, 1000, 1.5 ); VIPS_ARG_DOUBLE( class, "min_ampl", 3, _( "Minimum amplitude" ), diff --git a/libvips/foreign/pdfload.c b/libvips/foreign/pdfload.c index 04caef60..b9a66c10 100644 --- a/libvips/foreign/pdfload.c +++ b/libvips/foreign/pdfload.c @@ -16,6 +16,8 @@ * - reopen the input if we minimised too early * 11/3/20 * - move on top of VipsSource + * 21/9/20 + * - allow dpi and scale to both be set [le0daniel] */ /* @@ -109,10 +111,14 @@ typedef struct _VipsForeignLoadPdf { */ double dpi; - /* Calculate this from DPI. At 72 DPI, we render 1:1 with cairo. + /* Scale by this factor. */ double scale; + /* The total scale factor we render with. + */ + double total_scale; + /* Background colour. */ VipsArrayDouble *background; @@ -170,8 +176,7 @@ vips_foreign_load_pdf_build( VipsObject *object ) GError *error = NULL; - if( !vips_object_argument_isset( object, "scale" ) ) - pdf->scale = pdf->dpi / 72.0; + pdf->total_scale = pdf->scale * pdf->dpi / 72.0; pdf->stream = vips_g_input_stream_new_from_source( pdf->source ); if( !(pdf->doc = poppler_document_new_from_stream( pdf->stream, @@ -338,8 +343,8 @@ vips_foreign_load_pdf_header( VipsForeignLoad *load ) * does round to nearest. Without this, things like * shrink-on-load will break. */ - pdf->pages[i].width = VIPS_RINT( width * pdf->scale ); - pdf->pages[i].height = VIPS_RINT( height * pdf->scale ); + pdf->pages[i].width = VIPS_RINT( width * pdf->total_scale ); + pdf->pages[i].height = VIPS_RINT( height * pdf->total_scale ); if( pdf->pages[i].width > pdf->image.width ) pdf->image.width = pdf->pages[i].width; @@ -421,10 +426,10 @@ vips_foreign_load_pdf_generate( VipsRegion *or, cr = cairo_create( surface ); cairo_surface_destroy( surface ); - cairo_scale( cr, pdf->scale, pdf->scale ); + cairo_scale( cr, pdf->total_scale, pdf->total_scale ); cairo_translate( cr, - (pdf->pages[i].left - rect.left) / pdf->scale, - (pdf->pages[i].top - rect.top) / pdf->scale ); + (pdf->pages[i].left - rect.left) / pdf->total_scale, + (pdf->pages[i].top - rect.top) / pdf->total_scale ); /* poppler is single-threaded, but we don't need to lock since * we're running inside a non-threaded tilecache. @@ -862,9 +867,8 @@ vips_foreign_load_pdf_is_a( const char *filename ) * left. Set to -1 to mean "until the end of the document". Use vips_grid() * to change page layout. * - * Use @dpi to set the rendering resolution. The default is 72. Alternatively, - * you can scale the rendering from the default 1 point == 1 pixel by - * setting @scale. + * Use @dpi to set the rendering resolution. The default is 72. Additionally, + * you can scale by setting @scale. If you set both, they combine. * * Use @background to set the background RGBA colour. The default is 255 * (solid white), use eg. 0 for a transparent background. diff --git a/libvips/resample/thumbnail.c b/libvips/resample/thumbnail.c index b6ffe672..88b18d8a 100644 --- a/libvips/resample/thumbnail.c +++ b/libvips/resample/thumbnail.c @@ -736,24 +736,6 @@ vips_thumbnail_build( VipsObject *object ) return( -1 ); in = t[2]; - /* If there's an alpha, we have to premultiply before shrinking. See - * https://github.com/libvips/libvips/issues/291 - */ - have_premultiplied = FALSE; - if( vips_image_hasalpha( in ) ) { - g_info( "premultiplying alpha" ); - if( vips_premultiply( in, &t[3], NULL ) ) - return( -1 ); - have_premultiplied = TRUE; - - /* vips_premultiply() makes a float image. When we - * vips_unpremultiply() below, we need to cast back to the - * pre-premultiply format. - */ - unpremultiplied_format = in->BandFmt; - in = t[3]; - } - /* Shrink to preshrunk_page_height, so we work for multi-page images. */ vips_thumbnail_calculate_shrink( thumbnail, @@ -771,6 +753,26 @@ vips_thumbnail_build( VipsObject *object ) vshrink = (double) in->Ysize / target_image_height; } + /* If there's an alpha, we have to premultiply before shrinking. See + * https://github.com/libvips/libvips/issues/291 + */ + have_premultiplied = FALSE; + if( vips_image_hasalpha( in ) && + hshrink != 1.0 && + vshrink != 1.0 ) { + g_info( "premultiplying alpha" ); + if( vips_premultiply( in, &t[3], NULL ) ) + return( -1 ); + have_premultiplied = TRUE; + + /* vips_premultiply() makes a float image. When we + * vips_unpremultiply() below, we need to cast back to the + * pre-premultiply format. + */ + unpremultiplied_format = in->BandFmt; + in = t[3]; + } + if( vips_resize( in, &t[4], 1.0 / hshrink, "vscale", 1.0 / vshrink, NULL ) )