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.65 by root, Thu Dec 2 03:11:45 2021 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines