@@ -444,8 +444,11 @@ bool GrkImage::isOpacity(uint16_t compno) const
444444}
445445bool GrkImage::isPostProcessNoOp (void ) const
446446{
447- // applyColour: palette or channel_definition requires processing
448- if (meta && (meta->color .palette || meta->color .channel_definition ))
447+ // applyColour: palette requires processing; channel_definition only blocks
448+ // if it needs component data swaps (type-only metadata is applied early)
449+ if (meta && meta->color .palette )
450+ return false ;
451+ if (needsChannelDefinitionSwap ())
449452 return false ;
450453 // applyColourManagement: ICC profile that must be applied
451454 if (meta && meta->color .icc_profile_buf )
@@ -504,6 +507,11 @@ bool GrkImage::isPostProcessNoOp(void) const
504507}
505508void GrkImage::postReadHeader (CodingParams* cp)
506509{
510+ // Apply channel definition types (e.g. alpha) early so format writers
511+ // can emit correct metadata (TIFF EXTRASAMPLES, etc.) before strip-based
512+ // decompress starts. Component data swaps are deferred to postProcess.
513+ applyChannelDefinitionTypes ();
514+
507515 uint8_t prec = comps[0 ].prec ;
508516 if (precision)
509517 prec = precision->prec ;
@@ -596,6 +604,44 @@ void GrkImage::allocPalette(uint8_t num_channels, uint16_t num_entries)
596604 ((GrkImageMeta*)meta)->allocPalette (num_channels, num_entries);
597605}
598606
607+ bool GrkImage::needsChannelDefinitionSwap () const
608+ {
609+ if (!meta || !meta->color .channel_definition )
610+ return false ;
611+ auto info = meta->color .channel_definition ->descriptions ;
612+ uint16_t n = meta->color .channel_definition ->num_channel_descriptions ;
613+ for (uint16_t i = 0 ; i < n; ++i)
614+ {
615+ if (info[i].typ != GRK_CHANNEL_TYPE_COLOUR)
616+ continue ;
617+ if (info[i].asoc == GRK_CHANNEL_ASSOC_WHOLE_IMAGE)
618+ continue ;
619+ uint16_t channel = info[i].channel ;
620+ uint16_t asoc = info[i].asoc ;
621+ if (channel >= numcomps || asoc > numcomps)
622+ continue ;
623+ uint16_t asoc_index = (uint16_t )(asoc - 1 );
624+ if (channel != asoc_index)
625+ return true ;
626+ }
627+ return false ;
628+ }
629+
630+ void GrkImage::applyChannelDefinitionTypes ()
631+ {
632+ if (!meta || !meta->color .channel_definition )
633+ return ;
634+ auto info = meta->color .channel_definition ->descriptions ;
635+ uint16_t n = meta->color .channel_definition ->num_channel_descriptions ;
636+ for (uint16_t i = 0 ; i < n; ++i)
637+ {
638+ uint16_t channel = info[i].channel ;
639+ if (channel >= numcomps)
640+ continue ;
641+ comps[channel].type = (GRK_CHANNEL_TYPE)info[i].typ ;
642+ }
643+ }
644+
599645void GrkImage::apply_channel_definition ()
600646{
601647 if (channel_definition_applied)
0 commit comments