ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CV/CV.xs
(Generate patch)

Comparing CV/CV.xs (file contents):
Revision 1.58 by root, Mon Jan 4 04:49:04 2021 UTC vs.
Revision 1.67 by root, Fri May 12 01:23:57 2023 UTC

303 303
304MODULE = Gtk2::CV PACKAGE = Gtk2::CV 304MODULE = Gtk2::CV PACKAGE = Gtk2::CV
305 305
306PROTOTYPES: ENABLE 306PROTOTYPES: ENABLE
307 307
308void
309_exit (int code)
310
308# calculate the common prefix length of two strings 311# calculate the common prefix length of two strings
309# missing function in perl. really :) 312# missing function in perl. really :)
310int 313int
311common_prefix_length (a, b) 314common_prefix_length (a, b)
312 unsigned char *a = (unsigned char *)SvPVutf8_nolen ($arg); 315 unsigned char *a = (unsigned char *)SvPVutf8_nolen ($arg);
418 CODE: 421 CODE:
419{ 422{
420 STRLEN data_len; 423 STRLEN data_len;
421 U8 *data = SvPVbyte (image_data, data_len); 424 U8 *data = SvPVbyte (image_data, data_len);
422 static const unsigned char jxl_header[] = { 425 static const unsigned char jxl_header[] = {
423 0, 0, 0, 0x0c, 0x4a, 0x58, 0x4c, 0x20, 426 0, 0, 0, 0x0c, 0x4a, 0x58, 0x4c, 0x20, 0x0d, 0xa, 0x87, 0x0a
424 0x0d, 0xa, 0x87, 0x0a, 0, 0, 0, 0x14,
425 0x66, 0x74, 0x79, 0x70, 0x6a, 0x78, 0x6c, 0x20,
426 0, 0, 0, 0, 0x6a, 0x78, 0x6c, 0x20,
427 }; 427 };
428 428
429 if (data_len >= 20 429 if (data_len >= 20
430 && data[0] == 0xff 430 && data[0] == 0xff
431 && data[1] == 0xd8 431 && data[1] == 0xd8
450 && data[ 5] == 0x0a 450 && data[ 5] == 0x0a
451 && data[ 6] == 0x1a 451 && data[ 6] == 0x1a
452 && data[ 7] == 0x0a) 452 && data[ 7] == 0x0a)
453 RETVAL = "image/png"; 453 RETVAL = "image/png";
454 else if (data_len >= sizeof (jxl_header) && memcmp (data, jxl_header, sizeof (jxl_header)) == 0) 454 else if (data_len >= sizeof (jxl_header) && memcmp (data, jxl_header, sizeof (jxl_header)) == 0)
455 RETVAL = "image/jxl"; // todo: might want to use JxlSignatureCheck
456 else if (data_len >= 2
457 && data[0] == 0xff
458 && data[1] == 0x0a)
455 RETVAL = "image/jxl"; 459 RETVAL = "image/jxl";
460 else if (data_len >= 13
461 && data[0] == 'G'
462 && data[1] == 'I'
463 && data[2] == 'F'
464 && data[3] == '8'
465 //&& (data[4] == '7' || data[4] == '9')
466 && data[5] == 'a')
467 {
468 RETVAL = "image/gif";
469
470 // now see if its animated - we require the netscape application header for this
471 int ofs = 13;
472
473 if (data[10] & 0x80)
474 ofs += (1 << ((data[10] & 7) + 1)) * 3;
475
476 if (data_len >= ofs + 2 + 1 + 11)
477 {
478
479 // skip a graphic control extension block. we assume
480 // there is at most one such block - while the NAB
481 // has to come firstz, some files do not obey this
482 if (data[ofs] == 0x21 && data[ofs + 1] == 0xf9)
483 ofs += 3 + data[ofs + 2] + 1;
484
485 if (data_len >= ofs + 2 + 1 + 11)
486 if (!memcmp (data + ofs, "\x21\xff\x0bNETSCAPE2.0", sizeof ("\x21\xff\x0bNETSCAPE2.0") - 1))
487 RETVAL = "video/gif";
488 }
489 }
490 else if (data_len >= 0x8000 + 6
491 && data[0x8000+0] == 0
492 && data[0x8000+1] == (U8)'B'
493 && data[0x8000+2] == (U8)'E'
494 && data[0x8000+3] == (U8)'A'
495 && data[0x8000+4] == (U8)'0'
496 && data[0x8000+5] == (U8)'1')
497 RETVAL = "video/iso-bluray";
498
456 else 499 else
457 XSRETURN_UNDEF; 500 XSRETURN_UNDEF;
458} 501}
459 OUTPUT: 502 OUTPUT:
460 RETVAL 503 RETVAL
551GdkPixbuf_noinc * 594GdkPixbuf_noinc *
552decode_jxl (SV *image_data, int thumbnail = 0, int iw = 0, int ih = 0) 595decode_jxl (SV *image_data, int thumbnail = 0, int iw = 0, int ih = 0)
553 CODE: 596 CODE:
554{ 597{
555#if JXL 598#if JXL
556 JxlDecoder *dec = JxlDecoderCreate (0); 599 JxlDecoder *dec;
557 JxlBasicInfo info; 600 JxlBasicInfo info;
558 const uint8_t *next_in = (uint8_t *)SvPVbyte_nolen (image_data); 601 const uint8_t *next_in = (uint8_t *)SvPVbyte_nolen (image_data);
559 size_t avail_in = SvCUR (image_data); 602 size_t avail_in = SvCUR (image_data);
560 const char *error = 0; 603 const char *error = 0;
604 JxlDecoderStatus status;
605 static void *runner_cache;
561 void *runner = 0; 606 void *runner = 0;
562 struct bmff_box box; 607
608 RETVAL = 0;
609
610 if (runner_cache)
611 runner = runner_cache;
612 else
613 runner = JxlThreadParallelRunnerCreate (0, JxlThreadParallelRunnerDefaultNumWorkerThreads ());
614
615 runner_cache = 0;
563 616
564 perlinterp_release (); 617 perlinterp_release ();
565 618
566 RETVAL = 0; 619 dec = JxlDecoderCreate (0);
567 620
568 error = "JxlDecoderCreate failed"; 621 error = "JxlDecoderCreate failed";
569 if (!dec) 622 if (!dec)
570 goto done; 623 goto done;
571 624
572 runner = JxlThreadParallelRunnerCreate (0, JxlThreadParallelRunnerDefaultNumWorkerThreads ()); 625 status = JxlDecoderSetParallelRunner (dec, JxlThreadParallelRunner, runner);
573
574 error = "JxlDecoderSetParallelRunner failed"; 626 error = "JxlDecoderSetParallelRunner failed";
575 if (JxlDecoderSetParallelRunner (dec, JxlThreadParallelRunner, runner) != JXL_DEC_SUCCESS) 627 if (status != JXL_DEC_SUCCESS)
576 goto done; 628 goto done;
577 629
578 error = "JxlDecoderSubscribeEvents failed"; 630 error = "JxlDecoderSubscribeEvents failed";
579 if (JxlDecoderSubscribeEvents (dec, JXL_DEC_FULL_IMAGE | 0xffc0) != JXL_DEC_SUCCESS) 631 status = JxlDecoderSubscribeEvents (dec, JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE);
632 if (status != JXL_DEC_SUCCESS)
580 goto done; 633 goto done;
581 634
635 status = JxlDecoderSetInput (dec, next_in, avail_in);
636 error = "JxlDecoderSetInput failed";
637 if (status != JXL_DEC_SUCCESS)
638 goto done;
639
582 for (;;) 640 for (;;)
583 { 641 {
584 JxlDecoderStatus status = JxlDecoderProcessInput (dec, &next_in, &avail_in); 642 status = JxlDecoderProcessInput (dec);
585 643
586 printf ("status %d\n",status);
587
588 switch (status) 644 switch (status)
589 { 645 {
646 case JXL_DEC_FULL_IMAGE:
647 error = 0;
648 goto done;
649
590 case JXL_DEC_ERROR: 650 case JXL_DEC_ERROR:
591 error = "JxlDecoderProcessInput failed"; 651 error = "JxlDecoderProcessInput failed";
592 goto done; 652 goto done;
593 653
594 case JXL_DEC_NEED_MORE_INPUT: 654 case JXL_DEC_NEED_MORE_INPUT:
595 error = "incomplete file"; 655 error = "incomplete file";
596 goto done; 656 goto done;
597 657
598 case JXL_DEC_SUCCESS: 658 case JXL_DEC_SUCCESS:
659 error = "incomplete decode";
599 goto done; 660 goto done;
600 661
601 case JXL_DEC_NEED_IMAGE_OUT_BUFFER: 662 case JXL_DEC_BASIC_INFO:
602 { 663 {
664 status = JxlDecoderGetBasicInfo (dec, &info);
603 error = "JxlDecoderGetBasicInfo failed"; 665 error = "JxlDecoderGetBasicInfo failed";
604 if (JxlDecoderGetBasicInfo (dec, &info) != JXL_DEC_SUCCESS) 666 if (status != JXL_DEC_SUCCESS)
605 goto done; 667 goto done;
606 668
607 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!info.alpha_bits, 8, info.xsize, info.ysize); 669 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!info.alpha_bits, 8, info.xsize, info.ysize);
608 error = "unable to allocate pixbuf"; 670 error = "unable to allocate pixbuf";
609 if (!RETVAL) 671 if (!RETVAL)
614 JXL_TYPE_UINT8, 676 JXL_TYPE_UINT8,
615 JXL_NATIVE_ENDIAN, 677 JXL_NATIVE_ENDIAN,
616 gdk_pixbuf_get_rowstride (RETVAL) 678 gdk_pixbuf_get_rowstride (RETVAL)
617 }; 679 };
618 680
681 // cannot use gdk_pixbuf_get_byte_length because that does
682 // not return the size of the buffer, but the size of the buffer without
683 // the last padding bytes. the internal buffer is rowstride * ysize,
684 // and this is what the jxl decoder needs. none of this is documented
685 // in either library, of course.
686
687 status = JxlDecoderSetImageOutBuffer (
688 dec,
689 &format,
690 gdk_pixbuf_get_pixels (RETVAL),
691 gdk_pixbuf_get_rowstride (RETVAL) * info.ysize
692 );
619 error = "JxlDecoderSetImageOutBuffer failed"; 693 error = "JxlDecoderSetImageOutBuffer failed";
620 if (JxlDecoderSetImageOutBuffer (
621 dec,
622 &format,
623 gdk_pixbuf_get_pixels (RETVAL),
624 gdk_pixbuf_get_byte_length (RETVAL)
625 ) != JXL_DEC_SUCCESS) 694 if (status != JXL_DEC_SUCCESS)
626 goto done; 695 goto done;
627 } 696 }
628 break; 697 break;
629 698
630 default: 699 default:
635 704
636 done: 705 done:
637 if (dec) 706 if (dec)
638 JxlDecoderDestroy (dec); 707 JxlDecoderDestroy (dec);
639 708
709 perlinterp_acquire ();
710
640 if (runner) 711 if (runner_cache)
641 JxlThreadParallelRunnerDestroy (runner); 712 JxlThreadParallelRunnerDestroy (runner);
642 713
643 perlinterp_acquire (); 714 runner_cache = runner;
644 715
645 if (error) 716 if (error)
646 { 717 {
647 if (RETVAL) 718 if (RETVAL)
648 g_object_unref (RETVAL); 719 g_object_unref (RETVAL);
649 720
650 croak ("load_jxl: %s", error); 721 croak ("load_jxl: %s (status %d)", error, status);
651 } 722 }
652#else 723#else
653 croak ("load_jxl: jpeg-xl not enabled at compile time"); 724 croak ("load_jxl: jpeg-xl not enabled at compile time");
654#endif 725#endif
655} 726}
847 CODE: 918 CODE:
848{ 919{
849 STRLEN plen; 920 STRLEN plen;
850 U8 *path = (U8 *)SvPV (pathsv, plen); 921 U8 *path = (U8 *)SvPV (pathsv, plen);
851 U8 *pend = path + plen; 922 U8 *pend = path + plen;
852 U8 dst [plen * 6 * 3], *dstp = dst; 923 U8 dst [plen * 8 * 3], *dstp = dst;
853 924
854 while (path < pend) 925 while (path < pend)
855 { 926 {
856 U8 ch = *path; 927 U8 ch = *path;
857 928
859 *dstp++ = *path++; 930 *dstp++ = *path++;
860 else if (ch >= 'A' && ch <= 'Z') 931 else if (ch >= 'A' && ch <= 'Z')
861 *dstp++ = *path++ + ('a' - 'A'); 932 *dstp++ = *path++ + ('a' - 'A');
862 else if (ch >= '0' && ch <= '9') 933 else if (ch >= '0' && ch <= '9')
863 { 934 {
935 /* version sort, up to 8 digits */
864 STRLEN el, nl = 0; 936 STRLEN el, nl = 0;
865 while (*path >= '0' && *path <= '9' && path < pend) 937 while (*path >= '0' && *path <= '9' && path < pend)
866 path++, nl++; 938 path++, nl++;
867 939
868 for (el = nl; el < 6; el++) 940 for (el = nl; el < 8; el++)
869 *dstp++ = '0'; 941 *dstp++ = '0';
870 942
871 memcpy (dstp, path - nl, nl); 943 memcpy (dstp, path - nl, nl);
872 dstp += nl; 944 dstp += nl;
873 } 945 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines