--- CV/CV.xs 2017/12/23 05:27:04 1.53 +++ CV/CV.xs 2018/07/30 22:55:46 1.57 @@ -22,6 +22,7 @@ #include #if WEBP +#include #include #endif @@ -202,6 +203,7 @@ } ///////////////////////////////////////////////////////////////////////////// +// memory source for libjpeg static void cv_ms_init (j_decompress_ptr cinfo) { @@ -213,20 +215,26 @@ static boolean cv_ms_fill (j_decompress_ptr cinfo) { - ERREXIT (cinfo, JERR_INPUT_EMPTY); + // unexpected EOF, warn and generate fake EOI marker + + WARNMS (cinfo, JWRN_JPEG_EOF); + + struct jpeg_source_mgr *src = (struct jpeg_source_mgr *)cinfo->src; + + static const JOCTET eoi[] = { 0xFF, JPEG_EOI }; + + src->next_input_byte = eoi; + src->bytes_in_buffer = sizeof (eoi); return TRUE; } static void cv_ms_skip (j_decompress_ptr cinfo, long num_bytes) { - if (num_bytes > 0) - { - struct jpeg_source_mgr *src = (struct jpeg_source_mgr *)cinfo->src; + struct jpeg_source_mgr *src = (struct jpeg_source_mgr *)cinfo->src; - src->next_input_byte += num_bytes; - src->bytes_in_buffer -= num_bytes; - } + src->next_input_byte += num_bytes; + src->bytes_in_buffer -= num_bytes; } static void cv_jpeg_mem_src (j_decompress_ptr cinfo, void *buf, size_t buflen) @@ -255,6 +263,7 @@ PROTOTYPES: ENABLE +# calculate the common prefix length of two strings # missing function in perl. really :) int common_prefix_length (a, b) @@ -405,25 +414,34 @@ CODE: { #if WEBP - guchar *data; STRLEN data_size; int alpha; - WebPDecoderConfig config; + WebPData data; + WebPDemuxer *demux; + WebPIterator iter; + WebPDecoderConfig config; int inw, inh; - data = SvPVbyte (image_data, data_size); + data.bytes = (uint8_t *)SvPVbyte (image_data, data_size); + data.size = data_size; perlinterp_release (); RETVAL = 0; - if (!WebPInitDecoderConfig (&config)) - goto err; + if (!(demux = WebPDemux (&data))) + goto err_demux; + + if (!WebPDemuxGetFrame (demux, 1, &iter)) + goto err_iter; + + if (!WebPInitDecoderConfig (&config)) + goto err_iter; config.options.use_threads = 1; - if (WebPGetFeatures (data, data_size, &config.input) != VP8_STATUS_OK) - goto err; + if (WebPGetFeatures (iter.fragment.bytes, iter.fragment.size, &config.input) != VP8_STATUS_OK) + goto err_iter; inw = config.input.width; inh = config.input.height; @@ -448,11 +466,11 @@ ih = inh; } - alpha = config.input.has_alpha; + alpha = !!config.input.has_alpha; - RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!alpha, 8, iw, ih); + RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, alpha, 8, iw, ih); if (!RETVAL) - goto err; + goto err_iter; config.output.colorspace = alpha ? MODE_RGBA : MODE_RGB; config.output.u.RGBA.rgba = gdk_pixbuf_get_pixels (RETVAL); @@ -460,14 +478,18 @@ config.output.u.RGBA.size = gdk_pixbuf_get_byte_length (RETVAL); config.output.is_external_memory = 1; - if (WebPDecode (data, data_size, &config) != VP8_STATUS_OK) + if (WebPDecode (iter.fragment.bytes, iter.fragment.size, &config) != VP8_STATUS_OK) { g_object_unref (RETVAL); RETVAL = 0; - goto err; + goto err_iter; } - err: + err_iter: + WebPDemuxReleaseIterator (&iter); + err_demux: + WebPDemuxDelete (demux); + perlinterp_acquire (); #else croak ("load_webp: webp not enabled at compile time"); @@ -507,6 +529,9 @@ XSRETURN_UNDEF; } + if (!data_len) + longjmp (jerr.setjmp_buffer, 4); + jpeg_create_decompress (&cinfo); cv_jpeg_mem_src (&cinfo, data, data_len);