Skip to content

Commit

Permalink
Move avifIsAlpha() to internal.h
Browse files Browse the repository at this point in the history
  • Loading branch information
y-guyon committed Mar 15, 2024
1 parent c783651 commit ebf311e
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 27 deletions.
5 changes: 5 additions & 0 deletions include/avif/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ void avifImageCopyNoAlloc(avifImage * dstImage, const avifImage * srcImage);
// Ignores the gainMap field (which exists only if AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP is defined).
void avifImageCopySamples(avifImage * dstImage, const avifImage * srcImage, avifPlanesFlags planes);

// ---------------------------------------------------------------------------
// Alpha

typedef struct avifAlphaParams
{
uint32_t width;
Expand Down Expand Up @@ -321,6 +324,8 @@ typedef enum avifItemCategory
AVIF_ITEM_CATEGORY_COUNT
} avifItemCategory;

avifBool avifIsAlpha(avifItemCategory itemCategory);

// ---------------------------------------------------------------------------

#if defined(AVIF_ENABLE_EXPERIMENTAL_AVIR)
Expand Down
10 changes: 10 additions & 0 deletions src/avif.c
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,16 @@ avifBool avifCleanApertureBoxConvertCropRect(avifCleanApertureBox * clap,

// ---------------------------------------------------------------------------

avifBool avifIsAlpha(avifItemCategory itemCategory)
{
if (itemCategory == AVIF_ITEM_ALPHA) {
return AVIF_TRUE;
}
return AVIF_FALSE;
}

// ---------------------------------------------------------------------------

avifBool avifAreGridDimensionsValid(avifPixelFormat yuvFormat, uint32_t imageW, uint32_t imageH, uint32_t tileW, uint32_t tileH, avifDiagnostics * diag)
{
// ISO/IEC 23000-22:2019, Section 7.3.11.4.2:
Expand Down
21 changes: 10 additions & 11 deletions src/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -1523,7 +1523,7 @@ static avifResult avifDecoderDataAllocateGridImagePlanes(avifDecoderData * data,
return AVIF_RESULT_INVALID_IMAGE_GRID;
}

avifBool alpha = (tile->input->itemCategory == AVIF_ITEM_ALPHA);
const avifBool alpha = avifIsAlpha(tile->input->itemCategory);
if (alpha) {
// An alpha tile does not contain any YUV pixels.
AVIF_ASSERT_OR_RETURN(tile->image->yuvFormat == AVIF_PIXEL_FORMAT_NONE);
Expand Down Expand Up @@ -1618,8 +1618,7 @@ static avifResult avifDecoderDataCopyTileToImage(avifDecoderData * data,
#endif
AVIF_ASSERT_OR_RETURN(avifImageSetViewRect(&dstView, dst, &dstViewRect) == AVIF_RESULT_OK &&
avifImageSetViewRect(&srcView, tile->image, &srcViewRect) == AVIF_RESULT_OK);
avifImageCopySamples(&dstView, &srcView, (tile->input->itemCategory == AVIF_ITEM_ALPHA) ? AVIF_PLANES_A : AVIF_PLANES_YUV);

avifImageCopySamples(&dstView, &srcView, avifIsAlpha(tile->input->itemCategory) ? AVIF_PLANES_A : AVIF_PLANES_YUV);
return AVIF_RESULT_OK;
}

Expand Down Expand Up @@ -4968,7 +4967,7 @@ avifResult avifDecoderReset(avifDecoder * decoder)
continue;
}
#endif
if (c == AVIF_ITEM_ALPHA && !mainItems[c]->width && !mainItems[c]->height) {
if (avifIsAlpha(c) && !mainItems[c]->width && !mainItems[c]->height) {
// NON-STANDARD: Alpha subimage does not have an ispe property; adopt width/height from color item
AVIF_ASSERT_OR_RETURN(!(decoder->strictFlags & AVIF_STRICT_ALPHA_ISPE_REQUIRED));
mainItems[c]->width = mainItems[AVIF_ITEM_COLOR]->width;
Expand All @@ -4978,7 +4977,7 @@ avifResult avifDecoderReset(avifDecoder * decoder)
AVIF_CHECKRES(avifDecoderGenerateImageTiles(decoder, &data->tileInfos[c], mainItems[c], c));

avifStrictFlags strictFlags = decoder->strictFlags;
if (c == AVIF_ITEM_ALPHA && !isAlphaItemInInput) {
if (avifIsAlpha(c) && !isAlphaItemInInput) {
// In this case, the made up grid item will not have an associated pixi property. So validate everything else
// but the pixi property.
strictFlags &= ~AVIF_STRICT_PIXI_REQUIRED;
Expand All @@ -4989,7 +4988,7 @@ avifResult avifDecoderReset(avifDecoder * decoder)

if (mainItems[AVIF_ITEM_COLOR]->progressive) {
decoder->progressiveState = AVIF_PROGRESSIVE_STATE_AVAILABLE;
// data->color.firstTileIndex is not yet defined but will be set to 0 a few lines below.
// data->tileInfos[AVIF_ITEM_COLOR].firstTileIndex is not yet defined but will be set to 0 a few lines below.
const avifTile * colorTile = &data->tiles.tile[0];
if (colorTile->input->samples.count > 1) {
decoder->progressiveState = AVIF_PROGRESSIVE_STATE_ACTIVE;
Expand Down Expand Up @@ -5184,7 +5183,7 @@ static avifResult avifGetErrorForItemCategory(avifItemCategory itemCategory)
return AVIF_RESULT_DECODE_GAIN_MAP_FAILED;
}
#endif
return (itemCategory == AVIF_ITEM_ALPHA) ? AVIF_RESULT_DECODE_ALPHA_FAILED : AVIF_RESULT_DECODE_COLOR_FAILED;
return avifIsAlpha(itemCategory) ? AVIF_RESULT_DECODE_ALPHA_FAILED : AVIF_RESULT_DECODE_COLOR_FAILED;
}

static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextImageIndex, avifTileInfo * info)
Expand All @@ -5201,7 +5200,7 @@ static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextIma
}

avifBool isLimitedRangeAlpha = AVIF_FALSE;
if (!tile->codec->getNextImage(tile->codec, decoder, sample, tile->input->itemCategory == AVIF_ITEM_ALPHA, &isLimitedRangeAlpha, tile->image)) {
if (!tile->codec->getNextImage(tile->codec, decoder, sample, avifIsAlpha(tile->input->itemCategory), &isLimitedRangeAlpha, tile->image)) {
avifDiagnosticsPrintf(&decoder->diag, "tile->codec->getNextImage() failed");
return avifGetErrorForItemCategory(tile->input->itemCategory);
}
Expand Down Expand Up @@ -5229,7 +5228,7 @@ static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextIma
// of the specification. However, it was allowed in version 1.0.0 of the
// specification. To allow such files, simply convert the alpha plane to
// full range.
if ((tile->input->itemCategory == AVIF_ITEM_ALPHA) && isLimitedRangeAlpha) {
if (avifIsAlpha(tile->input->itemCategory) && isLimitedRangeAlpha) {
avifResult result = avifImageLimitedToFullAlpha(tile->image);
if (result != AVIF_RESULT_OK) {
avifDiagnosticsPrintf(&decoder->diag, "avifImageLimitedToFullAlpha failed");
Expand Down Expand Up @@ -5281,7 +5280,7 @@ static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextIma
default:
if ((decoder->image->width != src->width) || (decoder->image->height != src->height) ||
(decoder->image->depth != src->depth)) {
if (tile->input->itemCategory == AVIF_ITEM_ALPHA) {
if (avifIsAlpha(tile->input->itemCategory)) {
avifDiagnosticsPrintf(&decoder->diag,
"The color image item does not match the alpha image item in width, height, or bit depth");
return AVIF_RESULT_DECODE_ALPHA_FAILED;
Expand All @@ -5295,7 +5294,7 @@ static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextIma
break;
}

if (tile->input->itemCategory == AVIF_ITEM_ALPHA) {
if (avifIsAlpha(tile->input->itemCategory)) {
avifImageStealPlanes(decoder->image, src, AVIF_PLANES_A);
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
} else if (tile->input->itemCategory == AVIF_ITEM_GAIN_MAP) {
Expand Down
41 changes: 25 additions & 16 deletions src/write.c
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,7 @@ static avifResult avifEncoderAddImageItems(avifEncoder * encoder,
uint16_t * topLevelItemID)
{
const uint32_t cellCount = gridCols * gridRows;
const char * infeName = (itemCategory == AVIF_ITEM_ALPHA) ? infeNameAlpha
const char * infeName = avifIsAlpha(itemCategory) ? infeNameAlpha
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
: (itemCategory == AVIF_ITEM_GAIN_MAP) ? infeNameGainMap
#endif
Expand Down Expand Up @@ -1192,7 +1192,12 @@ static avifBool avifEncoderDataShouldForceKeyframeForAlpha(const avifEncoderData

static avifResult avifGetErrorForItemCategory(avifItemCategory itemCategory)
{
return (itemCategory == AVIF_ITEM_ALPHA) ? AVIF_RESULT_ENCODE_ALPHA_FAILED : AVIF_RESULT_ENCODE_COLOR_FAILED;
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
if (itemCategory == AVIF_ITEM_GAIN_MAP) {
return AVIF_RESULT_ENCODE_GAIN_MAP_FAILED;
}
#endif
return avifIsAlpha(itemCategory) ? AVIF_RESULT_ENCODE_ALPHA_FAILED : AVIF_RESULT_ENCODE_COLOR_FAILED;
}

static avifResult avifValidateImageBasicProperties(const avifImage * avifImage)
Expand Down Expand Up @@ -1662,18 +1667,20 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder,
}
cellImage = paddedCellImage;
}
const int quantizer = (item->itemCategory == AVIF_ITEM_ALPHA) ? encoder->data->quantizerAlpha

const avifBool isAlpha = avifIsAlpha(item->itemCategory);
int quantizer = isAlpha ? encoder->data->quantizerAlpha
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
: (item->itemCategory == AVIF_ITEM_GAIN_MAP) ? encoder->data->quantizerGainMap
: (item->itemCategory == AVIF_ITEM_GAIN_MAP) ? encoder->data->quantizerGainMap
#endif
: encoder->data->quantizer;
: encoder->data->quantizer;
// If alpha channel is present, set disableLaggedOutput to AVIF_TRUE. If the encoder supports it, this enables
// avifEncoderDataShouldForceKeyframeForAlpha to force a keyframe in the alpha channel whenever a keyframe has been
// encoded in the color channel for animated images.
avifResult encodeResult = item->codec->encodeImage(item->codec,
encoder,
cellImage,
item->itemCategory == AVIF_ITEM_ALPHA,
isAlpha,
encoder->data->tileRowsLog2,
encoder->data->tileColsLog2,
quantizer,
Expand Down Expand Up @@ -1780,10 +1787,12 @@ static avifResult avifEncoderWriteMediaDataBox(avifEncoder * encoder,
// only process metadata (XMP/Exif) payloads when metadataPass is true
continue;
}
avifBool isAlphaOrGainMap = item->itemCategory == AVIF_ITEM_ALPHA;
const avifBool isAlpha = avifIsAlpha(item->itemCategory);
const avifBool isAlphaOrGainMap = isAlpha
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
isAlphaOrGainMap = isAlphaOrGainMap || item->itemCategory == AVIF_ITEM_GAIN_MAP;
|| item->itemCategory == AVIF_ITEM_GAIN_MAP
#endif
;
if (alphaAndGainMapPass != isAlphaOrGainMap) {
// only process alpha payloads when alphaPass is true
continue;
Expand All @@ -1794,8 +1803,7 @@ static avifResult avifEncoderWriteMediaDataBox(avifEncoder * encoder,
// We always interleave all AV1 items for layered images.
AVIF_ASSERT_OR_RETURN(item->encodeOutput->samples.count == item->mdatFixups.count);

avifEncoderItemReference * ref = (item->itemCategory == AVIF_ITEM_ALPHA) ? avifArrayPush(layeredAlphaItems)
: avifArrayPush(layeredColorItems);
avifEncoderItemReference * ref = avifArrayPush(isAlpha ? layeredAlphaItems : layeredColorItems);
AVIF_CHECKERR(ref != NULL, AVIF_RESULT_OUT_OF_MEMORY);
*ref = item;
continue;
Expand All @@ -1820,7 +1828,7 @@ static avifResult avifEncoderWriteMediaDataBox(avifEncoder * encoder,
avifEncodeSample * sample = &item->encodeOutput->samples.sample[sampleIndex];
AVIF_CHECKRES(avifRWStreamWrite(s, sample->data.data, sample->data.size));

if (item->itemCategory == AVIF_ITEM_ALPHA) {
if (isAlpha) {
encoder->ioStats.alphaOBUSize += sample->data.size;
} else if (item->itemCategory == AVIF_ITEM_COLOR) {
encoder->ioStats.colorOBUSize += sample->data.size;
Expand Down Expand Up @@ -2254,7 +2262,7 @@ static avifResult avifRWStreamWriteProperties(avifItemPropertyDedup * const dedu
imageHeight = item->gridHeight;
}

// Properties all image items need
// Properties all image items need (coded and derived)
// ispe = image spatial extent (width, height)
avifItemPropertyDedupStart(dedup);
avifBoxMarker ispe;
Expand All @@ -2272,15 +2280,16 @@ static avifResult avifRWStreamWriteProperties(avifItemPropertyDedup * const dedu
hasPixi = AVIF_FALSE;
}
#endif
const avifBool isAlpha = avifIsAlpha(item->itemCategory);
uint8_t depth = (uint8_t)itemMetadata->depth;
if (hasPixi) {
avifItemPropertyDedupStart(dedup);
uint8_t channelCount =
(item->itemCategory == AVIF_ITEM_ALPHA || (itemMetadata->yuvFormat == AVIF_PIXEL_FORMAT_YUV400)) ? 1 : 3;
uint8_t channelCount = (isAlpha || (itemMetadata->yuvFormat == AVIF_PIXEL_FORMAT_YUV400)) ? 1 : 3;
avifBoxMarker pixi;
AVIF_CHECKRES(avifRWStreamWriteFullBox(&dedup->s, "pixi", AVIF_BOX_SIZE_TBD, 0, 0, &pixi));
AVIF_CHECKRES(avifRWStreamWriteU8(&dedup->s, channelCount)); // unsigned int (8) num_channels;
for (uint8_t chan = 0; chan < channelCount; ++chan) {
AVIF_CHECKRES(avifRWStreamWriteU8(&dedup->s, (uint8_t)itemMetadata->depth)); // unsigned int (8) bits_per_channel;
AVIF_CHECKRES(avifRWStreamWriteU8(&dedup->s, depth)); // unsigned int (8) bits_per_channel;
}
avifRWStreamFinishBox(&dedup->s, pixi);
AVIF_CHECKRES(avifItemPropertyDedupFinish(dedup, s, &item->ipma, AVIF_FALSE));
Expand All @@ -2293,7 +2302,7 @@ static avifResult avifRWStreamWriteProperties(avifItemPropertyDedup * const dedu
AVIF_CHECKRES(avifItemPropertyDedupFinish(dedup, s, &item->ipma, AVIF_TRUE));
}

if (item->itemCategory == AVIF_ITEM_ALPHA) {
if (isAlpha) {
// Alpha specific properties

avifItemPropertyDedupStart(dedup);
Expand Down

0 comments on commit ebf311e

Please sign in to comment.