From 9da89f814f76f8e01ae3045fb6c134cf7915b331 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 24 Sep 2023 17:35:56 +0100 Subject: [PATCH] add error handling for vips2tiff jpeg tile write --- libvips/foreign/dzsave.c | 2 ++ libvips/foreign/vips2jpeg.c | 21 ++++++++++++++++++-- libvips/foreign/vips2tiff.c | 38 +++++++++++++++++++++++++------------ 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index 63ce50dfc7..24da2b1d5c 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -1599,6 +1599,8 @@ strip_save(Level *level) image_strip_init(&strip, level); + vips_image_set_int(strip.image, "vips-no-minimise", 1); + if (vips_threadpool_run(strip.image, vips_thread_state_new, image_strip_allocate, diff --git a/libvips/foreign/vips2jpeg.c b/libvips/foreign/vips2jpeg.c index e3bbc14bab..037f05c170 100644 --- a/libvips/foreign/vips2jpeg.c +++ b/libvips/foreign/vips2jpeg.c @@ -139,8 +139,6 @@ #endif /*HAVE_CONFIG_H*/ #include -#ifdef HAVE_JPEG - #include #include #include @@ -152,6 +150,8 @@ #include "pforeign.h" +#ifdef HAVE_JPEG + #include "jpeg.h" #define ICC_MARKER (JPEG_APP0 + 2) /* JPEG marker code for ICC */ @@ -1037,4 +1037,21 @@ vips__jpeg_region_write_target(VipsRegion *region, VipsRect *rect, return 0; } +#else /*!HAVE_JPEG*/ + +int +vips__jpeg_region_write_target(VipsRegion *region, VipsRect *rect, + VipsTarget *target, + int Q, const char *profile, + gboolean optimize_coding, gboolean progressive, + gboolean strip, gboolean trellis_quant, + gboolean overshoot_deringing, gboolean optimize_scans, + int quant_table, VipsForeignSubsample subsample_mode, + int restart_interval) +{ + vips_error("jp2k", + "%s", _("libvips built without JPEG support")); + return -1; +} + #endif /*HAVE_JPEG*/ diff --git a/libvips/foreign/vips2tiff.c b/libvips/foreign/vips2tiff.c index d1e60553a1..50cc0fdfd0 100644 --- a/libvips/foreign/vips2tiff.c +++ b/libvips/foreign/vips2tiff.c @@ -698,8 +698,11 @@ static int wtiff_compress_jpeg(Wtiff *wtiff, VipsRegion *strip, VipsRect *tile, VipsTarget *target) { + size_t sizeof_pel = VIPS_REGION_SIZEOF_PEL(strip); + struct jpeg_compress_struct cinfo; - struct jpeg_error_mgr jerr; + ErrorManager eman; + VipsPel *line; #ifdef DEBUG printf("wtiff_compress_jpeg: left = %d, top = %d, " @@ -708,13 +711,31 @@ wtiff_compress_jpeg(Wtiff *wtiff, #endif /*DEBUG*/ // we could have one of these per thread and reuse it for a small speedup - cinfo.err = jpeg_std_error(&jerr); - jpeg_create_compress(&cinfo); + cinfo.err = jpeg_std_error(&eman.pub); + cinfo.dest = NULL; + eman.pub.error_exit = vips__new_error_exit; + eman.pub.output_message = vips__new_output_message; + eman.fp = NULL; + + /// we need a line buffer to pad edge tiles + line = VIPS_MALLOC(NULL, wtiff->tilew * sizeof_pel); + + /* Error handling. The error message will have ben set by our handlers. + */ + if (setjmp(eman.jmp)) { + jpeg_destroy_compress(&cinfo); + VIPS_FREE(line); + return -1; + } /* Attach output. */ vips__jpeg_target_dest(&cinfo, target); + /* Make jpeg compression object. + */ + jpeg_create_compress(&cinfo); + wtiff_compress_jpeg_header(wtiff, &cinfo, strip->im); // don't output tables, just coefficients @@ -725,12 +746,7 @@ wtiff_compress_jpeg(Wtiff *wtiff, if (tile->width < wtiff->tilew || tile->height < wtiff->tileh) { - size_t sizeof_pel = VIPS_REGION_SIZEOF_PEL(strip); - VipsPel *line = VIPS_MALLOC(NULL, wtiff->tilew * sizeof_pel); - - JSAMPROW row_pointer[1]; - - row_pointer[0] = line; + JSAMPROW row_pointer[1] = { line }; for (int y = 0; y < tile->height; y++) { memcpy(line, VIPS_REGION_ADDR(strip, tile->left, tile->top + y), @@ -742,8 +758,6 @@ wtiff_compress_jpeg(Wtiff *wtiff, for (int y = tile->height; y < wtiff->tileh; y++) { jpeg_write_scanlines(&cinfo, row_pointer, 1); } - - g_free(row_pointer[0]); } else { for (int y = 0; y < tile->height; y++) { @@ -752,8 +766,8 @@ wtiff_compress_jpeg(Wtiff *wtiff, row_pointer[0] = VIPS_REGION_ADDR(strip, tile->left, tile->top + y); jpeg_write_scanlines(&cinfo, row_pointer, 1); } - } + jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo);