… | |
… | |
20 | #include <gtk2perl.h> |
20 | #include <gtk2perl.h> |
21 | |
21 | |
22 | #include <assert.h> |
22 | #include <assert.h> |
23 | |
23 | |
24 | #if WEBP |
24 | #if WEBP |
|
|
25 | #include <webp/demux.h> |
25 | #include <webp/decode.h> |
26 | #include <webp/decode.h> |
26 | #endif |
27 | #endif |
27 | |
28 | |
28 | #include "perlmulticore.h" |
29 | #include "perlmulticore.h" |
29 | |
30 | |
… | |
… | |
200 | |
201 | |
201 | PerlIO_write (fp, a85_buf, a85_ptr - a85_buf); |
202 | PerlIO_write (fp, a85_buf, a85_ptr - a85_buf); |
202 | } |
203 | } |
203 | |
204 | |
204 | ///////////////////////////////////////////////////////////////////////////// |
205 | ///////////////////////////////////////////////////////////////////////////// |
|
|
206 | // memory source for libjpeg |
205 | |
207 | |
206 | static void cv_ms_init (j_decompress_ptr cinfo) |
208 | static void cv_ms_init (j_decompress_ptr cinfo) |
207 | { |
209 | { |
208 | } |
210 | } |
209 | |
211 | |
… | |
… | |
211 | { |
213 | { |
212 | } |
214 | } |
213 | |
215 | |
214 | static boolean cv_ms_fill (j_decompress_ptr cinfo) |
216 | static boolean cv_ms_fill (j_decompress_ptr cinfo) |
215 | { |
217 | { |
216 | ERREXIT (cinfo, JERR_INPUT_EMPTY); |
218 | // unexpected EOF, warn and generate fake EOI marker |
|
|
219 | |
|
|
220 | WARNMS (cinfo, JWRN_JPEG_EOF); |
|
|
221 | |
|
|
222 | struct jpeg_source_mgr *src = (struct jpeg_source_mgr *)cinfo->src; |
|
|
223 | |
|
|
224 | static const JOCTET eoi[] = { 0xFF, JPEG_EOI }; |
|
|
225 | |
|
|
226 | src->next_input_byte = eoi; |
|
|
227 | src->bytes_in_buffer = sizeof (eoi); |
217 | |
228 | |
218 | return TRUE; |
229 | return TRUE; |
219 | } |
230 | } |
220 | |
231 | |
221 | static void cv_ms_skip (j_decompress_ptr cinfo, long num_bytes) |
232 | static void cv_ms_skip (j_decompress_ptr cinfo, long num_bytes) |
222 | { |
233 | { |
223 | if (num_bytes > 0) |
|
|
224 | { |
|
|
225 | struct jpeg_source_mgr *src = (struct jpeg_source_mgr *)cinfo->src; |
234 | struct jpeg_source_mgr *src = (struct jpeg_source_mgr *)cinfo->src; |
226 | |
235 | |
227 | src->next_input_byte += num_bytes; |
236 | src->next_input_byte += num_bytes; |
228 | src->bytes_in_buffer -= num_bytes; |
237 | src->bytes_in_buffer -= num_bytes; |
229 | } |
|
|
230 | } |
238 | } |
231 | |
239 | |
232 | static void cv_jpeg_mem_src (j_decompress_ptr cinfo, void *buf, size_t buflen) |
240 | static void cv_jpeg_mem_src (j_decompress_ptr cinfo, void *buf, size_t buflen) |
233 | { |
241 | { |
234 | struct jpeg_source_mgr *src; |
242 | struct jpeg_source_mgr *src; |
… | |
… | |
253 | |
261 | |
254 | MODULE = Gtk2::CV PACKAGE = Gtk2::CV |
262 | MODULE = Gtk2::CV PACKAGE = Gtk2::CV |
255 | |
263 | |
256 | PROTOTYPES: ENABLE |
264 | PROTOTYPES: ENABLE |
257 | |
265 | |
|
|
266 | # calculate the common prefix length of two strings |
258 | # missing function in perl. really :) |
267 | # missing function in perl. really :) |
259 | int |
268 | int |
260 | common_prefix_length (a, b) |
269 | common_prefix_length (a, b) |
261 | unsigned char *a = (unsigned char *)SvPVutf8_nolen ($arg); |
270 | unsigned char *a = (unsigned char *)SvPVutf8_nolen ($arg); |
262 | unsigned char *b = (unsigned char *)SvPVutf8_nolen ($arg); |
271 | unsigned char *b = (unsigned char *)SvPVutf8_nolen ($arg); |
… | |
… | |
403 | GdkPixbuf_noinc * |
412 | GdkPixbuf_noinc * |
404 | decode_webp (SV *image_data, int thumbnail = 0, int iw = 0, int ih = 0) |
413 | decode_webp (SV *image_data, int thumbnail = 0, int iw = 0, int ih = 0) |
405 | CODE: |
414 | CODE: |
406 | { |
415 | { |
407 | #if WEBP |
416 | #if WEBP |
408 | guchar *data; |
|
|
409 | STRLEN data_size; |
417 | STRLEN data_size; |
410 | int alpha; |
418 | int alpha; |
|
|
419 | WebPData data; |
|
|
420 | WebPDemuxer *demux; |
|
|
421 | WebPIterator iter; |
411 | WebPDecoderConfig config; |
422 | WebPDecoderConfig config; |
412 | int inw, inh; |
423 | int inw, inh; |
413 | |
424 | |
414 | data = SvPVbyte (image_data, data_size); |
425 | data.bytes = (uint8_t *)SvPVbyte (image_data, data_size); |
|
|
426 | data.size = data_size; |
415 | |
427 | |
416 | perlinterp_release (); |
428 | perlinterp_release (); |
417 | |
429 | |
418 | RETVAL = 0; |
430 | RETVAL = 0; |
419 | |
431 | |
|
|
432 | if (!(demux = WebPDemux (&data))) |
|
|
433 | goto err_demux; |
|
|
434 | |
|
|
435 | if (!WebPDemuxGetFrame (demux, 1, &iter)) |
|
|
436 | goto err_iter; |
|
|
437 | |
420 | if (!WebPInitDecoderConfig (&config)) |
438 | if (!WebPInitDecoderConfig (&config)) |
421 | goto err; |
439 | goto err_iter; |
422 | |
440 | |
423 | config.options.use_threads = 1; |
441 | config.options.use_threads = 1; |
424 | |
442 | |
425 | if (WebPGetFeatures (data, data_size, &config.input) != VP8_STATUS_OK) |
443 | if (WebPGetFeatures (iter.fragment.bytes, iter.fragment.size, &config.input) != VP8_STATUS_OK) |
426 | goto err; |
444 | goto err_iter; |
427 | |
445 | |
428 | inw = config.input.width; |
446 | inw = config.input.width; |
429 | inh = config.input.height; |
447 | inh = config.input.height; |
430 | |
448 | |
431 | if (thumbnail) |
449 | if (thumbnail) |
… | |
… | |
446 | { |
464 | { |
447 | iw = inw; |
465 | iw = inw; |
448 | ih = inh; |
466 | ih = inh; |
449 | } |
467 | } |
450 | |
468 | |
451 | alpha = config.input.has_alpha; |
469 | alpha = !!config.input.has_alpha; |
452 | |
470 | |
453 | RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!alpha, 8, iw, ih); |
471 | RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, alpha, 8, iw, ih); |
454 | if (!RETVAL) |
472 | if (!RETVAL) |
455 | goto err; |
473 | goto err_iter; |
456 | |
474 | |
457 | config.output.colorspace = alpha ? MODE_RGBA : MODE_RGB; |
475 | config.output.colorspace = alpha ? MODE_RGBA : MODE_RGB; |
458 | config.output.u.RGBA.rgba = gdk_pixbuf_get_pixels (RETVAL); |
476 | config.output.u.RGBA.rgba = gdk_pixbuf_get_pixels (RETVAL); |
459 | config.output.u.RGBA.stride = gdk_pixbuf_get_rowstride (RETVAL); |
477 | config.output.u.RGBA.stride = gdk_pixbuf_get_rowstride (RETVAL); |
460 | config.output.u.RGBA.size = gdk_pixbuf_get_byte_length (RETVAL); |
478 | config.output.u.RGBA.size = gdk_pixbuf_get_byte_length (RETVAL); |
461 | config.output.is_external_memory = 1; |
479 | config.output.is_external_memory = 1; |
462 | |
480 | |
463 | if (WebPDecode (data, data_size, &config) != VP8_STATUS_OK) |
481 | if (WebPDecode (iter.fragment.bytes, iter.fragment.size, &config) != VP8_STATUS_OK) |
464 | { |
482 | { |
465 | g_object_unref (RETVAL); |
483 | g_object_unref (RETVAL); |
466 | RETVAL = 0; |
484 | RETVAL = 0; |
467 | goto err; |
485 | goto err_iter; |
468 | } |
486 | } |
469 | |
487 | |
470 | err: |
488 | err_iter: |
|
|
489 | WebPDemuxReleaseIterator (&iter); |
|
|
490 | err_demux: |
|
|
491 | WebPDemuxDelete (demux); |
|
|
492 | |
471 | perlinterp_acquire (); |
493 | perlinterp_acquire (); |
472 | #else |
494 | #else |
473 | croak ("load_webp: webp not enabled at compile time"); |
495 | croak ("load_webp: webp not enabled at compile time"); |
474 | #endif |
496 | #endif |
475 | } |
497 | } |
… | |
… | |
504 | g_object_unref ((gpointer)pb); |
526 | g_object_unref ((gpointer)pb); |
505 | |
527 | |
506 | perlinterp_acquire (); |
528 | perlinterp_acquire (); |
507 | XSRETURN_UNDEF; |
529 | XSRETURN_UNDEF; |
508 | } |
530 | } |
|
|
531 | |
|
|
532 | if (!data_len) |
|
|
533 | longjmp (jerr.setjmp_buffer, 4); |
509 | |
534 | |
510 | jpeg_create_decompress (&cinfo); |
535 | jpeg_create_decompress (&cinfo); |
511 | cv_jpeg_mem_src (&cinfo, data, data_len); |
536 | cv_jpeg_mem_src (&cinfo, data, data_len); |
512 | |
537 | |
513 | jpeg_read_header (&cinfo, TRUE); |
538 | jpeg_read_header (&cinfo, TRUE); |