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.66 by root, Tue Mar 21 00:06:49 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
456 else 491 else
457 XSRETURN_UNDEF; 492 XSRETURN_UNDEF;
458} 493}
459 OUTPUT: 494 OUTPUT:
460 RETVAL 495 RETVAL
551GdkPixbuf_noinc * 586GdkPixbuf_noinc *
552decode_jxl (SV *image_data, int thumbnail = 0, int iw = 0, int ih = 0) 587decode_jxl (SV *image_data, int thumbnail = 0, int iw = 0, int ih = 0)
553 CODE: 588 CODE:
554{ 589{
555#if JXL 590#if JXL
556 JxlDecoder *dec = JxlDecoderCreate (0); 591 JxlDecoder *dec;
557 JxlBasicInfo info; 592 JxlBasicInfo info;
558 const uint8_t *next_in = (uint8_t *)SvPVbyte_nolen (image_data); 593 const uint8_t *next_in = (uint8_t *)SvPVbyte_nolen (image_data);
559 size_t avail_in = SvCUR (image_data); 594 size_t avail_in = SvCUR (image_data);
560 const char *error = 0; 595 const char *error = 0;
596 JxlDecoderStatus status;
597 static void *runner_cache;
561 void *runner = 0; 598 void *runner = 0;
562 struct bmff_box box; 599
600 RETVAL = 0;
601
602 if (runner_cache)
603 runner = runner_cache;
604 else
605 runner = JxlThreadParallelRunnerCreate (0, JxlThreadParallelRunnerDefaultNumWorkerThreads ());
606
607 runner_cache = 0;
563 608
564 perlinterp_release (); 609 perlinterp_release ();
565 610
566 RETVAL = 0; 611 dec = JxlDecoderCreate (0);
567 612
568 error = "JxlDecoderCreate failed"; 613 error = "JxlDecoderCreate failed";
569 if (!dec) 614 if (!dec)
570 goto done; 615 goto done;
571 616
572 runner = JxlThreadParallelRunnerCreate (0, JxlThreadParallelRunnerDefaultNumWorkerThreads ()); 617 status = JxlDecoderSetParallelRunner (dec, JxlThreadParallelRunner, runner);
573
574 error = "JxlDecoderSetParallelRunner failed"; 618 error = "JxlDecoderSetParallelRunner failed";
575 if (JxlDecoderSetParallelRunner (dec, JxlThreadParallelRunner, runner) != JXL_DEC_SUCCESS) 619 if (status != JXL_DEC_SUCCESS)
576 goto done; 620 goto done;
577 621
578 error = "JxlDecoderSubscribeEvents failed"; 622 error = "JxlDecoderSubscribeEvents failed";
579 if (JxlDecoderSubscribeEvents (dec, JXL_DEC_FULL_IMAGE | JXL_DEC_BASIC_INFO) != JXL_DEC_SUCCESS) 623 status = JxlDecoderSubscribeEvents (dec, JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE);
624 if (status != JXL_DEC_SUCCESS)
580 goto done; 625 goto done;
581 626
627 status = JxlDecoderSetInput (dec, next_in, avail_in);
582 error = "JxlDecoderSetInput failed"; 628 error = "JxlDecoderSetInput failed";
583 if (JxlDecoderSetInput (dec, next_in, avail_in) != JXL_DEC_SUCCESS) 629 if (status != JXL_DEC_SUCCESS)
584 goto done; 630 goto done;
585 631
586 for (;;) 632 for (;;)
587 { 633 {
588 JxlDecoderStatus status = JxlDecoderProcessInput (dec); 634 status = JxlDecoderProcessInput (dec);
589 635
590 printf ("status %d\n",status);
591
592 switch (status) 636 switch (status)
593 { 637 {
638 case JXL_DEC_FULL_IMAGE:
639 error = 0;
640 goto done;
641
594 case JXL_DEC_ERROR: 642 case JXL_DEC_ERROR:
595 error = "JxlDecoderProcessInput failed"; 643 error = "JxlDecoderProcessInput failed";
596 goto done; 644 goto done;
597 645
598 case JXL_DEC_NEED_MORE_INPUT: 646 case JXL_DEC_NEED_MORE_INPUT:
599 error = "incomplete file"; 647 error = "incomplete file";
600 goto done; 648 goto done;
601 649
602 case JXL_DEC_SUCCESS: 650 case JXL_DEC_SUCCESS:
651 error = "incomplete decode";
603 goto done; 652 goto done;
604 653
605 case JXL_DEC_NEED_IMAGE_OUT_BUFFER: 654 case JXL_DEC_BASIC_INFO:
606 { 655 {
656 status = JxlDecoderGetBasicInfo (dec, &info);
607 error = "JxlDecoderGetBasicInfo failed"; 657 error = "JxlDecoderGetBasicInfo failed";
608 if (JxlDecoderGetBasicInfo (dec, &info) != JXL_DEC_SUCCESS) 658 if (status != JXL_DEC_SUCCESS)
609 goto done; 659 goto done;
610 660
611 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!info.alpha_bits, 8, info.xsize, info.ysize); 661 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!info.alpha_bits, 8, info.xsize, info.ysize);
612 error = "unable to allocate pixbuf"; 662 error = "unable to allocate pixbuf";
613 if (!RETVAL) 663 if (!RETVAL)
618 JXL_TYPE_UINT8, 668 JXL_TYPE_UINT8,
619 JXL_NATIVE_ENDIAN, 669 JXL_NATIVE_ENDIAN,
620 gdk_pixbuf_get_rowstride (RETVAL) 670 gdk_pixbuf_get_rowstride (RETVAL)
621 }; 671 };
622 672
673 // cannot use gdk_pixbuf_get_byte_length because that does
674 // not return the size of the buffer, but the size of the buffer without
675 // the last padding bytes. the internal buffer is rowstride * ysize,
676 // and this is what the jxl decoder needs. none of this is documented
677 // in either library, of course.
678
679 status = JxlDecoderSetImageOutBuffer (
680 dec,
681 &format,
682 gdk_pixbuf_get_pixels (RETVAL),
683 gdk_pixbuf_get_rowstride (RETVAL) * info.ysize
684 );
623 error = "JxlDecoderSetImageOutBuffer failed"; 685 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) 686 if (status != JXL_DEC_SUCCESS)
630 goto done; 687 goto done;
631 } 688 }
632 break; 689 break;
633 690
634 default: 691 default:
639 696
640 done: 697 done:
641 if (dec) 698 if (dec)
642 JxlDecoderDestroy (dec); 699 JxlDecoderDestroy (dec);
643 700
701 perlinterp_acquire ();
702
644 if (runner) 703 if (runner_cache)
645 JxlThreadParallelRunnerDestroy (runner); 704 JxlThreadParallelRunnerDestroy (runner);
646 705
647 perlinterp_acquire (); 706 runner_cache = runner;
648 707
649 if (error) 708 if (error)
650 { 709 {
651 if (RETVAL) 710 if (RETVAL)
652 g_object_unref (RETVAL); 711 g_object_unref (RETVAL);
653 712
654 croak ("load_jxl: %s", error); 713 croak ("load_jxl: %s (status %d)", error, status);
655 } 714 }
656#else 715#else
657 croak ("load_jxl: jpeg-xl not enabled at compile time"); 716 croak ("load_jxl: jpeg-xl not enabled at compile time");
658#endif 717#endif
659} 718}
851 CODE: 910 CODE:
852{ 911{
853 STRLEN plen; 912 STRLEN plen;
854 U8 *path = (U8 *)SvPV (pathsv, plen); 913 U8 *path = (U8 *)SvPV (pathsv, plen);
855 U8 *pend = path + plen; 914 U8 *pend = path + plen;
856 U8 dst [plen * 6 * 3], *dstp = dst; 915 U8 dst [plen * 8 * 3], *dstp = dst;
857 916
858 while (path < pend) 917 while (path < pend)
859 { 918 {
860 U8 ch = *path; 919 U8 ch = *path;
861 920
863 *dstp++ = *path++; 922 *dstp++ = *path++;
864 else if (ch >= 'A' && ch <= 'Z') 923 else if (ch >= 'A' && ch <= 'Z')
865 *dstp++ = *path++ + ('a' - 'A'); 924 *dstp++ = *path++ + ('a' - 'A');
866 else if (ch >= '0' && ch <= '9') 925 else if (ch >= '0' && ch <= '9')
867 { 926 {
927 /* version sort, up to 8 digits */
868 STRLEN el, nl = 0; 928 STRLEN el, nl = 0;
869 while (*path >= '0' && *path <= '9' && path < pend) 929 while (*path >= '0' && *path <= '9' && path < pend)
870 path++, nl++; 930 path++, nl++;
871 931
872 for (el = nl; el < 6; el++) 932 for (el = nl; el < 8; el++)
873 *dstp++ = '0'; 933 *dstp++ = '0';
874 934
875 memcpy (dstp, path - nl, nl); 935 memcpy (dstp, path - nl, nl);
876 dstp += nl; 936 dstp += nl;
877 } 937 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines