--- CV/CV.xs 2017/12/23 04:25:50 1.52 +++ CV/CV.xs 2017/12/23 05:27:04 1.53 @@ -9,6 +9,8 @@ #include #include +#include + #include #include #include @@ -201,6 +203,54 @@ ///////////////////////////////////////////////////////////////////////////// +static void cv_ms_init (j_decompress_ptr cinfo) +{ +} + +static void cv_ms_term (j_decompress_ptr cinfo) +{ +} + +static boolean cv_ms_fill (j_decompress_ptr cinfo) +{ + ERREXIT (cinfo, JERR_INPUT_EMPTY); + + 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; + + 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) +{ + struct jpeg_source_mgr *src; + + if (!cinfo->src) + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ( + (j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (struct jpeg_source_mgr) + ); + + src = (struct jpeg_source_mgr *)cinfo->src; + src->init_source = cv_ms_init; + src->fill_input_buffer = cv_ms_fill; + src->skip_input_data = cv_ms_skip; + src->resync_to_restart = jpeg_resync_to_restart; + src->term_source = cv_ms_term; + src->next_input_byte = (JOCTET *)buf; + src->bytes_in_buffer = buflen; +} + +///////////////////////////////////////////////////////////////////////////// + MODULE = Gtk2::CV PACKAGE = Gtk2::CV PROTOTYPES: ENABLE @@ -312,6 +362,44 @@ OUTPUT: RETVAL +const char * +filetype (SV *image_data) + CODE: +{ + STRLEN data_len; + U8 *data = SvPVbyte (image_data, data_len); + + if (data_len >= 20 + && data[0] == 0xff + && data[1] == 0xd8 + && data[2] == 0xff) + RETVAL = "jpg"; + else if (data_len >= 12 + && data[ 0] == (U8)'R' + && data[ 1] == (U8)'I' + && data[ 2] == (U8)'F' + && data[ 3] == (U8)'F' + && data[ 8] == (U8)'W' + && data[ 9] == (U8)'E' + && data[10] == (U8)'B' + && data[11] == (U8)'P') + RETVAL = "webp"; + else if (data_len >= 16 + && data[ 0] == 0x89 + && data[ 1] == (U8)'P' + && data[ 2] == (U8)'N' + && data[ 3] == (U8)'G' + && data[ 4] == 0x0d + && data[ 5] == 0x0a + && data[ 6] == 0x1a + && data[ 7] == 0x0a) + RETVAL = "png"; + else + RETVAL = "other"; +} + OUTPUT: + RETVAL + GdkPixbuf_noinc * decode_webp (SV *image_data, int thumbnail = 0, int iw = 0, int ih = 0) CODE: @@ -389,23 +477,18 @@ RETVAL GdkPixbuf_noinc * -load_jpeg (SV *path, int thumbnail = 0, int iw = 0, int ih = 0) +decode_jpeg (SV *image_data, int thumbnail = 0, int iw = 0, int ih = 0) CODE: { struct jpeg_decompress_struct cinfo; struct jpg_err_mgr jerr; - guchar *data; int rs; - FILE *fp; volatile GdkPixbuf *pb = 0; + STRLEN data_len; + guchar *data = SvPVbyte (image_data, data_len); RETVAL = 0; - fp = fopen (SvPVbyte_nolen (path), "rb"); - - if (!fp) - XSRETURN_UNDEF; - perlinterp_release (); cinfo.err = jpeg_std_error (&jerr.err); @@ -415,7 +498,6 @@ if ((rs = setjmp (jerr.setjmp_buffer))) { - fclose (fp); jpeg_destroy_decompress (&cinfo); if (pb) @@ -426,8 +508,8 @@ } jpeg_create_decompress (&cinfo); + cv_jpeg_mem_src (&cinfo, data, data_len); - jpeg_stdio_src (&cinfo, fp); jpeg_read_header (&cinfo, TRUE); cinfo.dct_method = JDCT_DEFAULT; @@ -516,7 +598,6 @@ } jpeg_finish_decompress (&cinfo); - fclose (fp); jpeg_destroy_decompress (&cinfo); perlinterp_acquire (); }