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

Comparing CV/CV.xs (file contents):
Revision 1.59 by root, Sat Apr 10 03:32:09 2021 UTC vs.
Revision 1.70 by root, Thu Jun 8 15:42:03 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);
318 { 321 {
319 RETVAL += (*a & 0xc0) != 0x80; 322 RETVAL += (*a & 0xc0) != 0x80;
320 a++, b++; 323 a++, b++;
321 } 324 }
322 325
326 OUTPUT:
327 RETVAL
328
329int
330common_prefix_length_byte (a, b)
331 unsigned char *a = (unsigned char *)SvPVbyte_nolen ($arg);
332 unsigned char *b = (unsigned char *)SvPVbyte_nolen ($arg);
333 CODE:
334 RETVAL = 0;
335 while (*a == *b && *a)
336 a++, b++, RETVAL++;
323 OUTPUT: 337 OUTPUT:
324 RETVAL 338 RETVAL
325 339
326const char * 340const char *
327magic (SV *path_or_data) 341magic (SV *path_or_data)
418 CODE: 432 CODE:
419{ 433{
420 STRLEN data_len; 434 STRLEN data_len;
421 U8 *data = SvPVbyte (image_data, data_len); 435 U8 *data = SvPVbyte (image_data, data_len);
422 static const unsigned char jxl_header[] = { 436 static const unsigned char jxl_header[] = {
423 0, 0, 0, 0x0c, 0x4a, 0x58, 0x4c, 0x20, 437 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 }; 438 };
428 439
429 if (data_len >= 20 440 if (data_len >= 20
430 && data[0] == 0xff 441 && data[0] == 0xff
431 && data[1] == 0xd8 442 && data[1] == 0xd8
450 && data[ 5] == 0x0a 461 && data[ 5] == 0x0a
451 && data[ 6] == 0x1a 462 && data[ 6] == 0x1a
452 && data[ 7] == 0x0a) 463 && data[ 7] == 0x0a)
453 RETVAL = "image/png"; 464 RETVAL = "image/png";
454 else if (data_len >= sizeof (jxl_header) && memcmp (data, jxl_header, sizeof (jxl_header)) == 0) 465 else if (data_len >= sizeof (jxl_header) && memcmp (data, jxl_header, sizeof (jxl_header)) == 0)
466 RETVAL = "image/jxl"; // todo: might want to use JxlSignatureCheck
467 else if (data_len >= 2
468 && data[0] == 0xff
469 && data[1] == 0x0a)
455 RETVAL = "image/jxl"; 470 RETVAL = "image/jxl";
471 else if (data_len >= 13
472 && data[0] == 'G'
473 && data[1] == 'I'
474 && data[2] == 'F'
475 && data[3] == '8'
476 //&& (data[4] == '7' || data[4] == '9')
477 && data[5] == 'a')
478 {
479 RETVAL = "image/gif";
480
481 // now see if its animated - we require the netscape application header for this
482 int ofs = 13;
483
484 if (data[10] & 0x80)
485 ofs += (1 << ((data[10] & 7) + 1)) * 3;
486
487 if (data_len >= ofs + 2 + 1 + 11)
488 {
489
490 // skip a graphic control extension block. we assume
491 // there is at most one such block - while the NAB
492 // has to come firstz, some files do not obey this
493 if (data[ofs] == 0x21 && data[ofs + 1] == 0xf9)
494 ofs += 3 + data[ofs + 2] + 1;
495
496 if (data_len >= ofs + 2 + 1 + 11)
497 if (!memcmp (data + ofs, "\x21\xff\x0bNETSCAPE2.0", sizeof ("\x21\xff\x0bNETSCAPE2.0") - 1))
498 RETVAL = "video/gif";
499 }
500 }
501 else if (data_len >= 0x8000 + 6
502 && data[0x8000+1] == (U8)'B'
503 && data[0x8000+2] == (U8)'E'
504 && data[0x8000+3] == (U8)'A'
505 && data[0x8000+4] == (U8)'0'
506 && data[0x8000+5] == (U8)'1')
507 RETVAL = "video/iso-bluray";
508 else if (data_len >= 0x8000 + 6
509 && data[0x8000+1] == (U8)'C'
510 && data[0x8000+2] == (U8)'D'
511 && data[0x8000+3] == (U8)'0'
512 && data[0x8000+4] == (U8)'0'
513 && data[0x8000+5] == (U8)'1')
514 RETVAL = "video/iso9660";
515
456 else 516 else
457 XSRETURN_UNDEF; 517 XSRETURN_UNDEF;
458} 518}
459 OUTPUT: 519 OUTPUT:
460 RETVAL 520 RETVAL
551GdkPixbuf_noinc * 611GdkPixbuf_noinc *
552decode_jxl (SV *image_data, int thumbnail = 0, int iw = 0, int ih = 0) 612decode_jxl (SV *image_data, int thumbnail = 0, int iw = 0, int ih = 0)
553 CODE: 613 CODE:
554{ 614{
555#if JXL 615#if JXL
556 JxlDecoder *dec = JxlDecoderCreate (0); 616 JxlDecoder *dec;
557 JxlBasicInfo info; 617 JxlBasicInfo info;
558 const uint8_t *next_in = (uint8_t *)SvPVbyte_nolen (image_data); 618 const uint8_t *next_in = (uint8_t *)SvPVbyte_nolen (image_data);
559 size_t avail_in = SvCUR (image_data); 619 size_t avail_in = SvCUR (image_data);
560 const char *error = 0; 620 const char *error = 0;
621 JxlDecoderStatus status;
622 static void *runner_cache;
561 void *runner = 0; 623 void *runner = 0;
562 struct bmff_box box; 624
625 RETVAL = 0;
626
627 if (runner_cache)
628 runner = runner_cache;
629 else
630 runner = JxlThreadParallelRunnerCreate (0, JxlThreadParallelRunnerDefaultNumWorkerThreads ());
631
632 runner_cache = 0;
563 633
564 perlinterp_release (); 634 perlinterp_release ();
565 635
566 RETVAL = 0; 636 dec = JxlDecoderCreate (0);
567 637
568 error = "JxlDecoderCreate failed"; 638 error = "JxlDecoderCreate failed";
569 if (!dec) 639 if (!dec)
570 goto done; 640 goto done;
571 641
572 runner = JxlThreadParallelRunnerCreate (0, JxlThreadParallelRunnerDefaultNumWorkerThreads ()); 642 status = JxlDecoderSetParallelRunner (dec, JxlThreadParallelRunner, runner);
573
574 error = "JxlDecoderSetParallelRunner failed"; 643 error = "JxlDecoderSetParallelRunner failed";
575 if (JxlDecoderSetParallelRunner (dec, JxlThreadParallelRunner, runner) != JXL_DEC_SUCCESS) 644 if (status != JXL_DEC_SUCCESS)
576 goto done; 645 goto done;
577 646
578 error = "JxlDecoderSubscribeEvents failed"; 647 error = "JxlDecoderSubscribeEvents failed";
579 if (JxlDecoderSubscribeEvents (dec, JXL_DEC_FULL_IMAGE | JXL_DEC_BASIC_INFO) != JXL_DEC_SUCCESS) 648 status = JxlDecoderSubscribeEvents (dec, JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE);
649 if (status != JXL_DEC_SUCCESS)
580 goto done; 650 goto done;
581 651
652 status = JxlDecoderSetInput (dec, next_in, avail_in);
582 error = "JxlDecoderSetInput failed"; 653 error = "JxlDecoderSetInput failed";
583 if (JxlDecoderSetInput (dec, next_in, avail_in) != JXL_DEC_SUCCESS) 654 if (status != JXL_DEC_SUCCESS)
584 goto done; 655 goto done;
585 656
586 for (;;) 657 for (;;)
587 { 658 {
588 JxlDecoderStatus status = JxlDecoderProcessInput (dec); 659 status = JxlDecoderProcessInput (dec);
589 660
590 printf ("status %d\n",status);
591
592 switch (status) 661 switch (status)
593 { 662 {
663 case JXL_DEC_FULL_IMAGE:
664 error = 0;
665 goto done;
666
594 case JXL_DEC_ERROR: 667 case JXL_DEC_ERROR:
595 error = "JxlDecoderProcessInput failed"; 668 error = "JxlDecoderProcessInput failed";
596 goto done; 669 goto done;
597 670
598 case JXL_DEC_NEED_MORE_INPUT: 671 case JXL_DEC_NEED_MORE_INPUT:
599 error = "incomplete file"; 672 error = "incomplete file";
600 goto done; 673 goto done;
601 674
602 case JXL_DEC_SUCCESS: 675 case JXL_DEC_SUCCESS:
676 error = "incomplete decode";
603 goto done; 677 goto done;
604 678
605 case JXL_DEC_NEED_IMAGE_OUT_BUFFER: 679 case JXL_DEC_BASIC_INFO:
606 { 680 {
681 status = JxlDecoderGetBasicInfo (dec, &info);
607 error = "JxlDecoderGetBasicInfo failed"; 682 error = "JxlDecoderGetBasicInfo failed";
608 if (JxlDecoderGetBasicInfo (dec, &info) != JXL_DEC_SUCCESS) 683 if (status != JXL_DEC_SUCCESS)
609 goto done; 684 goto done;
610 685
611 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!info.alpha_bits, 8, info.xsize, info.ysize); 686 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!info.alpha_bits, 8, info.xsize, info.ysize);
612 error = "unable to allocate pixbuf"; 687 error = "unable to allocate pixbuf";
613 if (!RETVAL) 688 if (!RETVAL)
618 JXL_TYPE_UINT8, 693 JXL_TYPE_UINT8,
619 JXL_NATIVE_ENDIAN, 694 JXL_NATIVE_ENDIAN,
620 gdk_pixbuf_get_rowstride (RETVAL) 695 gdk_pixbuf_get_rowstride (RETVAL)
621 }; 696 };
622 697
698 // cannot use gdk_pixbuf_get_byte_length because that does
699 // not return the size of the buffer, but the size of the buffer without
700 // the last padding bytes. the internal buffer is rowstride * ysize,
701 // and this is what the jxl decoder needs. none of this is documented
702 // in either library, of course.
703
704 status = JxlDecoderSetImageOutBuffer (
705 dec,
706 &format,
707 gdk_pixbuf_get_pixels (RETVAL),
708 gdk_pixbuf_get_rowstride (RETVAL) * info.ysize
709 );
623 error = "JxlDecoderSetImageOutBuffer failed"; 710 error = "JxlDecoderSetImageOutBuffer failed";
624 if (JxlDecoderSetImageOutBuffer (
625 dec,
626 &format,
627 gdk_pixbuf_get_pixels (RETVAL),
628 gdk_pixbuf_get_byte_length (RETVAL)
629 ) != JXL_DEC_SUCCESS) 711 if (status != JXL_DEC_SUCCESS)
630 goto done; 712 goto done;
631 } 713 }
632 break; 714 break;
633 715
634 default: 716 default:
639 721
640 done: 722 done:
641 if (dec) 723 if (dec)
642 JxlDecoderDestroy (dec); 724 JxlDecoderDestroy (dec);
643 725
726 perlinterp_acquire ();
727
644 if (runner) 728 if (runner_cache)
645 JxlThreadParallelRunnerDestroy (runner); 729 JxlThreadParallelRunnerDestroy (runner);
646 730
647 perlinterp_acquire (); 731 runner_cache = runner;
648 732
649 if (error) 733 if (error)
650 { 734 {
651 if (RETVAL) 735 if (RETVAL)
652 g_object_unref (RETVAL); 736 g_object_unref (RETVAL);
653 737
654 croak ("load_jxl: %s", error); 738 croak ("load_jxl: %s (status %d)", error, status);
655 } 739 }
656#else 740#else
657 croak ("load_jxl: jpeg-xl not enabled at compile time"); 741 croak ("load_jxl: jpeg-xl not enabled at compile time");
658#endif 742#endif
659} 743}
851 CODE: 935 CODE:
852{ 936{
853 STRLEN plen; 937 STRLEN plen;
854 U8 *path = (U8 *)SvPV (pathsv, plen); 938 U8 *path = (U8 *)SvPV (pathsv, plen);
855 U8 *pend = path + plen; 939 U8 *pend = path + plen;
856 U8 dst [plen * 6 * 3], *dstp = dst; 940 U8 dst [plen * 8 * 3], *dstp = dst;
857 941
858 while (path < pend) 942 while (path < pend)
859 { 943 {
860 U8 ch = *path; 944 U8 ch = *path;
861 945
863 *dstp++ = *path++; 947 *dstp++ = *path++;
864 else if (ch >= 'A' && ch <= 'Z') 948 else if (ch >= 'A' && ch <= 'Z')
865 *dstp++ = *path++ + ('a' - 'A'); 949 *dstp++ = *path++ + ('a' - 'A');
866 else if (ch >= '0' && ch <= '9') 950 else if (ch >= '0' && ch <= '9')
867 { 951 {
952 /* version sort, up to 8 digits */
868 STRLEN el, nl = 0; 953 STRLEN el, nl = 0;
869 while (*path >= '0' && *path <= '9' && path < pend) 954 while (*path >= '0' && *path <= '9' && path < pend)
870 path++, nl++; 955 path++, nl++;
871 956
872 for (el = nl; el < 6; el++) 957 for (el = nl; el < 8; el++)
873 *dstp++ = '0'; 958 *dstp++ = '0';
874 959
875 memcpy (dstp, path - nl, nl); 960 memcpy (dstp, path - nl, nl);
876 dstp += nl; 961 dstp += nl;
877 } 962 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines