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.69 by root, Wed Jun 7 17:18:46 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+1] == (U8)'B'
492 && data[0x8000+2] == (U8)'E'
493 && data[0x8000+3] == (U8)'A'
494 && data[0x8000+4] == (U8)'0'
495 && data[0x8000+5] == (U8)'1')
496 RETVAL = "video/iso-bluray";
497 else if (data_len >= 0x8000 + 6
498 && data[0x8000+1] == (U8)'C'
499 && data[0x8000+2] == (U8)'D'
500 && data[0x8000+3] == (U8)'0'
501 && data[0x8000+4] == (U8)'0'
502 && data[0x8000+5] == (U8)'1')
503 RETVAL = "video/iso9660";
504
456 else 505 else
457 XSRETURN_UNDEF; 506 XSRETURN_UNDEF;
458} 507}
459 OUTPUT: 508 OUTPUT:
460 RETVAL 509 RETVAL
551GdkPixbuf_noinc * 600GdkPixbuf_noinc *
552decode_jxl (SV *image_data, int thumbnail = 0, int iw = 0, int ih = 0) 601decode_jxl (SV *image_data, int thumbnail = 0, int iw = 0, int ih = 0)
553 CODE: 602 CODE:
554{ 603{
555#if JXL 604#if JXL
556 JxlDecoder *dec = JxlDecoderCreate (0); 605 JxlDecoder *dec;
557 JxlBasicInfo info; 606 JxlBasicInfo info;
558 const uint8_t *next_in = (uint8_t *)SvPVbyte_nolen (image_data); 607 const uint8_t *next_in = (uint8_t *)SvPVbyte_nolen (image_data);
559 size_t avail_in = SvCUR (image_data); 608 size_t avail_in = SvCUR (image_data);
560 const char *error = 0; 609 const char *error = 0;
610 JxlDecoderStatus status;
611 static void *runner_cache;
561 void *runner = 0; 612 void *runner = 0;
562 struct bmff_box box; 613
614 RETVAL = 0;
615
616 if (runner_cache)
617 runner = runner_cache;
618 else
619 runner = JxlThreadParallelRunnerCreate (0, JxlThreadParallelRunnerDefaultNumWorkerThreads ());
620
621 runner_cache = 0;
563 622
564 perlinterp_release (); 623 perlinterp_release ();
565 624
566 RETVAL = 0; 625 dec = JxlDecoderCreate (0);
567 626
568 error = "JxlDecoderCreate failed"; 627 error = "JxlDecoderCreate failed";
569 if (!dec) 628 if (!dec)
570 goto done; 629 goto done;
571 630
572 runner = JxlThreadParallelRunnerCreate (0, JxlThreadParallelRunnerDefaultNumWorkerThreads ()); 631 status = JxlDecoderSetParallelRunner (dec, JxlThreadParallelRunner, runner);
573
574 error = "JxlDecoderSetParallelRunner failed"; 632 error = "JxlDecoderSetParallelRunner failed";
575 if (JxlDecoderSetParallelRunner (dec, JxlThreadParallelRunner, runner) != JXL_DEC_SUCCESS) 633 if (status != JXL_DEC_SUCCESS)
576 goto done; 634 goto done;
577 635
578 error = "JxlDecoderSubscribeEvents failed"; 636 error = "JxlDecoderSubscribeEvents failed";
579 if (JxlDecoderSubscribeEvents (dec, JXL_DEC_FULL_IMAGE | 0xffc0) != JXL_DEC_SUCCESS) 637 status = JxlDecoderSubscribeEvents (dec, JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE);
638 if (status != JXL_DEC_SUCCESS)
580 goto done; 639 goto done;
581 640
641 status = JxlDecoderSetInput (dec, next_in, avail_in);
642 error = "JxlDecoderSetInput failed";
643 if (status != JXL_DEC_SUCCESS)
644 goto done;
645
582 for (;;) 646 for (;;)
583 { 647 {
584 JxlDecoderStatus status = JxlDecoderProcessInput (dec, &next_in, &avail_in); 648 status = JxlDecoderProcessInput (dec);
585 649
586 printf ("status %d\n",status);
587
588 switch (status) 650 switch (status)
589 { 651 {
652 case JXL_DEC_FULL_IMAGE:
653 error = 0;
654 goto done;
655
590 case JXL_DEC_ERROR: 656 case JXL_DEC_ERROR:
591 error = "JxlDecoderProcessInput failed"; 657 error = "JxlDecoderProcessInput failed";
592 goto done; 658 goto done;
593 659
594 case JXL_DEC_NEED_MORE_INPUT: 660 case JXL_DEC_NEED_MORE_INPUT:
595 error = "incomplete file"; 661 error = "incomplete file";
596 goto done; 662 goto done;
597 663
598 case JXL_DEC_SUCCESS: 664 case JXL_DEC_SUCCESS:
665 error = "incomplete decode";
599 goto done; 666 goto done;
600 667
601 case JXL_DEC_NEED_IMAGE_OUT_BUFFER: 668 case JXL_DEC_BASIC_INFO:
602 { 669 {
670 status = JxlDecoderGetBasicInfo (dec, &info);
603 error = "JxlDecoderGetBasicInfo failed"; 671 error = "JxlDecoderGetBasicInfo failed";
604 if (JxlDecoderGetBasicInfo (dec, &info) != JXL_DEC_SUCCESS) 672 if (status != JXL_DEC_SUCCESS)
605 goto done; 673 goto done;
606 674
607 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!info.alpha_bits, 8, info.xsize, info.ysize); 675 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!info.alpha_bits, 8, info.xsize, info.ysize);
608 error = "unable to allocate pixbuf"; 676 error = "unable to allocate pixbuf";
609 if (!RETVAL) 677 if (!RETVAL)
614 JXL_TYPE_UINT8, 682 JXL_TYPE_UINT8,
615 JXL_NATIVE_ENDIAN, 683 JXL_NATIVE_ENDIAN,
616 gdk_pixbuf_get_rowstride (RETVAL) 684 gdk_pixbuf_get_rowstride (RETVAL)
617 }; 685 };
618 686
687 // cannot use gdk_pixbuf_get_byte_length because that does
688 // not return the size of the buffer, but the size of the buffer without
689 // the last padding bytes. the internal buffer is rowstride * ysize,
690 // and this is what the jxl decoder needs. none of this is documented
691 // in either library, of course.
692
693 status = JxlDecoderSetImageOutBuffer (
694 dec,
695 &format,
696 gdk_pixbuf_get_pixels (RETVAL),
697 gdk_pixbuf_get_rowstride (RETVAL) * info.ysize
698 );
619 error = "JxlDecoderSetImageOutBuffer failed"; 699 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) 700 if (status != JXL_DEC_SUCCESS)
626 goto done; 701 goto done;
627 } 702 }
628 break; 703 break;
629 704
630 default: 705 default:
635 710
636 done: 711 done:
637 if (dec) 712 if (dec)
638 JxlDecoderDestroy (dec); 713 JxlDecoderDestroy (dec);
639 714
715 perlinterp_acquire ();
716
640 if (runner) 717 if (runner_cache)
641 JxlThreadParallelRunnerDestroy (runner); 718 JxlThreadParallelRunnerDestroy (runner);
642 719
643 perlinterp_acquire (); 720 runner_cache = runner;
644 721
645 if (error) 722 if (error)
646 { 723 {
647 if (RETVAL) 724 if (RETVAL)
648 g_object_unref (RETVAL); 725 g_object_unref (RETVAL);
649 726
650 croak ("load_jxl: %s", error); 727 croak ("load_jxl: %s (status %d)", error, status);
651 } 728 }
652#else 729#else
653 croak ("load_jxl: jpeg-xl not enabled at compile time"); 730 croak ("load_jxl: jpeg-xl not enabled at compile time");
654#endif 731#endif
655} 732}
847 CODE: 924 CODE:
848{ 925{
849 STRLEN plen; 926 STRLEN plen;
850 U8 *path = (U8 *)SvPV (pathsv, plen); 927 U8 *path = (U8 *)SvPV (pathsv, plen);
851 U8 *pend = path + plen; 928 U8 *pend = path + plen;
852 U8 dst [plen * 6 * 3], *dstp = dst; 929 U8 dst [plen * 8 * 3], *dstp = dst;
853 930
854 while (path < pend) 931 while (path < pend)
855 { 932 {
856 U8 ch = *path; 933 U8 ch = *path;
857 934
859 *dstp++ = *path++; 936 *dstp++ = *path++;
860 else if (ch >= 'A' && ch <= 'Z') 937 else if (ch >= 'A' && ch <= 'Z')
861 *dstp++ = *path++ + ('a' - 'A'); 938 *dstp++ = *path++ + ('a' - 'A');
862 else if (ch >= '0' && ch <= '9') 939 else if (ch >= '0' && ch <= '9')
863 { 940 {
941 /* version sort, up to 8 digits */
864 STRLEN el, nl = 0; 942 STRLEN el, nl = 0;
865 while (*path >= '0' && *path <= '9' && path < pend) 943 while (*path >= '0' && *path <= '9' && path < pend)
866 path++, nl++; 944 path++, nl++;
867 945
868 for (el = nl; el < 6; el++) 946 for (el = nl; el < 8; el++)
869 *dstp++ = '0'; 947 *dstp++ = '0';
870 948
871 memcpy (dstp, path - nl, nl); 949 memcpy (dstp, path - nl, nl);
872 dstp += nl; 950 dstp += nl;
873 } 951 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines