@@ -448,8 +448,10 @@ Dictionary ResourceImporterTexture::_load_editor_meta(const String &p_path) cons
448448}
449449
450450void ResourceImporterTexture::_remap_channels (Ref<Image> &r_image, ChannelRemap p_options[4 ]) {
451- bool attempted_hdr_inverted = false ;
451+ ERR_FAIL_COND (r_image-> is_compressed ()) ;
452452
453+ // Currently HDR inverted remapping is not allowed.
454+ bool attempted_hdr_inverted = false ;
453455 if (r_image->get_format () >= Image::FORMAT_RF && r_image->get_format () <= Image::FORMAT_RGBE9995) {
454456 // Formats which can hold HDR data cannot be inverted the same way as unsigned normalized ones (1.0 - channel).
455457 for (int i = 0 ; i < 4 ; i++) {
@@ -480,11 +482,127 @@ void ResourceImporterTexture::_remap_channels(Ref<Image> &r_image, ChannelRemap
480482 WARN_PRINT (" Attempted to use an inverted channel remap on an HDR image. The remap has been changed to its uninverted equivalent." );
481483 }
482484
483- if (p_options[0 ] == REMAP_R && p_options[1 ] == REMAP_G && p_options[2 ] == REMAP_B && p_options[3 ] == REMAP_A) {
485+ // Optimization: Set the remap from 'unused' to either 0 or 1 to avoid repeated checks in the conversion loop.
486+ for (int i = 0 ; i < 4 ; i++) {
487+ if (p_options[i] == REMAP_UNUSED) {
488+ p_options[i] = i == 3 ? REMAP_1 : REMAP_0;
489+ }
490+ }
491+
492+ // Expand the image's channel count in the event that the current set of channels doesn't allow for the desired remap.
493+ const Image::Format original_format = r_image->get_format ();
494+ const uint32_t channel_mask = Image::get_format_component_mask (original_format);
495+
496+ // Whether a channel is supported by the format itself.
497+ const bool has_channel_r = channel_mask & 0x1 ;
498+ const bool has_channel_g = channel_mask & 0x2 ;
499+ const bool has_channel_b = channel_mask & 0x4 ;
500+ const bool has_channel_a = channel_mask & 0x8 ;
501+
502+ // Whether a certain channel needs to be remapped.
503+ const bool remap_r = p_options[0 ] != REMAP_R ? !(!has_channel_r && p_options[0 ] == REMAP_0) : false ;
504+ const bool remap_g = p_options[1 ] != REMAP_G ? !(!has_channel_g && p_options[1 ] == REMAP_0) : false ;
505+ const bool remap_b = p_options[2 ] != REMAP_B ? !(!has_channel_b && p_options[2 ] == REMAP_0) : false ;
506+ const bool remap_a = p_options[3 ] != REMAP_A ? !(!has_channel_a && p_options[3 ] == REMAP_1) : false ;
507+
508+ if (!(remap_r || remap_g || remap_b || remap_a)) {
484509 // Default color map, do nothing.
485510 return ;
486511 }
487512
513+ // Whether a certain channel set is needed, either from the source or the remap.
514+ const bool needs_rg = remap_g || has_channel_g;
515+ const bool needs_rgb = remap_b || has_channel_b;
516+ const bool needs_rgba = remap_a || has_channel_a;
517+
518+ bool could_not_expand = false ;
519+ switch (original_format) {
520+ case Image::FORMAT_R8:
521+ case Image::FORMAT_RG8:
522+ case Image::FORMAT_RGB8: {
523+ // Convert to either RGBA8, RGB8 or RG8.
524+ if (needs_rgba) {
525+ r_image->convert (Image::FORMAT_RGBA8);
526+ } else if (needs_rgb) {
527+ r_image->convert (Image::FORMAT_RGB8);
528+ } else if (needs_rg) {
529+ r_image->convert (Image::FORMAT_RG8);
530+ }
531+ } break ;
532+ case Image::FORMAT_RH:
533+ case Image::FORMAT_RGH:
534+ case Image::FORMAT_RGBH: {
535+ // Convert to either RGBAH, RGBH or RGH.
536+ if (needs_rgba) {
537+ r_image->convert (Image::FORMAT_RGBAH);
538+ } else if (needs_rgb) {
539+ r_image->convert (Image::FORMAT_RGBH);
540+ } else if (needs_rg) {
541+ r_image->convert (Image::FORMAT_RGH);
542+ }
543+ } break ;
544+ case Image::FORMAT_RF:
545+ case Image::FORMAT_RGF:
546+ case Image::FORMAT_RGBF: {
547+ // Convert to either RGBAF, RGBF or RGF.
548+ if (needs_rgba) {
549+ r_image->convert (Image::FORMAT_RGBAF);
550+ } else if (needs_rgb) {
551+ r_image->convert (Image::FORMAT_RGBF);
552+ } else if (needs_rg) {
553+ r_image->convert (Image::FORMAT_RGF);
554+ }
555+ } break ;
556+ case Image::FORMAT_L8: {
557+ const bool uniform_rgb = (p_options[0 ] == p_options[1 ] && p_options[1 ] == p_options[2 ]) || !(remap_r || remap_g || remap_b);
558+ if (uniform_rgb) {
559+ // Uniform RGB.
560+ if (needs_rgba) {
561+ r_image->convert (Image::FORMAT_LA8);
562+ }
563+ } else {
564+ // Non-uniform RGB.
565+ if (needs_rgba) {
566+ r_image->convert (Image::FORMAT_RGBA8);
567+ } else {
568+ r_image->convert (Image::FORMAT_RGB8);
569+ }
570+ could_not_expand = true ;
571+ }
572+ } break ;
573+ case Image::FORMAT_LA8: {
574+ const bool uniform_rgb = (p_options[0 ] == p_options[1 ] && p_options[1 ] == p_options[2 ]) || !(remap_r || remap_g || remap_b);
575+ if (!uniform_rgb) {
576+ // Non-uniform RGB.
577+ r_image->convert (Image::FORMAT_RGBA8);
578+ could_not_expand = true ;
579+ }
580+ } break ;
581+ case Image::FORMAT_RGB565: {
582+ if (needs_rgba) {
583+ // RGB565 doesn't have an alpha expansion, convert to RGBA8.
584+ r_image->convert (Image::FORMAT_RGBA8);
585+ could_not_expand = true ;
586+ }
587+ } break ;
588+ case Image::FORMAT_RGBE9995: {
589+ if (needs_rgba) {
590+ // RGB9995 doesn't have an alpha expansion, convert to RGBAH.
591+ r_image->convert (Image::FORMAT_RGBAH);
592+ could_not_expand = true ;
593+ }
594+ } break ;
595+
596+ default : {
597+ } break ;
598+ }
599+
600+ if (could_not_expand) {
601+ WARN_PRINT (vformat (" Unable to expand image format %s's channels (the target format does not exist), converting to %s as a fallback." ,
602+ Image::get_format_name (original_format), Image::get_format_name (r_image->get_format ())));
603+ }
604+
605+ // Remap the channels.
488606 for (int x = 0 ; x < r_image->get_width (); x++) {
489607 for (int y = 0 ; y < r_image->get_height (); y++) {
490608 Color src = r_image->get_pixel (x, y);
@@ -518,11 +636,6 @@ void ResourceImporterTexture::_remap_channels(Ref<Image> &r_image, ChannelRemap
518636 dst[i] = 1 .0f - src.a ;
519637 break ;
520638
521- case REMAP_UNUSED:
522- // For Alpha the unused value is 1, for other channels it's 0.
523- dst[i] = (i == 3 ) ? 1 .0f : 0 .0f ;
524- break ;
525-
526639 case REMAP_0:
527640 dst[i] = 0 .0f ;
528641 break ;
0 commit comments