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.64 by root, Wed Dec 1 03:32:40 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;
561 void *runner = 0; 594 void *runner = 0;
562 struct bmff_box box; 595
596 RETVAL = 0;
563 597
564 perlinterp_release (); 598 perlinterp_release ();
565 599
566 RETVAL = 0; 600 dec = JxlDecoderCreate (0);
567 601
568 error = "JxlDecoderCreate failed"; 602 error = "JxlDecoderCreate failed";
569 if (!dec) 603 if (!dec)
570 goto done; 604 goto done;
571 605
572 runner = JxlThreadParallelRunnerCreate (0, JxlThreadParallelRunnerDefaultNumWorkerThreads ()); 606 runner = JxlThreadParallelRunnerCreate (0, JxlThreadParallelRunnerDefaultNumWorkerThreads ());
573 607
608 status = JxlDecoderSetParallelRunner (dec, JxlThreadParallelRunner, runner);
574 error = "JxlDecoderSetParallelRunner failed"; 609 error = "JxlDecoderSetParallelRunner failed";
575 if (JxlDecoderSetParallelRunner (dec, JxlThreadParallelRunner, runner) != JXL_DEC_SUCCESS) 610 if (status != JXL_DEC_SUCCESS)
576 goto done; 611 goto done;
577 612
578 error = "JxlDecoderSubscribeEvents failed"; 613 error = "JxlDecoderSubscribeEvents failed";
579 if (JxlDecoderSubscribeEvents (dec, JXL_DEC_FULL_IMAGE | JXL_DEC_BASIC_INFO) != JXL_DEC_SUCCESS) 614 status = JxlDecoderSubscribeEvents (dec, JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE);
615 if (status != JXL_DEC_SUCCESS)
580 goto done; 616 goto done;
581 617
618 status = JxlDecoderSetInput (dec, next_in, avail_in);
582 error = "JxlDecoderSetInput failed"; 619 error = "JxlDecoderSetInput failed";
583 if (JxlDecoderSetInput (dec, next_in, avail_in) != JXL_DEC_SUCCESS) 620 if (status != JXL_DEC_SUCCESS)
584 goto done; 621 goto done;
585 622
586 for (;;) 623 for (;;)
587 { 624 {
588 JxlDecoderStatus status = JxlDecoderProcessInput (dec); 625 status = JxlDecoderProcessInput (dec);
589 626
590 printf ("status %d\n",status);
591
592 switch (status) 627 switch (status)
593 { 628 {
629 case JXL_DEC_FULL_IMAGE:
630 error = 0;
631 goto done;
632
594 case JXL_DEC_ERROR: 633 case JXL_DEC_ERROR:
595 error = "JxlDecoderProcessInput failed"; 634 error = "JxlDecoderProcessInput failed";
596 goto done; 635 goto done;
597 636
598 case JXL_DEC_NEED_MORE_INPUT: 637 case JXL_DEC_NEED_MORE_INPUT:
599 error = "incomplete file"; 638 error = "incomplete file";
600 goto done; 639 goto done;
601 640
602 case JXL_DEC_SUCCESS: 641 case JXL_DEC_SUCCESS:
642 error = "incomplete decode";
603 goto done; 643 goto done;
604 644
605 case JXL_DEC_NEED_IMAGE_OUT_BUFFER: 645 case JXL_DEC_BASIC_INFO:
606 { 646 {
647 status = JxlDecoderGetBasicInfo (dec, &info);
607 error = "JxlDecoderGetBasicInfo failed"; 648 error = "JxlDecoderGetBasicInfo failed";
608 if (JxlDecoderGetBasicInfo (dec, &info) != JXL_DEC_SUCCESS) 649 if (status != JXL_DEC_SUCCESS)
609 goto done; 650 goto done;
610 651
611 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!info.alpha_bits, 8, info.xsize, info.ysize); 652 RETVAL = gdk_pixbuf_new (GDK_COLORSPACE_RGB, !!info.alpha_bits, 8, info.xsize, info.ysize);
612 error = "unable to allocate pixbuf"; 653 error = "unable to allocate pixbuf";
613 if (!RETVAL) 654 if (!RETVAL)
618 JXL_TYPE_UINT8, 659 JXL_TYPE_UINT8,
619 JXL_NATIVE_ENDIAN, 660 JXL_NATIVE_ENDIAN,
620 gdk_pixbuf_get_rowstride (RETVAL) 661 gdk_pixbuf_get_rowstride (RETVAL)
621 }; 662 };
622 663
664 // cannot use gdk_pixbuf_get_byte_length because that does
665 // not return the size of the buffer, but the size of the buffer without
666 // the last padding bytes. the internal buffer is rowstride * ysize,
667 // and this is what the jxl decoder needs. none of this is documented
668 // in either library, of course.
669
670 status = JxlDecoderSetImageOutBuffer (
671 dec,
672 &format,
673 gdk_pixbuf_get_pixels (RETVAL),
674 gdk_pixbuf_get_rowstride (RETVAL) * info.ysize
675 );
623 error = "JxlDecoderSetImageOutBuffer failed"; 676 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) 677 if (status != JXL_DEC_SUCCESS)
630 goto done; 678 goto done;
631 } 679 }
632 break; 680 break;
633 681
634 default: 682 default:
649 if (error) 697 if (error)
650 { 698 {
651 if (RETVAL) 699 if (RETVAL)
652 g_object_unref (RETVAL); 700 g_object_unref (RETVAL);
653 701
654 croak ("load_jxl: %s", error); 702 croak ("load_jxl: %s (status %d)", error, status);
655 } 703 }
656#else 704#else
657 croak ("load_jxl: jpeg-xl not enabled at compile time"); 705 croak ("load_jxl: jpeg-xl not enabled at compile time");
658#endif 706#endif
659} 707}
851 CODE: 899 CODE:
852{ 900{
853 STRLEN plen; 901 STRLEN plen;
854 U8 *path = (U8 *)SvPV (pathsv, plen); 902 U8 *path = (U8 *)SvPV (pathsv, plen);
855 U8 *pend = path + plen; 903 U8 *pend = path + plen;
856 U8 dst [plen * 6 * 3], *dstp = dst; 904 U8 dst [plen * 8 * 3], *dstp = dst;
857 905
858 while (path < pend) 906 while (path < pend)
859 { 907 {
860 U8 ch = *path; 908 U8 ch = *path;
861 909
863 *dstp++ = *path++; 911 *dstp++ = *path++;
864 else if (ch >= 'A' && ch <= 'Z') 912 else if (ch >= 'A' && ch <= 'Z')
865 *dstp++ = *path++ + ('a' - 'A'); 913 *dstp++ = *path++ + ('a' - 'A');
866 else if (ch >= '0' && ch <= '9') 914 else if (ch >= '0' && ch <= '9')
867 { 915 {
916 /* version sort, up to 8 digits */
868 STRLEN el, nl = 0; 917 STRLEN el, nl = 0;
869 while (*path >= '0' && *path <= '9' && path < pend) 918 while (*path >= '0' && *path <= '9' && path < pend)
870 path++, nl++; 919 path++, nl++;
871 920
872 for (el = nl; el < 6; el++) 921 for (el = nl; el < 8; el++)
873 *dstp++ = '0'; 922 *dstp++ = '0';
874 923
875 memcpy (dstp, path - nl, nl); 924 memcpy (dstp, path - nl, nl);
876 dstp += nl; 925 dstp += nl;
877 } 926 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines